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 __x86_64__
70 #elif defined __aarch64__
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
151 winevent_hook_todo
=0x800
155 UINT message
; /* the WM_* code */
156 msg_flags_t flags
; /* message props */
157 WPARAM wParam
; /* expected value of wParam */
158 LPARAM lParam
; /* expected value of lParam */
159 WPARAM wp_mask
; /* mask for wParam checks */
160 LPARAM lp_mask
; /* mask for lParam checks */
163 struct recvd_message
{
164 UINT message
; /* the WM_* code */
165 msg_flags_t flags
; /* message props */
166 HWND hwnd
; /* window that received the message */
167 WPARAM wParam
; /* expected value of wParam */
168 LPARAM lParam
; /* expected value of lParam */
169 int line
; /* source line where logged */
170 const char *descr
; /* description for trace output */
171 char output
[512]; /* trace output */
174 /* Empty message sequence */
175 static const struct message WmEmptySeq
[] =
179 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
180 static const struct message WmCreateOverlappedSeq
[] = {
181 { HCBT_CREATEWND
, hook
},
182 { WM_GETMINMAXINFO
, sent
},
183 { WM_NCCREATE
, sent
},
184 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
185 { 0x0093, sent
|defwinproc
|optional
},
186 { 0x0094, sent
|defwinproc
|optional
},
187 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
189 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
192 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
193 * for a not visible overlapped window.
195 static const struct message WmSWP_ShowOverlappedSeq
[] = {
196 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
197 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
198 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
199 { WM_GETTEXT
, sent
|defwinproc
|optional
},
200 { WM_ERASEBKGND
, sent
|optional
},
201 { HCBT_ACTIVATE
, hook
},
202 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
203 { WM_NOTIFYFORMAT
, sent
|optional
},
204 { WM_QUERYUISTATE
, sent
|optional
},
205 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
206 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
207 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
208 { WM_NCACTIVATE
, sent
},
209 { WM_GETTEXT
, sent
|defwinproc
|optional
},
210 { WM_ACTIVATE
, sent
|wparam
, 1 },
211 { HCBT_SETFOCUS
, hook
},
212 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
213 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
214 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
215 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
216 { WM_GETTEXT
, sent
|optional
},
217 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
218 { WM_GETTEXT
, sent
|defwinproc
|optional
},
219 { WM_ERASEBKGND
, sent
|optional
},
220 /* Win9x adds SWP_NOZORDER below */
221 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
222 { WM_GETTEXT
, sent
|optional
},
223 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
224 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
225 { WM_ERASEBKGND
, sent
|optional
},
226 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10 */
227 { WM_SYNCPAINT
, sent
|optional
},
228 { WM_GETTITLEBARINFOEX
, sent
|optional
},
229 { WM_PAINT
, sent
|optional
},
230 { WM_NCPAINT
, sent
|beginpaint
|optional
},
231 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
232 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
235 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
236 * for a visible overlapped window.
238 static const struct message WmSWP_HideOverlappedSeq
[] = {
239 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
240 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
241 { HCBT_ACTIVATE
, hook
|optional
},
242 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
243 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
244 { WM_NCACTIVATE
, sent
|optional
},
245 { WM_ACTIVATE
, sent
|optional
},
246 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
250 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
251 * for a visible overlapped window.
253 static const struct message WmSWP_ResizeSeq
[] = {
254 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
255 { WM_GETMINMAXINFO
, sent
|defwinproc
},
256 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
257 { WM_NCPAINT
, sent
|optional
},
258 { WM_GETTEXT
, sent
|defwinproc
|optional
},
259 { WM_ERASEBKGND
, sent
|optional
},
260 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
261 { WM_SIZE
, sent
|defwinproc
|optional
},
262 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
263 { WM_NCPAINT
, sent
|optional
},
264 { WM_GETTEXT
, sent
|defwinproc
|optional
},
265 { WM_ERASEBKGND
, sent
|optional
},
266 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
267 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
271 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
272 * for a visible popup window.
274 static const struct message WmSWP_ResizePopupSeq
[] = {
275 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
276 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* Win9x */
277 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
278 { WM_NCPAINT
, sent
|optional
},
279 { WM_GETTEXT
, sent
|defwinproc
|optional
},
280 { WM_ERASEBKGND
, sent
|optional
},
281 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
282 { WM_SIZE
, sent
|defwinproc
|wparam
|optional
, SIZE_RESTORED
},
283 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
284 { WM_NCPAINT
, sent
|optional
},
285 { WM_GETTEXT
, sent
|defwinproc
|optional
},
286 { WM_ERASEBKGND
, sent
|optional
},
287 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
291 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
292 * for a visible overlapped window.
294 static const struct message WmSWP_MoveSeq
[] = {
295 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
},
296 { WM_NCPAINT
, sent
|optional
},
297 { WM_GETTEXT
, sent
|defwinproc
|optional
},
298 { WM_ERASEBKGND
, sent
|optional
},
299 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
300 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
301 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
304 /* Resize with SetWindowPos(SWP_NOZORDER)
305 * for a visible overlapped window
306 * SWP_NOZORDER is stripped by the logging code
308 static const struct message WmSWP_ResizeNoZOrder
[] = {
309 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
},
310 { WM_GETMINMAXINFO
, sent
|defwinproc
},
311 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
312 { WM_NCPAINT
, sent
|optional
},
313 { WM_GETTEXT
, sent
|defwinproc
|optional
},
314 { WM_ERASEBKGND
, sent
|optional
},
315 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
, 0,
316 SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
317 { WM_MOVE
, sent
|defwinproc
|optional
},
318 { WM_SIZE
, sent
|defwinproc
|optional
},
319 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
320 { WM_NCPAINT
, sent
|optional
}, /* Win9x doesn't send it */
321 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
322 { WM_ERASEBKGND
, sent
|optional
}, /* Win9x doesn't send it */
323 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
324 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
328 /* Switch visible mdi children */
329 static const struct message WmSwitchChild
[] = {
330 /* Switch MDI child */
331 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
332 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 1st MDI child */
333 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
334 { WM_CHILDACTIVATE
, sent
},/* in the 1st MDI child */
335 /* Deactivate 2nd MDI child */
336 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
337 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
338 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
339 /* Preparing for maximize and maximize the 1st MDI child */
340 { WM_GETMINMAXINFO
, sent
|defwinproc
}, /* in the 1st MDI child */
341 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
}, /* in the 1st MDI child */
342 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
343 { WM_CHILDACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
344 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 1st MDI child */
345 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
}, /* in the 1st MDI child */
346 /* Lock redraw 2nd MDI child */
347 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
348 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
349 /* Restore 2nd MDI child */
350 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},/* in the 2nd MDI child */
351 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
352 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
353 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 2nd MDI child */
354 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
}, /* in the 2nd MDI child */
355 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
356 /* Redraw 2nd MDI child */
357 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
358 /* Redraw MDI frame */
359 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},/* in MDI frame */
360 { WM_NCCALCSIZE
, sent
|wparam
, 1 },/* in MDI frame */
361 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in MDI frame */
362 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in MDI frame */
363 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
364 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
365 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
366 { HCBT_SETFOCUS
, hook
},
367 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
368 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },/* in the 1st MDI child */
369 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
370 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
371 { WM_SETFOCUS
, sent
},/* in the MDI client */
372 { HCBT_SETFOCUS
, hook
},
373 { WM_KILLFOCUS
, sent
},/* in the MDI client */
374 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
375 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 }, /* in the 1st MDI child */
376 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
377 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
378 { WM_MDIACTIVATE
, sent
|defwinproc
},/* in the 1st MDI child */
379 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 1st MDI child */
383 /* Switch visible not maximized mdi children */
384 static const struct message WmSwitchNotMaximizedChild
[] = {
385 /* Switch not maximized MDI child */
386 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
387 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 2nd MDI child */
388 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
389 { WM_CHILDACTIVATE
, sent
},/* in the 2nd MDI child */
390 /* Deactivate 1st MDI child */
391 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
392 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
393 /* Activate 2nd MDI child */
394 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
}, /* in the 2nd MDI child */
395 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 2nd MDI child */
396 { HCBT_SETFOCUS
, hook
}, /* in the 1st MDI child */
397 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
398 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
399 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
400 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
401 { WM_SETFOCUS
, sent
, 0 }, /* in the MDI client */
402 { HCBT_SETFOCUS
, hook
},
403 { WM_KILLFOCUS
, sent
}, /* in the MDI client */
404 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
405 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
406 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
407 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
408 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
409 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 2nd MDI child */
414 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
415 SWP_NOZORDER|SWP_FRAMECHANGED)
416 * for a visible overlapped window with WS_CLIPCHILDREN style set.
418 static const struct message WmSWP_FrameChanged_clip
[] = {
419 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
420 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
421 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
422 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
423 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
424 { WM_NCPAINT
, sent
}, /* wparam != 1 */
425 { WM_ERASEBKGND
, sent
},
426 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
427 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
431 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
432 SWP_NOZORDER|SWP_FRAMECHANGED)
433 * for a visible overlapped window.
435 static const struct message WmSWP_FrameChangedDeferErase
[] = {
436 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
437 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
438 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
439 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
440 { WM_PAINT
, sent
|parent
|optional
},
441 { WM_NCPAINT
, sent
|beginpaint
|parent
|optional
}, /* wparam != 1 */
442 { WM_GETTEXT
, sent
|beginpaint
|parent
|defwinproc
|optional
},
444 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
445 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
449 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
450 SWP_NOZORDER|SWP_FRAMECHANGED)
451 * for a visible overlapped window without WS_CLIPCHILDREN style set.
453 static const struct message WmSWP_FrameChanged_noclip
[] = {
454 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
455 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
456 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
457 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
458 { WM_ERASEBKGND
, sent
|parent
|optional
},
459 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
460 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
462 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
463 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
467 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
468 static const struct message WmShowOverlappedSeq
[] = {
469 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
470 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
471 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
472 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
473 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
474 { WM_GETTEXT
, sent
|defwinproc
|optional
},
475 { WM_ERASEBKGND
, sent
|optional
},
476 { HCBT_ACTIVATE
, hook
|optional
},
477 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
478 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
479 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
480 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
481 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
482 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
483 { WM_GETTEXT
, sent
|defwinproc
|optional
},
484 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
485 { HCBT_SETFOCUS
, hook
|optional
},
486 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
487 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
488 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
489 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
490 { WM_GETTEXT
, sent
|optional
},
491 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
492 { WM_GETTEXT
, sent
|defwinproc
|optional
},
493 { WM_ERASEBKGND
, sent
|optional
},
494 /* Win9x adds SWP_NOZORDER below */
495 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
496 { WM_NCCALCSIZE
, sent
|optional
},
497 { WM_GETTEXT
, sent
|optional
},
498 { WM_NCPAINT
, sent
|optional
},
499 { WM_ERASEBKGND
, sent
|optional
},
500 { WM_SYNCPAINT
, sent
|optional
},
501 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
502 * messages. Does that mean that CreateWindow doesn't set initial
503 * window dimensions for overlapped windows?
508 { WM_PAINT
, sent
|optional
},
509 { WM_NCPAINT
, sent
|beginpaint
|optional
},
512 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
513 static const struct message WmShowMaxOverlappedSeq
[] = {
514 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
515 { WM_GETMINMAXINFO
, sent
},
516 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
517 { WM_GETMINMAXINFO
, sent
|defwinproc
},
518 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
519 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
520 { HCBT_ACTIVATE
, hook
|optional
},
521 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
522 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
523 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
524 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
525 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
526 { WM_GETTEXT
, sent
|defwinproc
|optional
},
527 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
528 { HCBT_SETFOCUS
, hook
|optional
},
529 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
530 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
531 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
532 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
533 { WM_GETTEXT
, sent
|optional
},
534 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
535 { WM_GETTEXT
, sent
|defwinproc
|optional
},
536 { WM_ERASEBKGND
, sent
|optional
},
537 /* Win9x adds SWP_NOZORDER below */
538 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
539 { WM_MOVE
, sent
|defwinproc
},
540 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
541 { WM_GETTEXT
, sent
|optional
},
542 { WM_NCCALCSIZE
, sent
|optional
},
543 { WM_NCPAINT
, sent
|optional
},
544 { WM_ERASEBKGND
, sent
|optional
},
545 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
546 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
547 { WM_SYNCPAINT
, sent
|optional
},
548 { WM_GETTITLEBARINFOEX
, sent
|optional
},
549 { WM_PAINT
, sent
|optional
},
550 { WM_NCPAINT
, sent
|beginpaint
|optional
},
551 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
554 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
555 static const struct message WmShowRestoreMaxOverlappedSeq
[] = {
556 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
557 { WM_GETTEXT
, sent
|optional
},
558 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
559 { WM_GETMINMAXINFO
, sent
|defwinproc
},
560 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
561 { WM_NCPAINT
, sent
|optional
},
562 { WM_GETTEXT
, sent
|defwinproc
|optional
},
563 { WM_ERASEBKGND
, sent
|optional
},
564 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
565 { WM_MOVE
, sent
|defwinproc
|optional
},
566 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
567 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
568 { WM_NCPAINT
, sent
|optional
},
569 { WM_ERASEBKGND
, sent
|optional
},
570 { WM_PAINT
, sent
|optional
},
571 { WM_GETTITLEBARINFOEX
, sent
|optional
},
572 { WM_NCPAINT
, sent
|beginpaint
|optional
},
573 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
574 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
575 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
576 { WM_SYNCPAINT
, sent
|optional
},
579 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
580 static const struct message WmShowRestoreMinOverlappedSeq
[] = {
581 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
582 { WM_QUERYOPEN
, sent
|optional
},
583 { WM_GETTEXT
, sent
|optional
},
584 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
585 { WM_WINDOWPOSCHANGING
, sent
|optional
}, /* SWP_NOSIZE|SWP_NOMOVE */
586 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
587 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
588 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
589 { WM_MOVE
, sent
|optional
},
590 { WM_SIZE
, sent
|wparam
|optional
, SIZE_RESTORED
},
591 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
592 { WM_GETTEXT
, sent
|optional
},
593 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
|SWP_NOCOPYBITS
},
594 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
},
595 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
596 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win10. */
597 { HCBT_ACTIVATE
, hook
|optional
},
598 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
599 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
600 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
601 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
602 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
603 { WM_GETTEXT
, sent
|defwinproc
|optional
},
604 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
605 { HCBT_SETFOCUS
, hook
|optional
},
606 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
607 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
608 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
609 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
610 { WM_GETTEXT
, sent
|optional
},
611 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
612 { WM_GETTEXT
, sent
|defwinproc
|optional
},
613 { WM_ERASEBKGND
, sent
},
614 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_STATECHANGED
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
},
615 { WM_MOVE
, sent
|defwinproc
},
616 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
617 { HCBT_SETFOCUS
, hook
|optional
},
618 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
619 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
620 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
621 { WM_ERASEBKGND
, sent
|optional
},
622 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
623 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
624 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
625 { HCBT_SETFOCUS
, hook
|optional
},
626 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
627 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
628 { WM_ACTIVATE
, sent
|wparam
, 1 },
629 { WM_GETTEXT
, sent
|optional
},
630 { WM_PAINT
, sent
|optional
},
631 { WM_GETTITLEBARINFOEX
, sent
|optional
},
632 { WM_NCPAINT
, sent
|beginpaint
|optional
},
633 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
636 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
637 static const struct message WmShowMinOverlappedSeq
[] = {
638 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
639 { HCBT_SETFOCUS
, hook
|optional
},
640 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
641 { WM_KILLFOCUS
, sent
|optional
},
642 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
643 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
644 { WM_GETTEXT
, sent
|optional
},
645 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCOPYBITS
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
646 { WM_GETMINMAXINFO
, sent
|defwinproc
},
647 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
648 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
649 { WM_NCPAINT
, sent
|optional
},
650 { WM_GETTEXT
, sent
|defwinproc
|optional
},
651 { WM_WINDOWPOSCHANGED
, sent
},
652 { WM_MOVE
, sent
|defwinproc
},
653 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
654 { WM_NCCALCSIZE
, sent
|optional
},
655 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
656 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
657 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
658 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
659 { WM_GETTEXT
, sent
|defwinproc
|optional
},
660 { WM_ACTIVATE
, sent
|optional
},
661 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
663 /* Vista sometimes restores the window right away... */
664 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
665 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
666 { HCBT_MINMAX
, hook
|optional
|lparam
, 0, SW_RESTORE
},
667 { WM_QUERYOPEN
, sent
|optional
},
668 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
669 { WM_GETMINMAXINFO
, sent
|optional
|defwinproc
},
670 { WM_NCCALCSIZE
, sent
|optional
|wparam
, TRUE
},
671 { HCBT_ACTIVATE
, hook
|optional
},
672 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 1 },
673 { WM_NCACTIVATE
, sent
|optional
},
674 { WM_GETTEXT
, sent
|optional
},
675 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
676 { HCBT_SETFOCUS
, hook
|optional
},
677 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
678 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
679 { WM_SETFOCUS
, sent
|optional
},
680 { WM_NCPAINT
, sent
|optional
},
681 { WM_GETTEXT
, sent
|defwinproc
|optional
},
682 { WM_ERASEBKGND
, sent
|optional
},
683 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
684 { WM_MOVE
, sent
|defwinproc
|optional
},
685 { WM_SIZE
, sent
|defwinproc
|optional
|wparam
, SIZE_RESTORED
},
686 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
687 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
688 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
690 { WM_PAINT
, sent
|optional
},
691 { WM_NCPAINT
, sent
|beginpaint
|optional
},
692 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
695 /* ShowWindow(SW_HIDE) for a visible overlapped window */
696 static const struct message WmHideOverlappedSeq
[] = {
697 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
698 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
699 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
700 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
701 { WM_SIZE
, sent
|optional
}, /* XP doesn't send it */
702 { WM_MOVE
, sent
|optional
}, /* XP doesn't send it */
703 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
704 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
705 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
706 { HCBT_SETFOCUS
, hook
|optional
},
707 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
708 { WM_KILLFOCUS
, sent
|wparam
|optional
, 0 },
709 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
710 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
713 /* DestroyWindow for a visible overlapped window */
714 static const struct message WmDestroyOverlappedSeq
[] = {
715 { HCBT_DESTROYWND
, hook
},
716 { 0x0090, sent
|optional
},
717 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
718 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
719 { 0x0090, sent
|optional
},
720 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
721 { WM_NCACTIVATE
, sent
|optional
|wparam
, 0 },
722 { WM_ACTIVATE
, sent
|optional
},
723 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 0 },
724 { WM_KILLFOCUS
, sent
|optional
|wparam
, 0 },
725 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
726 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
727 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
728 { WM_DESTROY
, sent
},
729 { WM_NCDESTROY
, sent
},
732 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
733 static const struct message WmCreateMaxPopupSeq
[] = {
734 { HCBT_CREATEWND
, hook
},
735 { WM_NCCREATE
, sent
},
736 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
738 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
739 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
741 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
742 { WM_GETMINMAXINFO
, sent
},
743 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
744 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
745 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
746 { WM_MOVE
, sent
|defwinproc
},
747 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
748 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
749 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
750 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
751 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
752 { HCBT_ACTIVATE
, hook
},
753 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
754 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
755 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
756 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
757 { WM_ERASEBKGND
, sent
|optional
},
758 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_NOMOVE
|SWP_NOSIZE
},
759 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
760 { WM_NCACTIVATE
, sent
},
761 { WM_ACTIVATE
, sent
|wparam
, 1 },
762 { HCBT_SETFOCUS
, hook
},
763 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
764 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
765 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
766 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
767 { WM_GETTEXT
, sent
|optional
},
768 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
769 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
770 { WM_ERASEBKGND
, sent
|optional
},
771 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
772 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
773 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
776 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
777 static const struct message WmCreateInvisibleMaxPopupSeq
[] = {
778 { HCBT_CREATEWND
, hook
},
779 { WM_NCCREATE
, sent
},
780 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
782 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
783 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
785 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
786 { WM_GETMINMAXINFO
, sent
},
787 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
788 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
789 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
790 { WM_MOVE
, sent
|defwinproc
},
791 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
792 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
795 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
796 static const struct message WmShowMaxPopupResizedSeq
[] = {
797 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
798 { WM_GETMINMAXINFO
, sent
},
799 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
800 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
801 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
802 { HCBT_ACTIVATE
, hook
},
803 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
804 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
805 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
806 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
807 { WM_ERASEBKGND
, sent
|optional
},
808 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
809 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
810 { WM_NCACTIVATE
, sent
},
811 { WM_ACTIVATE
, sent
|wparam
, 1 },
812 { HCBT_SETFOCUS
, hook
},
813 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
814 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
815 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
816 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
817 { WM_GETTEXT
, sent
|optional
},
818 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
819 { WM_ERASEBKGND
, sent
|optional
},
820 { WM_WINDOWPOSCHANGED
, sent
},
821 /* WinNT4.0 sends WM_MOVE */
822 { WM_MOVE
, sent
|defwinproc
|optional
},
823 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
824 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
827 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
828 static const struct message WmShowMaxPopupSeq
[] = {
829 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
830 { WM_GETMINMAXINFO
, sent
},
831 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
832 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
833 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
834 { HCBT_ACTIVATE
, hook
},
835 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
836 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
837 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
838 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
839 { WM_ERASEBKGND
, sent
|optional
},
840 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOMOVE
|SWP_NOSIZE
},
841 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
842 { WM_NCACTIVATE
, sent
},
843 { WM_ACTIVATE
, sent
|wparam
, 1 },
844 { HCBT_SETFOCUS
, hook
},
845 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
846 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
847 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
848 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
849 { WM_GETTEXT
, sent
|optional
},
850 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
851 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
852 { WM_ERASEBKGND
, sent
|optional
},
853 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
854 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
855 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
856 { WM_SIZE
, sent
|defwinproc
|optional
},
857 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
860 /* CreateWindow(WS_VISIBLE) for popup window */
861 static const struct message WmCreatePopupSeq
[] = {
862 { HCBT_CREATEWND
, hook
},
863 { WM_NCCREATE
, sent
},
864 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
866 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
867 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
869 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
870 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
871 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
872 { HCBT_ACTIVATE
, hook
},
873 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
874 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
875 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
876 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
877 { WM_ERASEBKGND
, sent
|optional
},
878 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
879 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
880 { WM_NCACTIVATE
, sent
},
881 { WM_ACTIVATE
, sent
|wparam
, 1 },
882 { HCBT_SETFOCUS
, hook
},
883 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
884 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
885 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
886 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
887 { WM_GETTEXT
, sent
|optional
},
888 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
889 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
890 { WM_ERASEBKGND
, sent
|optional
},
891 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
894 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
895 static const struct message WmShowVisMaxPopupSeq
[] = {
896 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
897 { WM_GETMINMAXINFO
, sent
},
898 { WM_GETTEXT
, sent
|optional
},
899 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
900 { WM_GETTEXT
, sent
|optional
},
901 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
902 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
903 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
904 { WM_ERASEBKGND
, sent
|optional
},
905 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
906 { WM_MOVE
, sent
|defwinproc
},
907 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
908 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
911 /* ShowWindow(hwnd, SW_RESTORE) to a minimized window */
912 static const struct message WmShowRestoreMinimizedOverlappedSeq
[] =
914 { HCBT_MINMAX
, hook
},
915 { WM_QUERYOPEN
, sent
},
916 { WM_GETTEXT
, sent
|optional
},
917 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
918 { WM_GETMINMAXINFO
, sent
|defwinproc
},
919 { WM_NCCALCSIZE
, sent
},
920 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
921 { HCBT_ACTIVATE
, hook
},
922 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
923 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
924 { WM_NCACTIVATE
, sent
},
925 { WM_GETTEXT
, sent
|defwinproc
|optional
},
926 { WM_ACTIVATE
, sent
|wparam
, WA_ACTIVE
},
927 { HCBT_SETFOCUS
, hook
},
928 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
929 { WM_SETFOCUS
, sent
|defwinproc
},
930 { WM_NCPAINT
, sent
},
931 { WM_GETTEXT
, sent
|defwinproc
|optional
},
932 { WM_GETTEXT
, sent
|defwinproc
|optional
},
933 { WM_ERASEBKGND
, sent
},
934 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
935 { WM_MOVE
, sent
|defwinproc
},
936 { WM_SIZE
, sent
|defwinproc
},
937 { WM_NCCALCSIZE
, sent
|optional
},
938 { WM_NCPAINT
, sent
|optional
},
939 { WM_ERASEBKGND
, sent
|optional
},
940 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
941 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
942 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
943 /* Note this WM_ACTIVATE message even if the window is already active and focused */
944 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
945 { WM_SYNCPAINT
, sent
|optional
},
947 { WM_GETMINMAXINFO
, sent
|optional
},
950 /* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to a minimized window */
951 static const struct message WmShowNoActivateMinimizedOverlappedSeq
[] =
953 { HCBT_MINMAX
, hook
},
954 { WM_QUERYOPEN
, sent
},
955 { WM_GETTEXT
, sent
|optional
},
956 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
957 { WM_GETMINMAXINFO
, sent
|defwinproc
},
958 { WM_NCCALCSIZE
, sent
},
959 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
960 { WM_NCPAINT
, sent
},
961 { WM_GETTEXT
, sent
|defwinproc
|optional
},
962 { WM_ERASEBKGND
, sent
},
963 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
964 { WM_MOVE
, sent
|defwinproc
},
965 { WM_SIZE
, sent
|defwinproc
},
966 /* Following optional messages are on XP/2003 */
967 { WM_NCCALCSIZE
, sent
|optional
},
968 { WM_NCPAINT
, sent
|optional
},
969 { WM_ERASEBKGND
, sent
|optional
},
970 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
971 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
972 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
973 { HCBT_SETFOCUS
, hook
|optional
},
974 { WM_SETFOCUS
, sent
|optional
},
975 { HCBT_ACTIVATE
, hook
|optional
},
976 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
977 { WM_NCACTIVATE
, sent
|optional
},
978 { WM_GETTEXT
, sent
|defwinproc
|optional
},
979 { WM_ACTIVATE
, sent
|wparam
|optional
, WA_ACTIVE
},
980 { HCBT_SETFOCUS
, hook
|optional
},
981 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
982 { WM_KILLFOCUS
, sent
|optional
},
983 { WM_SETFOCUS
, sent
|optional
},
984 /* Note this WM_ACTIVATE message on XP even if the window is already active and focused */
985 { WM_ACTIVATE
, sent
|wparam
|lparam
|optional
, WA_ACTIVE
, 0 },
986 { WM_SYNCPAINT
, sent
|optional
},
988 { WM_GETMINMAXINFO
, sent
|optional
},
991 /* ShowWindow(hwnd, SW_RESTORE) to an active minimized window */
992 static const struct message WmShowRestoreActiveMinimizedOverlappedSeq
[] =
994 { HCBT_MINMAX
, hook
},
995 { WM_QUERYOPEN
, sent
},
996 { WM_GETTEXT
, sent
|optional
},
997 { WM_NCACTIVATE
, sent
},
998 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
999 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1000 { WM_NCCALCSIZE
, sent
|optional
},
1001 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1002 { WM_MOVE
, sent
|optional
},
1003 { WM_SIZE
, sent
|optional
},
1004 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1005 { WM_GETTEXT
, sent
|optional
},
1006 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1007 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1008 { WM_NCCALCSIZE
, sent
},
1009 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win8+ sends this. */
1010 { WM_NCPAINT
, sent
},
1011 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1012 { WM_ERASEBKGND
, sent
},
1013 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1014 { WM_MOVE
, sent
|defwinproc
},
1015 { WM_SIZE
, sent
|defwinproc
},
1016 { WM_NCCALCSIZE
, sent
|optional
},
1017 { WM_NCPAINT
, sent
|optional
},
1018 { WM_ERASEBKGND
, sent
|optional
},
1019 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1020 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1021 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1022 { HCBT_SETFOCUS
, hook
},
1023 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1024 { WM_SETFOCUS
, sent
},
1025 /* Note this WM_ACTIVATE message even if the window is already active */
1026 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
1027 { WM_SYNCPAINT
, sent
|optional
},
1029 { WM_GETMINMAXINFO
, sent
|optional
},
1032 /* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to an active minimized window */
1033 static const struct message WmShowNoActivateActiveMinimizedOverlappedSeq
[] =
1035 { HCBT_MINMAX
, hook
},
1036 { WM_QUERYOPEN
, sent
},
1037 { WM_GETTEXT
, sent
|optional
},
1038 { WM_NCACTIVATE
, sent
},
1039 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1040 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1041 { WM_NCCALCSIZE
, sent
|optional
},
1042 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1043 { WM_MOVE
, sent
|optional
},
1044 { WM_SIZE
, sent
|optional
},
1045 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1046 { WM_GETTEXT
, sent
|optional
},
1047 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1048 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1049 { WM_NCCALCSIZE
, sent
},
1050 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win8+ sends this. */
1051 { WM_NCPAINT
, sent
},
1052 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1053 { WM_ERASEBKGND
, sent
},
1054 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1055 { WM_MOVE
, sent
|defwinproc
},
1056 { WM_SIZE
, sent
|defwinproc
},
1057 { WM_NCCALCSIZE
, sent
|optional
},
1058 { WM_NCPAINT
, sent
|optional
},
1059 { WM_ERASEBKGND
, sent
|optional
},
1060 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1061 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1062 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1063 /* Following optional messages are present on XP */
1064 { HCBT_SETFOCUS
, hook
|optional
},
1065 { WM_SETFOCUS
, sent
|optional
},
1066 /* Note this WM_ACTIVATE message even if the window is already active and with flag SW_SHOWNOACTIVATE */
1067 { WM_ACTIVATE
, sent
|wparam
|lparam
|optional
, WA_ACTIVE
, 0 },
1068 { WM_SYNCPAINT
, sent
|optional
},
1070 { WM_GETMINMAXINFO
, sent
|optional
},
1073 /* CreateWindow (for a child popup window, not initially visible) */
1074 static const struct message WmCreateChildPopupSeq
[] = {
1075 { HCBT_CREATEWND
, hook
},
1076 { WM_NCCREATE
, sent
},
1077 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1078 { WM_CREATE
, sent
},
1079 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1080 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1084 /* CreateWindow (for a popup window, not initially visible,
1085 * which sets WS_VISIBLE in WM_CREATE handler)
1087 static const struct message WmCreateInvisiblePopupSeq
[] = {
1088 { HCBT_CREATEWND
, hook
},
1089 { WM_NCCREATE
, sent
},
1090 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1091 { WM_CREATE
, sent
},
1092 { WM_STYLECHANGING
, sent
},
1093 { WM_STYLECHANGED
, sent
},
1094 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1095 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1099 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
1100 * for a popup window with WS_VISIBLE style set
1102 static const struct message WmShowVisiblePopupSeq_2
[] = {
1103 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1106 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1107 * for a popup window with WS_VISIBLE style set
1109 static const struct message WmShowVisiblePopupSeq_3
[] = {
1110 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1111 { HCBT_ACTIVATE
, hook
},
1112 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1113 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1114 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1115 { WM_NCACTIVATE
, sent
},
1116 { WM_ACTIVATE
, sent
|wparam
, 1 },
1117 { HCBT_SETFOCUS
, hook
},
1118 { WM_KILLFOCUS
, sent
|parent
},
1119 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1120 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1121 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1122 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1123 { WM_SETFOCUS
, sent
|defwinproc
},
1124 { WM_GETTEXT
, sent
|optional
},
1125 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_SHOWWINDOW
},
1128 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
1130 static const struct message WmShowPopupExtremeLocationSeq
[] = {
1131 { HCBT_CREATEWND
, hook
},
1132 { WM_NCCREATE
, sent
},
1133 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1134 { WM_CREATE
, sent
},
1135 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1136 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1138 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1139 { WM_WINDOWPOSCHANGING
, sent
},
1140 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1141 { HCBT_ACTIVATE
, hook
},
1142 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1143 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1144 { WM_QUERYNEWPALETTE
, sent
|optional
},
1146 /* occasionally received on test machines */
1147 { WM_NCPAINT
, sent
|optional
},
1148 { WM_ERASEBKGND
, sent
|optional
},
1149 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1151 { WM_ACTIVATEAPP
, sent
},
1152 { WM_NCACTIVATE
, sent
},
1153 { WM_ACTIVATE
, sent
},
1154 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1155 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1156 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1157 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1158 { HCBT_SETFOCUS
, hook
},
1159 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1160 { WM_SETFOCUS
, sent
|defwinproc
},
1161 { WM_NCPAINT
, sent
|wparam
|optional
, 1 }, /* Not always sent on Win8+ */
1162 { WM_ERASEBKGND
, sent
|optional
}, /* Not always sent on Win8+ */
1163 { WM_WINDOWPOSCHANGED
, sent
},
1164 /* occasionally received on test machines */
1165 { WM_NCPAINT
, sent
|optional
},
1166 { WM_ERASEBKGND
, sent
|optional
},
1169 /* CreateWindow (for a popup window with WS_VISIBLE style set)
1171 static const struct message WmShowPopupFirstDrawSeq_1
[] = {
1172 { HCBT_CREATEWND
, hook
},
1173 { WM_NCCREATE
, sent
},
1174 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1175 { WM_CREATE
, sent
},
1176 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1177 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1179 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1180 { WM_WINDOWPOSCHANGING
, sent
},
1181 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1182 { HCBT_ACTIVATE
, hook
},
1183 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1184 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1185 { WM_QUERYNEWPALETTE
, sent
|optional
},
1186 { WM_ACTIVATEAPP
, sent
},
1187 { WM_NCACTIVATE
, sent
},
1188 { WM_ACTIVATE
, sent
},
1189 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1190 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1191 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1192 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1193 { HCBT_SETFOCUS
, hook
},
1194 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1195 { WM_SETFOCUS
, sent
|defwinproc
},
1196 { WM_NCPAINT
, sent
|wparam
, 1 },
1197 { WM_ERASEBKGND
, sent
},
1198 { WM_WINDOWPOSCHANGED
, sent
},
1200 /* occasionally received on test machines */
1201 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1202 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1205 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1207 static const struct message WmShowPopupFirstDrawSeq_2
[] = {
1208 { HCBT_CREATEWND
, hook
},
1209 { WM_NCCREATE
, sent
},
1210 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1211 { WM_CREATE
, sent
},
1212 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1213 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1215 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1216 { WM_GETMINMAXINFO
, sent
},
1217 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_STATECHANGED
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
1218 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
1219 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1220 { HCBT_ACTIVATE
, hook
},
1221 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1222 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1223 { WM_NCPAINT
, sent
|optional
|wparam
, 1 },
1224 { WM_ERASEBKGND
, sent
|optional
},
1225 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1226 { WM_QUERYNEWPALETTE
, sent
|optional
},
1227 { WM_ACTIVATEAPP
, sent
},
1228 { WM_NCACTIVATE
, sent
},
1229 { WM_ACTIVATE
, sent
},
1230 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1231 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1232 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1233 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1234 { HCBT_SETFOCUS
, hook
},
1235 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1236 { WM_SETFOCUS
, sent
|defwinproc
},
1237 { WM_NCPAINT
, sent
|wparam
, 1 },
1238 { WM_ERASEBKGND
, sent
},
1239 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1240 { WM_MOVE
, sent
|defwinproc
},
1241 { WM_SIZE
, sent
|defwinproc
, 0 },
1242 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1244 /* occasionally received on test machines */
1245 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1246 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1249 static const struct message WmFirstDrawSetWindowPosSeq1
[] = {
1250 { HCBT_CREATEWND
, hook
},
1251 { WM_NCCREATE
, sent
},
1252 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1253 { WM_CREATE
, sent
},
1254 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1255 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1257 { WM_WINDOWPOSCHANGING
, sent
},
1258 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1259 { HCBT_ACTIVATE
, hook
},
1260 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1261 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1262 { WM_QUERYNEWPALETTE
, sent
|optional
},
1263 { WM_ACTIVATEAPP
, sent
},
1264 { WM_NCACTIVATE
, sent
},
1265 { WM_ACTIVATE
, sent
},
1266 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1267 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1268 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1269 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1270 { HCBT_SETFOCUS
, hook
},
1271 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1272 { WM_SETFOCUS
, sent
|defwinproc
},
1273 { WM_NCPAINT
, sent
|wparam
, 1 },
1274 { WM_ERASEBKGND
, sent
},
1275 { WM_WINDOWPOSCHANGED
, sent
},
1276 { WM_MOVE
, sent
|defwinproc
},
1277 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1280 static const struct message WmFirstDrawSetWindowPosSeq2
[] = {
1281 { HCBT_CREATEWND
, hook
},
1282 { WM_NCCREATE
, sent
},
1283 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1284 { WM_CREATE
, sent
},
1285 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1286 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1288 { WM_WINDOWPOSCHANGING
, sent
},
1289 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not always sent. */
1290 { HCBT_ACTIVATE
, hook
},
1291 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1292 { WM_QUERYNEWPALETTE
, sent
|optional
},
1293 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1294 { WM_ACTIVATEAPP
, sent
},
1295 { WM_NCACTIVATE
, sent
},
1296 { WM_ACTIVATE
, sent
},
1297 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1298 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1299 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1300 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1301 { HCBT_SETFOCUS
, hook
},
1302 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1303 { WM_SETFOCUS
, sent
|defwinproc
},
1304 { WM_WINDOWPOSCHANGED
, sent
},
1305 { WM_MOVE
, sent
|defwinproc
},
1306 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1309 static const struct message WmFirstDrawSetWindowPosSeq3
[] = {
1310 { HCBT_CREATEWND
, hook
},
1311 { WM_NCCREATE
, sent
},
1312 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1313 { WM_CREATE
, sent
},
1314 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1315 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1317 /* These happen only on Wine: */
1318 { EVENT_OBJECT_SHOW
, winevent_hook
|optional
},
1319 { HCBT_ACTIVATE
, hook
|optional
},
1320 { WM_QUERYNEWPALETTE
, sent
|optional
},
1321 { WM_ACTIVATEAPP
, sent
|optional
},
1322 { WM_NCACTIVATE
, sent
|optional
},
1323 { WM_ACTIVATE
, sent
|optional
},
1324 { HCBT_SETFOCUS
, hook
|optional
},
1325 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
1328 static const struct message WmFirstDrawSetWindowPosSeq4
[] = {
1329 { HCBT_CREATEWND
, hook
},
1330 { WM_NCCREATE
, sent
},
1331 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1332 { WM_CREATE
, sent
},
1333 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1334 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1336 { WM_WINDOWPOSCHANGING
, sent
},
1337 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1338 { HCBT_ACTIVATE
, hook
},
1339 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1340 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1341 { WM_QUERYNEWPALETTE
, sent
|optional
},
1342 { WM_ACTIVATEAPP
, sent
},
1343 { WM_NCACTIVATE
, sent
},
1344 { WM_ACTIVATE
, sent
},
1345 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1346 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1347 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1348 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1349 { HCBT_SETFOCUS
, hook
},
1350 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1351 { WM_SETFOCUS
, sent
|defwinproc
},
1352 { WM_NCPAINT
, sent
|wparam
, 1 },
1353 { WM_ERASEBKGND
, sent
},
1354 { WM_WINDOWPOSCHANGED
, sent
},
1357 static const struct message WmFirstDrawSetWindowPosSeq5
[] = {
1358 { HCBT_CREATEWND
, hook
},
1359 { WM_NCCREATE
, sent
},
1360 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1361 { WM_CREATE
, sent
},
1362 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1363 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1365 { WM_WINDOWPOSCHANGING
, sent
},
1366 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1367 { HCBT_ACTIVATE
, hook
},
1368 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1369 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1370 { WM_QUERYNEWPALETTE
, sent
|optional
},
1371 { WM_ACTIVATEAPP
, sent
},
1372 { WM_NCACTIVATE
, sent
},
1373 { WM_ACTIVATE
, sent
},
1374 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1375 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1376 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1377 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1378 { HCBT_SETFOCUS
, hook
},
1379 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1380 { WM_SETFOCUS
, sent
|defwinproc
},
1381 { WM_WINDOWPOSCHANGED
, sent
},
1384 static const struct message WmFirstDrawChildSeq1
[] = {
1385 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1386 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1389 static const struct message WmFirstDrawChildSeq2
[] = {
1390 { WM_NCPAINT
, sent
|wparam
, 1 },
1391 { WM_ERASEBKGND
, sent
},
1392 /* occasionally received on test machines */
1393 { WM_NCPAINT
, sent
|optional
},
1394 { WM_ERASEBKGND
, sent
|optional
},
1395 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1396 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1399 /* CreateWindow (for child window, not initially visible) */
1400 static const struct message WmCreateChildSeq
[] = {
1401 { HCBT_CREATEWND
, hook
},
1402 { WM_NCCREATE
, sent
},
1403 /* child is inserted into parent's child list after WM_NCCREATE returns */
1404 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1405 { WM_CREATE
, sent
},
1406 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1407 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1409 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1412 /* CreateWindow (for maximized child window, not initially visible) */
1413 static const struct message WmCreateMaximizedChildSeq
[] = {
1414 { HCBT_CREATEWND
, hook
},
1415 { WM_NCCREATE
, sent
},
1416 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1417 { WM_CREATE
, sent
},
1418 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1419 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1421 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1422 { WM_GETMINMAXINFO
, sent
},
1423 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
1424 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1425 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1426 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1427 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1428 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1431 /* CreateWindow (for a child window, initially visible) */
1432 static const struct message WmCreateVisibleChildSeq
[] = {
1433 { HCBT_CREATEWND
, hook
},
1434 { WM_NCCREATE
, sent
},
1435 /* child is inserted into parent's child list after WM_NCCREATE returns */
1436 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1437 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1438 { WM_CREATE
, sent
},
1439 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1440 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1442 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1443 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1444 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1445 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1446 { WM_ERASEBKGND
, sent
|parent
|optional
},
1447 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1448 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
1449 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1452 /* ShowWindow(SW_SHOW) for a not visible child window */
1453 static const struct message WmShowChildSeq
[] = {
1454 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1455 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1456 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1457 { WM_ERASEBKGND
, sent
|parent
|optional
},
1458 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1461 /* ShowWindow(SW_HIDE) for a visible child window */
1462 static const struct message WmHideChildSeq
[] = {
1463 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1464 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1465 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1466 { WM_ERASEBKGND
, sent
|parent
|optional
},
1467 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1470 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1471 static const struct message WmHideChildSeq2
[] = {
1472 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1473 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1474 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1475 { WM_ERASEBKGND
, sent
|parent
|optional
},
1476 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1479 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1480 * for a not visible child window
1482 static const struct message WmShowChildSeq_2
[] = {
1483 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1484 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1485 { WM_CHILDACTIVATE
, sent
},
1486 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1489 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1490 * for a not visible child window
1492 static const struct message WmShowChildSeq_3
[] = {
1493 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1494 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1495 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1498 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1499 * for a visible child window with a caption
1501 static const struct message WmShowChildSeq_4
[] = {
1502 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1503 { WM_CHILDACTIVATE
, sent
},
1506 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1507 static const struct message WmShowChildInvisibleParentSeq_1
[] = {
1508 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1509 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1510 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1511 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1512 { WM_CHILDACTIVATE
, sent
|optional
},
1513 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1514 { WM_MOVE
, sent
|defwinproc
},
1515 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1516 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1517 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1518 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1519 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1520 { WM_GETTEXT
, sent
|optional
},
1523 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1524 static const struct message WmShowChildInvisibleParentSeq_1r
[] = {
1525 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1528 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1529 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
1530 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1531 { WM_GETMINMAXINFO
, sent
},
1532 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
1533 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1534 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1535 { WM_CHILDACTIVATE
, sent
},
1536 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1537 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1538 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1541 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1542 static const struct message WmShowChildInvisibleParentSeq_2r
[] = {
1543 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1546 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1547 static const struct message WmShowChildInvisibleParentSeq_3
[] = {
1548 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1549 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1550 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1551 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1552 { WM_CHILDACTIVATE
, sent
},
1553 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1554 { WM_MOVE
, sent
|defwinproc
},
1555 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1556 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1557 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1558 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1559 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1560 { WM_GETTEXT
, sent
|optional
},
1563 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1564 static const struct message WmShowChildInvisibleParentSeq_3r
[] = {
1565 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1568 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1569 static const struct message WmShowChildInvisibleParentSeq_4
[] = {
1570 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1571 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1572 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1573 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1574 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|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
|winevent_hook_todo
, 0, 0 },
1578 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1579 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1580 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1581 { WM_GETTEXT
, sent
|optional
},
1584 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1585 static const struct message WmShowChildInvisibleParentSeq_4r
[] = {
1586 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1589 /* ShowWindow(SW_SHOW) for child with invisible parent */
1590 static const struct message WmShowChildInvisibleParentSeq_5
[] = {
1591 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1594 /* ShowWindow(SW_HIDE) for child with invisible parent */
1595 static const struct message WmHideChildInvisibleParentSeq
[] = {
1596 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1599 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1600 static const struct message WmShowChildInvisibleParentSeq_6
[] = {
1601 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1602 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1603 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1606 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1607 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
1608 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1609 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1610 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1613 /* DestroyWindow for a visible child window */
1614 static const struct message WmDestroyChildSeq
[] = {
1615 { HCBT_DESTROYWND
, hook
},
1616 { 0x0090, sent
|optional
},
1617 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1618 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1619 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1620 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1621 { WM_ERASEBKGND
, sent
|parent
|optional
},
1622 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1623 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
1624 { WM_KILLFOCUS
, sent
},
1625 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1626 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
1627 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1628 { WM_SETFOCUS
, sent
|parent
},
1629 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1630 { WM_DESTROY
, sent
},
1631 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
1632 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
1633 { WM_NCDESTROY
, sent
},
1636 /* visible child window destroyed by thread exit */
1637 static const struct message WmExitThreadSeq
[] = {
1638 { WM_NCDESTROY
, sent
}, /* actually in grandchild */
1639 { WM_PAINT
, sent
|parent
},
1640 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
1643 /* DestroyWindow for a visible child window with invisible parent */
1644 static const struct message WmDestroyInvisibleChildSeq
[] = {
1645 { HCBT_DESTROYWND
, hook
},
1646 { 0x0090, sent
|optional
},
1647 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1648 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1649 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1650 { WM_DESTROY
, sent
},
1651 { WM_NCDESTROY
, sent
},
1654 /* Resizing child window with MoveWindow (32) */
1655 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1656 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1657 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1658 { WM_ERASEBKGND
, sent
|parent
|optional
},
1659 { WM_ERASEBKGND
, sent
|optional
},
1660 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1661 { WM_MOVE
, sent
|defwinproc
},
1662 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1663 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1666 /* Creation of a custom dialog (32) */
1667 static const struct message WmCreateCustomDialogSeq
[] = {
1668 { HCBT_CREATEWND
, hook
},
1669 { WM_GETMINMAXINFO
, sent
},
1670 { WM_NCCREATE
, sent
},
1671 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1672 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1673 { WM_CREATE
, sent
},
1674 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1675 { WM_NOTIFYFORMAT
, sent
|optional
},
1676 { WM_QUERYUISTATE
, sent
|optional
},
1677 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1678 { WM_GETMINMAXINFO
, sent
|optional
},
1679 { WM_NCCALCSIZE
, sent
|optional
},
1680 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1681 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1682 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1683 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1684 { HCBT_ACTIVATE
, hook
},
1685 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1688 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1690 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1692 { WM_NCACTIVATE
, sent
},
1693 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1694 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1695 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1696 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1697 { WM_ACTIVATE
, sent
|wparam
, 1 },
1698 { WM_GETTEXT
, sent
|optional
},
1699 { WM_KILLFOCUS
, sent
|parent
},
1700 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1701 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1702 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1703 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1704 { WM_SETFOCUS
, sent
},
1705 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1706 { WM_NCPAINT
, sent
|wparam
, 1 },
1707 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1708 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1709 { WM_ERASEBKGND
, sent
},
1710 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1711 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1712 { WM_GETTEXT
, sent
|optional
},
1713 { WM_GETTEXT
, sent
|optional
},
1714 { WM_NCCALCSIZE
, sent
|optional
},
1715 { WM_NCPAINT
, sent
|optional
},
1716 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1717 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1718 { WM_ERASEBKGND
, sent
|optional
},
1719 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1720 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1721 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1725 /* Calling EndDialog for a custom dialog (32) */
1726 static const struct message WmEndCustomDialogSeq
[] = {
1727 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1728 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1729 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1730 { WM_GETTEXT
, sent
|optional
},
1731 { HCBT_ACTIVATE
, hook
},
1732 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1733 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1734 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1735 { WM_ACTIVATE
, sent
|wparam
, 0 },
1736 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1737 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1738 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1739 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1740 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1741 { HCBT_SETFOCUS
, hook
},
1742 { WM_KILLFOCUS
, sent
},
1743 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1744 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1745 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1746 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1747 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1750 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1751 static const struct message WmShowCustomDialogSeq
[] = {
1752 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1753 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1754 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1755 { HCBT_ACTIVATE
, hook
},
1756 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1758 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1760 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1761 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1762 { WM_NCACTIVATE
, sent
},
1763 { WM_ACTIVATE
, sent
|wparam
, 1 },
1764 { WM_GETTEXT
, sent
|optional
},
1766 { WM_KILLFOCUS
, sent
|parent
},
1767 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1768 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1769 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1770 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1771 { WM_SETFOCUS
, sent
},
1772 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1773 { WM_NCPAINT
, sent
|wparam
, 1 },
1774 { WM_ERASEBKGND
, sent
},
1775 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1776 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1779 /* Creation and destruction of a modal dialog (32) */
1780 static const struct message WmModalDialogSeq
[] = {
1781 { WM_CANCELMODE
, sent
|parent
},
1782 { HCBT_SETFOCUS
, hook
},
1783 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1784 { WM_KILLFOCUS
, sent
|parent
},
1785 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1786 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1787 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1788 { HCBT_CREATEWND
, hook
},
1789 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1790 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1791 { WM_SETFONT
, sent
},
1792 { WM_INITDIALOG
, sent
},
1793 { WM_CHANGEUISTATE
, sent
|optional
},
1794 { WM_UPDATEUISTATE
, sent
|optional
},
1795 { WM_SHOWWINDOW
, sent
},
1796 { HCBT_ACTIVATE
, hook
},
1797 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1798 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1799 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1800 { WM_NCACTIVATE
, sent
},
1801 { WM_GETTEXT
, sent
|optional
},
1802 { WM_ACTIVATE
, sent
|wparam
, 1 },
1803 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1804 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1805 { WM_NCPAINT
, sent
|optional
},
1806 { WM_GETTEXT
, sent
|optional
},
1807 { WM_ERASEBKGND
, sent
|optional
},
1808 { WM_CTLCOLORDLG
, sent
|optional
},
1809 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1810 { WM_GETTEXT
, sent
|optional
},
1811 { WM_NCCALCSIZE
, sent
|optional
},
1812 { WM_NCPAINT
, sent
|optional
},
1813 { WM_GETTEXT
, sent
|optional
},
1814 { WM_ERASEBKGND
, sent
|optional
},
1815 { WM_CTLCOLORDLG
, sent
|optional
},
1816 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1817 { WM_PAINT
, sent
|optional
},
1818 { WM_CTLCOLORBTN
, sent
|optional
},
1819 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1820 { WM_ENTERIDLE
, sent
|parent
|optional
},
1821 { WM_ENTERIDLE
, sent
|parent
|optional
},
1822 { WM_ENTERIDLE
, sent
|parent
|optional
},
1823 { WM_ENTERIDLE
, sent
|parent
|optional
},
1824 { WM_ENTERIDLE
, sent
|parent
|optional
},
1825 { WM_ENTERIDLE
, sent
|parent
|optional
},
1826 { WM_ENTERIDLE
, sent
|parent
|optional
},
1827 { WM_ENTERIDLE
, sent
|parent
|optional
},
1828 { WM_ENTERIDLE
, sent
|parent
|optional
},
1829 { WM_ENTERIDLE
, sent
|parent
|optional
},
1830 { WM_ENTERIDLE
, sent
|parent
|optional
},
1831 { WM_ENTERIDLE
, sent
|parent
|optional
},
1832 { WM_ENTERIDLE
, sent
|parent
|optional
},
1833 { WM_ENTERIDLE
, sent
|parent
|optional
},
1834 { WM_ENTERIDLE
, sent
|parent
|optional
},
1835 { WM_ENTERIDLE
, sent
|parent
|optional
},
1836 { WM_ENTERIDLE
, sent
|parent
|optional
},
1837 { WM_ENTERIDLE
, sent
|parent
|optional
},
1838 { WM_ENTERIDLE
, sent
|parent
|optional
},
1839 { WM_ENTERIDLE
, sent
|parent
|optional
},
1841 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1842 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1843 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1844 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1845 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1846 { WM_GETTEXT
, sent
|optional
},
1847 { HCBT_ACTIVATE
, hook
},
1848 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1849 { WM_GETTEXT
, sent
|optional
},
1850 { WM_ACTIVATE
, sent
|wparam
, 0 },
1851 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1852 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1853 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1854 { HCBT_SETFOCUS
, hook
},
1855 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1856 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1857 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1858 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1859 { HCBT_DESTROYWND
, hook
},
1860 { 0x0090, sent
|optional
},
1861 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1862 { WM_DESTROY
, sent
},
1863 { WM_NCDESTROY
, sent
},
1866 static const struct message WmModalDialogSeq_2
[] = {
1867 { WM_CANCELMODE
, sent
},
1868 { HCBT_SETFOCUS
, hook
},
1869 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1870 { WM_KILLFOCUS
, sent
},
1871 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1872 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1873 { WM_ENABLE
, sent
|wparam
, 0 },
1874 { HCBT_CREATEWND
, hook
},
1875 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
1876 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1877 { WM_SETFONT
, sent
},
1878 { WM_INITDIALOG
, sent
},
1879 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1880 { WM_CHANGEUISTATE
, sent
|optional
},
1881 { WM_UPDATEUISTATE
, sent
|optional
},
1882 { WM_ENABLE
, sent
|wparam
, 1 },
1883 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1884 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
1885 { WM_CHANGEUISTATE
, sent
|optional
},
1886 { WM_UPDATEUISTATE
, sent
|optional
},
1887 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1888 { HCBT_DESTROYWND
, hook
},
1889 { 0x0090, sent
|optional
},
1890 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1891 { WM_DESTROY
, sent
},
1892 { WM_NCDESTROY
, sent
},
1895 /* SetMenu for NonVisible windows with size change*/
1896 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1897 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1898 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1899 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1900 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1901 { WM_MOVE
, sent
|defwinproc
},
1902 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1903 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1904 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1905 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1906 { WM_GETTEXT
, sent
|optional
},
1907 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1910 /* SetMenu for NonVisible windows with no size change */
1911 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1912 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1913 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1914 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1915 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1918 /* SetMenu for Visible windows with size change */
1919 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1920 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1921 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1922 { 0x0093, sent
|defwinproc
|optional
},
1923 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1924 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1925 { 0x0093, sent
|defwinproc
|optional
},
1926 { 0x0093, sent
|defwinproc
|optional
},
1927 { 0x0091, sent
|defwinproc
|optional
},
1928 { 0x0092, sent
|defwinproc
|optional
},
1929 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1930 { WM_ERASEBKGND
, sent
|optional
},
1931 { WM_ACTIVATE
, sent
|optional
},
1932 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1933 { WM_MOVE
, sent
|defwinproc
},
1934 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1935 { 0x0093, sent
|optional
},
1936 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1937 { 0x0093, sent
|defwinproc
|optional
},
1938 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1939 { 0x0093, sent
|defwinproc
|optional
},
1940 { 0x0093, sent
|defwinproc
|optional
},
1941 { 0x0091, sent
|defwinproc
|optional
},
1942 { 0x0092, sent
|defwinproc
|optional
},
1943 { WM_ERASEBKGND
, sent
|optional
},
1944 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1945 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1948 /* SetMenu for Visible windows with no size change */
1949 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1950 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1951 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1952 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1953 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1954 { WM_ERASEBKGND
, sent
|optional
},
1955 { WM_ACTIVATE
, sent
|optional
},
1956 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1957 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1960 /* DrawMenuBar for a visible window */
1961 static const struct message WmDrawMenuBarSeq
[] =
1963 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1964 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1965 { 0x0093, sent
|defwinproc
|optional
},
1966 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1967 { 0x0093, sent
|defwinproc
|optional
},
1968 { 0x0093, sent
|defwinproc
|optional
},
1969 { 0x0091, sent
|defwinproc
|optional
},
1970 { 0x0092, sent
|defwinproc
|optional
},
1971 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1972 { WM_ERASEBKGND
, sent
|optional
},
1973 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1974 { 0x0093, sent
|optional
},
1975 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1979 static const struct message WmSetRedrawFalseSeq
[] =
1981 { WM_SETREDRAW
, sent
|wparam
, 0 },
1985 static const struct message WmSetRedrawTrueSeq
[] =
1987 { WM_SETREDRAW
, sent
|wparam
, 1 },
1991 static const struct message WmEnableWindowSeq_1
[] =
1993 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1994 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1995 { HCBT_SETFOCUS
, hook
|optional
},
1996 { WM_KILLFOCUS
, sent
|optional
},
1997 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
2001 static const struct message WmEnableWindowSeq_2
[] =
2003 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
2004 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
2008 static const struct message WmEnableWindowSeq_3
[] =
2010 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2011 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
2015 static const struct message WmEnableWindowSeq_4
[] =
2017 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
2021 static const struct message WmGetScrollRangeSeq
[] =
2023 { SBM_GETRANGE
, sent
},
2026 static const struct message WmGetScrollInfoSeq
[] =
2028 { SBM_GETSCROLLINFO
, sent
},
2031 static const struct message WmSetScrollRangeSeq
[] =
2033 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
2034 sends SBM_SETSCROLLINFO.
2036 { SBM_SETSCROLLINFO
, sent
},
2039 /* SetScrollRange for a window without a non-client area */
2040 static const struct message WmSetScrollRangeHSeq_empty
[] =
2042 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_HSCROLL
, 0 },
2045 static const struct message WmSetScrollRangeVSeq_empty
[] =
2047 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_VSCROLL
, 0 },
2050 static const struct message WmSetScrollRangeHVSeq
[] =
2052 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
2053 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2054 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2055 { WM_ERASEBKGND
, sent
|optional
},
2056 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2057 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2058 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2061 /* SetScrollRange for a window with a non-client area */
2062 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
2064 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
2065 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2066 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2067 { WM_NCPAINT
, sent
|optional
},
2068 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2069 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2070 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2071 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2072 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2073 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2074 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2075 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2076 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2077 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2078 { WM_ERASEBKGND
, sent
|optional
},
2079 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
2080 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
2081 { WM_SIZE
, sent
|defwinproc
|optional
},
2082 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2083 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2084 { WM_GETTEXT
, sent
|optional
},
2085 { WM_GETTEXT
, sent
|optional
},
2086 { WM_GETTEXT
, sent
|optional
},
2087 { WM_GETTEXT
, sent
|optional
},
2090 /* test if we receive the right sequence of messages */
2091 /* after calling ShowWindow( SW_SHOWNA) */
2092 static const struct message WmSHOWNAChildInvisParInvis
[] = {
2093 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2096 static const struct message WmSHOWNAChildVisParInvis
[] = {
2097 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2100 static const struct message WmSHOWNAChildVisParVis
[] = {
2101 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2102 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
2105 static const struct message WmSHOWNAChildInvisParVis
[] = {
2106 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2107 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2108 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2109 { WM_ERASEBKGND
, sent
|optional
},
2110 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
2113 static const struct message WmSHOWNATopVisible
[] = {
2114 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2115 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
2116 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2117 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2118 { WM_ERASEBKGND
, sent
|optional
},
2119 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2122 static const struct message WmSHOWNATopInvisible
[] = {
2123 { WM_NOTIFYFORMAT
, sent
|optional
},
2124 { WM_QUERYUISTATE
, sent
|optional
},
2125 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2126 { WM_GETMINMAXINFO
, sent
|optional
},
2127 { WM_NCCALCSIZE
, sent
|optional
},
2128 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2129 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2130 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2131 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2132 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2133 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2134 { WM_ERASEBKGND
, sent
|optional
},
2135 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2136 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2137 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2138 { WM_ERASEBKGND
, sent
|optional
},
2139 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
2140 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2145 static const struct message WmTrackPopupMenuMinimizeWindow
[] = {
2146 { HCBT_CREATEWND
, hook
},
2147 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2148 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2149 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2150 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2151 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2152 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2153 { 0x0093, sent
|optional
},
2154 { 0x0094, sent
|optional
},
2155 { 0x0094, sent
|optional
},
2156 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2157 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2158 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2159 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2160 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2161 { HCBT_MINMAX
, hook
},
2162 { HCBT_SETFOCUS
, hook
},
2163 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2164 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2165 { WM_GETTEXT
, sent
|optional
},
2166 { WM_WINDOWPOSCHANGING
, sent
},
2167 { WM_GETMINMAXINFO
, sent
|defwinproc
},
2168 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2169 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2170 { WM_WINDOWPOSCHANGED
, sent
},
2171 { WM_MOVE
, sent
|defwinproc
},
2172 { WM_SIZE
, sent
|defwinproc
},
2173 { WM_GETTEXT
, sent
|optional
},
2174 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2175 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2176 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
2177 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2178 { WM_CANCELMODE
, sent
},
2179 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2180 { WM_CAPTURECHANGED
, sent
|defwinproc
},
2181 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2182 { HCBT_DESTROYWND
, hook
},
2183 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2184 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2185 { WM_UNINITMENUPOPUP
, sent
|defwinproc
|lparam
, 0, 0 },
2186 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
2187 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2188 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 1, 0 },
2189 { WM_NCACTIVATE
, sent
},
2190 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2191 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2192 { WM_ACTIVATE
, sent
},
2193 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
2197 static const struct message WmTrackPopupMenu
[] = {
2198 { HCBT_CREATEWND
, hook
},
2199 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2200 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2201 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2202 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2203 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2204 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2205 { 0x0093, sent
|optional
},
2206 { 0x0094, sent
|optional
},
2207 { 0x0094, sent
|optional
},
2208 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2209 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2210 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2211 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2212 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2213 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2214 { WM_CAPTURECHANGED
, sent
},
2215 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2216 { HCBT_DESTROYWND
, hook
},
2217 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2218 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2219 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2220 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2221 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2222 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2226 static const struct message WmTrackPopupMenuEsc
[] = {
2230 static const struct message WmTrackPopupMenuCapture
[] = {
2231 { HCBT_CREATEWND
, hook
},
2232 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2233 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2234 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2235 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2236 { WM_CAPTURECHANGED
, sent
},
2237 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2238 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2239 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2240 { 0x0093, sent
|optional
},
2241 { 0x0094, sent
|optional
},
2242 { 0x0094, sent
|optional
},
2243 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2244 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2245 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2246 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2247 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2248 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2249 { WM_CAPTURECHANGED
, sent
},
2250 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2251 { HCBT_DESTROYWND
, hook
},
2252 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2253 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2254 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2255 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2256 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2257 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2261 static const struct message WmTrackPopupMenuEmpty
[] = {
2262 { HCBT_CREATEWND
, hook
},
2263 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2264 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2265 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2266 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2267 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2268 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2269 { 0x0093, sent
|optional
},
2270 { 0x0094, sent
|optional
},
2271 { 0x0094, sent
|optional
},
2272 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2273 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2274 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2275 { WM_CAPTURECHANGED
, sent
},
2276 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2277 { HCBT_DESTROYWND
, hook
},
2278 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2279 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2283 static const struct message WmTrackPopupMenuAbort
[] = {
2284 { HCBT_CREATEWND
, hook
},
2285 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2286 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2287 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2288 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2289 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2290 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2291 { 0x0093, sent
|optional
},
2292 { 0x0094, sent
|optional
},
2293 { 0x0094, sent
|optional
},
2294 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2295 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2296 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2297 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2298 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2299 { WM_CAPTURECHANGED
, sent
},
2300 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2301 { HCBT_DESTROYWND
, hook
},
2302 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2303 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2304 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2305 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2306 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2307 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2311 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
2312 static int sequence_cnt
, sequence_size
;
2313 static struct recvd_message
* sequence
;
2314 static int log_all_parent_messages
;
2315 static CRITICAL_SECTION sequence_cs
;
2317 /* user32 functions */
2318 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
2319 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
2320 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
2321 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
2322 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
2323 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
2324 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
2325 static UINT_PTR (WINAPI
*pSetCoalescableTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
, ULONG
);
2326 /* kernel32 functions */
2327 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
2329 static void init_procs(void)
2331 HMODULE user32
= GetModuleHandleA("user32.dll");
2332 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
2334 #define GET_PROC(dll, func) \
2335 p ## func = (void*)GetProcAddress(dll, #func); \
2337 trace("GetProcAddress(%s) failed\n", #func); \
2340 GET_PROC(user32
, NotifyWinEvent
)
2341 GET_PROC(user32
, SetWinEventHook
)
2342 GET_PROC(user32
, TrackMouseEvent
)
2343 GET_PROC(user32
, UnhookWinEvent
)
2344 GET_PROC(user32
, UpdateLayeredWindow
)
2345 GET_PROC(user32
, SetSystemTimer
)
2346 GET_PROC(user32
, KillSystemTimer
)
2347 GET_PROC(user32
, SetCoalescableTimer
)
2349 GET_PROC(kernel32
, GetCPInfoExA
)
2354 static const char *get_winpos_flags(UINT flags
)
2356 static char buffer
[300];
2359 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2360 DUMP( SWP_SHOWWINDOW
);
2361 DUMP( SWP_HIDEWINDOW
);
2362 DUMP( SWP_NOACTIVATE
);
2363 DUMP( SWP_FRAMECHANGED
);
2364 DUMP( SWP_NOCOPYBITS
);
2365 DUMP( SWP_NOOWNERZORDER
);
2366 DUMP( SWP_NOSENDCHANGING
);
2367 DUMP( SWP_DEFERERASE
);
2368 DUMP( SWP_ASYNCWINDOWPOS
);
2369 DUMP( SWP_NOZORDER
);
2370 DUMP( SWP_NOREDRAW
);
2373 DUMP( SWP_NOCLIENTSIZE
);
2374 DUMP( SWP_NOCLIENTMOVE
);
2375 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
2380 static BOOL
ignore_message( UINT message
)
2382 /* these are always ignored */
2383 return (message
>= 0xc000 ||
2384 message
== WM_GETICON
||
2385 message
== WM_GETOBJECT
||
2386 message
== WM_TIMECHANGE
||
2387 message
== WM_DISPLAYCHANGE
||
2388 message
== WM_DEVICECHANGE
||
2389 message
== WM_DWMNCRENDERINGCHANGED
||
2390 message
== WM_WININICHANGE
);
2393 static unsigned hash_Ly_W(const WCHAR
*str
)
2398 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2403 static unsigned hash_Ly(const char *str
)
2408 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2413 #define add_message(msg) add_message_(__LINE__,msg);
2414 static void add_message_(int line
, const struct recvd_message
*msg
)
2416 struct recvd_message
*seq
;
2418 EnterCriticalSection( &sequence_cs
);
2422 sequence
= malloc( sequence_size
* sizeof(*sequence
) );
2424 if (sequence_cnt
== sequence_size
)
2427 sequence
= realloc( sequence
, sequence_size
* sizeof(*sequence
) );
2430 seq
= &sequence
[sequence_cnt
++];
2431 seq
->hwnd
= msg
->hwnd
;
2432 seq
->message
= msg
->message
;
2433 seq
->flags
= msg
->flags
;
2434 seq
->wParam
= msg
->wParam
;
2435 seq
->lParam
= msg
->lParam
;
2437 seq
->descr
= msg
->descr
;
2439 LeaveCriticalSection( &sequence_cs
);
2443 if (msg
->flags
& hook
)
2445 static const char * const CBT_code_name
[10] =
2453 "HCBT_CLICKSKIPPED",
2458 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
2460 sprintf( seq
->output
, "%s: hook %d (%s) wp %08Ix lp %08Ix",
2461 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
2463 else if (msg
->flags
& winevent_hook
)
2465 sprintf( seq
->output
, "%s: winevent %p %08x %08Ix %08Ix",
2466 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2470 switch (msg
->message
)
2472 case WM_WINDOWPOSCHANGING
:
2473 case WM_WINDOWPOSCHANGED
:
2475 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
2477 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08Ix lp %08Ix after %p x %d y %d cx %d cy %d flags %s",
2478 msg
->descr
, msg
->hwnd
,
2479 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
2480 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
2481 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
2482 get_winpos_flags(winpos
->flags
) );
2484 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2485 * in the high word for internal purposes
2487 seq
->wParam
= winpos
->flags
& 0xffff;
2488 /* We are not interested in the flags that don't match under XP and Win9x */
2489 seq
->wParam
&= ~SWP_NOZORDER
;
2490 seq
->lParam
= (!!winpos
->cx
) | ((!!winpos
->cy
) << 1)
2491 | ((!!winpos
->x
) << 2) | ((!!winpos
->y
) << 3);
2498 NCCALCSIZE_PARAMS
*p
= (NCCALCSIZE_PARAMS
*)msg
->lParam
;
2499 WINDOWPOS
*winpos
= p
->lppos
;
2501 sprintf(seq
->output
, "%s: %p WM_NCCALCSIZE: winpos->cx %u, winpos->cy %u",
2502 msg
->descr
, msg
->hwnd
, winpos
->cx
, winpos
->cy
);
2503 seq
->lParam
= (!!winpos
->cx
) | ((!!winpos
->cy
) << 1)
2504 | ((!!winpos
->x
) << 2) | ((!!winpos
->y
) << 3);
2508 RECT
*rect
= (RECT
*)msg
->lParam
;
2510 sprintf(seq
->output
, "%s: %p WM_NCCALCSIZE: %s",
2511 msg
->descr
, msg
->hwnd
, wine_dbgstr_rect(rect
));
2517 DRAW_ITEM_STRUCT di
;
2518 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
2520 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2521 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
2522 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
2525 di
.u
.item
.type
= dis
->CtlType
;
2526 di
.u
.item
.ctl_id
= dis
->CtlID
;
2527 if (dis
->CtlType
== ODT_LISTBOX
||
2528 dis
->CtlType
== ODT_COMBOBOX
||
2529 dis
->CtlType
== ODT_MENU
)
2530 di
.u
.item
.item_id
= dis
->itemID
;
2531 di
.u
.item
.action
= dis
->itemAction
;
2532 di
.u
.item
.state
= dis
->itemState
;
2534 seq
->lParam
= di
.u
.lp
;
2538 case WM_MEASUREITEM
:
2540 MEASURE_ITEM_STRUCT mi
;
2541 MEASUREITEMSTRUCT
*mis
= (MEASUREITEMSTRUCT
*)msg
->lParam
;
2542 BOOL is_unicode_data
= TRUE
;
2544 sprintf( seq
->output
, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#Ix",
2545 msg
->descr
, msg
->hwnd
, mis
->CtlType
, mis
->CtlID
,
2546 mis
->itemID
, mis
->itemData
);
2548 if (mis
->CtlType
== ODT_LISTBOX
)
2550 HWND ctrl
= GetDlgItem(msg
->hwnd
, mis
->CtlID
);
2551 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2555 mi
.u
.item
.CtlType
= mis
->CtlType
;
2556 mi
.u
.item
.CtlID
= mis
->CtlID
;
2557 mi
.u
.item
.itemID
= mis
->itemID
;
2558 mi
.u
.item
.wParam
= msg
->wParam
;
2559 seq
->wParam
= mi
.u
.wp
;
2560 if (is_unicode_data
)
2561 seq
->lParam
= mis
->itemData
? hash_Ly_W((const WCHAR
*)mis
->itemData
) : 0;
2563 seq
->lParam
= mis
->itemData
? hash_Ly((const char *)mis
->itemData
) : 0;
2567 case WM_COMPAREITEM
:
2569 COMPAREITEMSTRUCT
*cis
= (COMPAREITEMSTRUCT
*)msg
->lParam
;
2570 HWND ctrl
= GetDlgItem(msg
->hwnd
, cis
->CtlID
);
2571 BOOL is_unicode_data
= TRUE
;
2573 ok(msg
->wParam
== cis
->CtlID
, "expected %#x, got %#Ix\n", cis
->CtlID
, msg
->wParam
);
2574 ok(cis
->hwndItem
== ctrl
, "expected %p, got %p\n", ctrl
, cis
->hwndItem
);
2575 ok((int)cis
->itemID1
>= 0, "expected >= 0, got %d\n", cis
->itemID1
);
2576 ok((int)cis
->itemID2
== -1, "expected -1, got %d\n", cis
->itemID2
);
2578 sprintf( seq
->output
, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#Ix, itemID2 %#x, itemData2 %#Ix",
2579 msg
->descr
, msg
->hwnd
, cis
->CtlType
, cis
->CtlID
,
2580 cis
->itemID1
, cis
->itemData1
, cis
->itemID2
, cis
->itemData2
);
2582 if (cis
->CtlType
== ODT_LISTBOX
)
2583 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2585 if (is_unicode_data
)
2587 seq
->wParam
= cis
->itemData1
? hash_Ly_W((const WCHAR
*)cis
->itemData1
) : 0;
2588 seq
->lParam
= cis
->itemData2
? hash_Ly_W((const WCHAR
*)cis
->itemData2
) : 0;
2592 seq
->wParam
= cis
->itemData1
? hash_Ly((const char *)cis
->itemData1
) : 0;
2593 seq
->lParam
= cis
->itemData2
? hash_Ly((const char *)cis
->itemData2
) : 0;
2599 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
2600 sprintf( seq
->output
, "%s: %p %04x wp %08Ix lp %08Ix",
2601 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2603 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
2604 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
2609 /* try to make sure pending X events have been processed before continuing */
2610 static void flush_events(void)
2614 int min_timeout
= 100;
2615 DWORD time
= GetTickCount() + diff
;
2619 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
2620 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2621 diff
= time
- GetTickCount();
2625 static void flush_sequence(void)
2627 EnterCriticalSection( &sequence_cs
);
2630 sequence_cnt
= sequence_size
= 0;
2631 LeaveCriticalSection( &sequence_cs
);
2634 static const char* message_type_name(int flags
) {
2635 if (flags
& hook
) return "hook";
2636 if (flags
& kbd_hook
) return "kbd_hook";
2637 if (flags
& winevent_hook
) return "winevent_hook";
2641 static BOOL
can_skip_message(const struct message
*expected
)
2643 if (expected
->flags
& optional
) return TRUE
;
2645 if ((expected
->flags
& winevent_hook
) && !hEvent_hook
) return TRUE
;
2646 if ((expected
->flags
& kbd_hook
) && !hKBD_hook
) return TRUE
;
2647 if ((expected
->flags
& hook
) && !hCBT_hook
) return TRUE
;
2649 if ((expected
->flags
& winevent_hook_todo
) && !strcmp(winetest_platform
, "wine")) return TRUE
;
2654 static BOOL
messages_equal(const struct message
*expected
, const struct recvd_message
*actual
,
2655 BOOL expect_equal
, const char* file
, int line
)
2657 int todo
= (expected
->flags
& winevent_hook_todo
) != 0;
2658 const int message_type_flags
= hook
|winevent_hook
|kbd_hook
;
2659 static int todo_reported
;
2661 if (!todo
&& can_skip_message(expected
))
2662 expect_equal
= FALSE
;
2664 if (!expected
->message
|| !actual
->message
) {
2665 if (expect_equal
&& (!todo
|| !todo_reported
++))
2667 ok_( file
, line
) (FALSE
, "the msg sequence is not complete: expected %s %04x - actual %s %04x\n",
2668 message_type_name(expected
->flags
), expected
->message
, message_type_name(actual
->flags
), actual
->message
);
2672 if (expected
->message
!= actual
->message
||
2673 (expected
->flags
& message_type_flags
) != (actual
->flags
& message_type_flags
))
2675 if (expect_equal
&& (!todo
|| !todo_reported
++))
2677 ok_( file
, line
) (FALSE
, "the %s 0x%04x was expected, but got %s 0x%04x instead\n",
2678 message_type_name(expected
->flags
), expected
->message
, message_type_name(actual
->flags
), actual
->message
);
2682 if (expected
->flags
& optional
)
2684 /* If a message can be sent in 2 different ways at the same time, we may need to treat
2685 * them as unequal so that the optional message can be properly skipped. */
2686 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) {
2687 /* don't match messages if their defwinproc status differs */
2694 ok_( file
, line
) (TRUE
, "got %s 0x%04x as expected\n",
2695 message_type_name(expected
->flags
), expected
->message
);
2700 static BOOL
sequence_contains_message(const struct message
*expected
, const struct recvd_message
*actual
)
2702 while (expected
->message
)
2704 if (messages_equal(expected
, actual
, FALSE
, __FILE__
, __LINE__
))
2711 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
2713 const struct recvd_message
*actual
= sequence
;
2714 unsigned int count
= 0;
2716 trace_(file
, line
)("Failed sequence %s:\n", context
);
2717 while (expected
->message
&& actual
->message
)
2719 if (actual
->output
[0])
2721 trace_(file
, line
)( " %u: expected: %s %04x - actual: %s\n",
2722 count
, message_type_name(expected
->flags
), expected
->message
, actual
->output
);
2725 if (messages_equal(expected
, actual
, FALSE
, file
, line
))
2731 else if (can_skip_message(expected
) || sequence_contains_message(expected
, actual
))
2742 /* optional trailing messages */
2743 while (can_skip_message(expected
))
2745 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2750 if (expected
->message
)
2752 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2756 while (actual
->message
&& actual
->output
[0])
2758 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
2764 #define ok_sequence( exp, contx, todo) \
2765 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2768 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2769 const char *file
, int line
)
2771 static const struct recvd_message end_of_sequence
;
2772 const struct message
*expected
= expected_list
;
2773 const struct recvd_message
*actual
;
2774 int failcount
= 0, dump
= 0;
2775 unsigned int count
= 0;
2776 BOOL is_wine
= !strcmp(winetest_platform
, "wine");
2778 add_message(&end_of_sequence
);
2782 winetest_push_context("%s: %u", context
, count
);
2784 while (expected
->message
&& actual
->message
)
2786 if (messages_equal(expected
, actual
, !todo
, file
, line
))
2788 if (expected
->flags
& wparam
)
2790 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2795 ok_( file
, line
) (FALSE
,
2796 "in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2797 expected
->message
, expected
->wParam
, actual
->wParam
);
2799 if (is_wine
) goto done
;
2803 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2804 "in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2805 expected
->message
, expected
->wParam
, actual
->wParam
);
2806 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2810 if (expected
->flags
& lparam
)
2812 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2817 ok_( file
, line
) (FALSE
,
2818 "in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2819 expected
->message
, expected
->lParam
, actual
->lParam
);
2821 if (is_wine
) goto done
;
2825 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2826 "in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2827 expected
->message
, expected
->lParam
, actual
->lParam
);
2828 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2831 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2836 ok_( file
, line
) (FALSE
,
2837 "the msg 0x%04x should %shave been sent by DefWindowProc\n",
2838 expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2840 if (is_wine
) goto done
;
2844 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2845 "the msg 0x%04x should %shave been sent by DefWindowProc\n",
2846 expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2847 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2850 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2851 "the msg 0x%04x should %shave been sent by BeginPaint\n",
2852 expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2853 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2855 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2856 "the msg 0x%04x should have been %s\n",
2857 expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2858 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2860 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2861 "the msg 0x%04x was expected in %s\n",
2862 expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2863 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2870 * silently drop hook messages if there is no support for them
2872 else if (can_skip_message(expected
))
2879 todo_wine
messages_equal(expected
, actual
, TRUE
, file
, line
);
2884 else if (sequence_contains_message(expected
, actual
))
2896 winetest_pop_context();
2897 winetest_push_context("%s: %u", context
, count
);
2900 /* skip all optional trailing messages */
2901 while (can_skip_message(expected
))
2903 messages_equal(expected
, actual
, TRUE
, file
, line
); /* check for message todo's */
2910 if (expected
->message
|| actual
->message
) {
2913 messages_equal(expected
, actual
, TRUE
, file
, line
);
2916 if (is_wine
) goto done
;
2920 if (expected
->message
|| actual
->message
)
2923 messages_equal(expected
, actual
, TRUE
, file
, line
);
2926 if (todo
&& !failcount
&& !strcmp(winetest_platform
, "wine")) /* succeeded yet marked todo */
2929 ok_( file
, line
)( TRUE
, "marked \"todo_wine\" but succeeds\n");
2933 winetest_pop_context();
2934 if (dump
&& (!is_wine
|| winetest_debug
> 1)) dump_sequence(expected_list
, context
, file
, line
);
2938 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
2940 /******************************** MDI test **********************************/
2942 /* CreateWindow for MDI frame window, initially visible */
2943 static const struct message WmCreateMDIframeSeq
[] = {
2944 { HCBT_CREATEWND
, hook
},
2945 { WM_GETMINMAXINFO
, sent
},
2946 { WM_NCCREATE
, sent
},
2947 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2948 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
2949 { WM_CREATE
, sent
},
2950 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2951 { WM_NOTIFYFORMAT
, sent
|optional
},
2952 { WM_QUERYUISTATE
, sent
|optional
},
2953 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2954 { WM_GETMINMAXINFO
, sent
|optional
},
2955 { WM_NCCALCSIZE
, sent
|optional
},
2956 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2957 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2958 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2959 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2960 { HCBT_ACTIVATE
, hook
},
2961 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2962 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2963 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2964 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2965 { WM_NCACTIVATE
, sent
},
2966 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2967 { WM_ACTIVATE
, sent
|wparam
, 1 },
2968 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2969 { HCBT_SETFOCUS
, hook
},
2970 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2971 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2972 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2973 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2974 /* Win9x adds SWP_NOZORDER below */
2975 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2976 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2977 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
2978 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2982 /* DestroyWindow for MDI frame window, initially visible */
2983 static const struct message WmDestroyMDIframeSeq
[] = {
2984 { HCBT_DESTROYWND
, hook
},
2985 { 0x0090, sent
|optional
},
2986 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2987 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2988 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2989 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2990 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
2991 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2992 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
2993 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
2994 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2995 { WM_DESTROY
, sent
},
2996 { WM_NCDESTROY
, sent
},
2999 /* CreateWindow for MDI client window, initially visible */
3000 static const struct message WmCreateMDIclientSeq
[] = {
3001 { HCBT_CREATEWND
, hook
},
3002 { WM_NCCREATE
, sent
},
3003 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3004 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
3005 { WM_CREATE
, sent
},
3006 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
3007 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3008 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3010 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
3011 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3012 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3013 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3014 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3017 /* ShowWindow(SW_SHOW) for MDI client window */
3018 static const struct message WmShowMDIclientSeq
[] = {
3019 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3020 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3021 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3022 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3025 /* ShowWindow(SW_HIDE) for MDI client window */
3026 static const struct message WmHideMDIclientSeq
[] = {
3027 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3028 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3029 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
3030 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
3031 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3034 /* DestroyWindow for MDI client window, initially visible */
3035 static const struct message WmDestroyMDIclientSeq
[] = {
3036 { HCBT_DESTROYWND
, hook
},
3037 { 0x0090, sent
|optional
},
3038 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
3039 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3040 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3041 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3042 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3043 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3044 { WM_DESTROY
, sent
},
3045 { WM_NCDESTROY
, sent
},
3048 /* CreateWindow for MDI child window, initially visible */
3049 static const struct message WmCreateMDIchildVisibleSeq
[] = {
3050 { HCBT_CREATEWND
, hook
},
3051 { WM_NCCREATE
, sent
},
3052 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3053 { WM_CREATE
, sent
},
3054 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3055 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3057 /* Win2k sends wparam set to
3058 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3059 * while Win9x doesn't bother to set child window id according to
3060 * CLIENTCREATESTRUCT.idFirstChild
3062 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3063 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3064 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3065 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3066 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3067 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3068 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3069 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3070 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3072 /* Win9x: message sequence terminates here. */
3074 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3075 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3076 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3077 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3078 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3079 { WM_SETFOCUS
, sent
}, /* in MDI client */
3080 { HCBT_SETFOCUS
, hook
},
3081 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3082 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3083 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3084 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3085 { WM_SETFOCUS
, sent
|defwinproc
},
3086 { WM_MDIACTIVATE
, sent
|defwinproc
},
3089 /* WM_CHILDACTIVATE sent to disabled window */
3090 static const struct message WmChildActivateDisabledWindowSeq
[] = {
3091 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3094 /* WM_CHILDACTIVATE sent to enabled window */
3095 static const struct message WmChildActivateWindowSeq
[] = {
3096 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3097 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 },
3098 { WM_MDIACTIVATE
, sent
|defwinproc
},
3099 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3100 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3101 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3102 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3103 { HCBT_SETFOCUS
, hook
},
3104 { WM_KILLFOCUS
, sent
|defwinproc
},
3105 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3106 { WM_SETFOCUS
, sent
},
3107 { HCBT_SETFOCUS
, hook
},
3108 { WM_KILLFOCUS
, sent
},
3109 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3110 { WM_SETFOCUS
, sent
|defwinproc
},
3111 { WM_MDIACTIVATE
, sent
|defwinproc
},
3114 /* CreateWindow for MDI child window with invisible parent */
3115 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
3116 { HCBT_CREATEWND
, hook
},
3117 { WM_GETMINMAXINFO
, sent
},
3118 { WM_NCCREATE
, sent
},
3119 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3120 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
3121 { WM_CREATE
, sent
},
3122 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3123 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3125 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3126 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3127 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3128 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3129 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3130 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3132 /* Win9x: message sequence terminates here. */
3134 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3135 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3136 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3137 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3138 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3139 { WM_SETFOCUS
, sent
}, /* in MDI client */
3140 { HCBT_SETFOCUS
, hook
},
3141 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3142 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3143 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3144 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3145 { WM_SETFOCUS
, sent
|defwinproc
},
3146 { WM_MDIACTIVATE
, sent
|defwinproc
},
3149 /* DestroyWindow for MDI child window, initially visible */
3150 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
3151 { HCBT_DESTROYWND
, hook
},
3152 /* Win2k sends wparam set to
3153 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3154 * while Win9x doesn't bother to set child window id according to
3155 * CLIENTCREATESTRUCT.idFirstChild
3157 { 0x0090, sent
|optional
},
3158 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3159 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3160 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3161 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3162 { WM_ERASEBKGND
, sent
|parent
|optional
},
3163 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3165 /* { WM_DESTROY, sent }
3166 * Win9x: message sequence terminates here.
3169 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3170 { WM_KILLFOCUS
, sent
},
3171 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3172 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3173 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3174 { WM_SETFOCUS
, sent
}, /* in MDI client */
3176 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3177 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3178 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3179 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3180 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3181 { WM_SETFOCUS
, sent
}, /* in MDI client */
3183 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3185 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3186 { WM_KILLFOCUS
, sent
},
3187 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3188 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3189 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3190 { WM_SETFOCUS
, sent
}, /* in MDI client */
3192 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3193 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3194 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3195 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3196 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3197 { WM_SETFOCUS
, sent
}, /* in MDI client */
3199 { WM_DESTROY
, sent
},
3201 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3202 { WM_KILLFOCUS
, sent
},
3203 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3204 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3205 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3206 { WM_SETFOCUS
, sent
}, /* in MDI client */
3208 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3209 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3210 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3211 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3212 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3213 { WM_SETFOCUS
, sent
}, /* in MDI client */
3215 { WM_NCDESTROY
, sent
},
3218 /* CreateWindow for MDI child window, initially invisible */
3219 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
3220 { HCBT_CREATEWND
, hook
},
3221 { WM_NCCREATE
, sent
},
3222 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3223 { WM_CREATE
, sent
},
3224 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3225 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3227 /* Win2k sends wparam set to
3228 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3229 * while Win9x doesn't bother to set child window id according to
3230 * CLIENTCREATESTRUCT.idFirstChild
3232 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3235 /* DestroyWindow for MDI child window, initially invisible */
3236 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
3237 { HCBT_DESTROYWND
, hook
},
3238 /* Win2k sends wparam set to
3239 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3240 * while Win9x doesn't bother to set child window id according to
3241 * CLIENTCREATESTRUCT.idFirstChild
3243 { 0x0090, sent
|optional
},
3244 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3245 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3246 { WM_DESTROY
, sent
},
3247 { WM_NCDESTROY
, sent
},
3248 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
3249 { WM_PARENTNOTIFY
, sent
|wparam
|optional
, WM_DESTROY
}, /* MDI client */
3252 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
3253 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
3254 { HCBT_CREATEWND
, hook
},
3255 { WM_NCCREATE
, sent
},
3256 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3257 { WM_CREATE
, sent
},
3258 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3259 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3261 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3262 { WM_GETMINMAXINFO
, sent
},
3263 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3264 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3265 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3266 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3268 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3269 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3270 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3271 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3272 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3273 /* Win2k sends wparam set to
3274 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3275 * while Win9x doesn't bother to set child window id according to
3276 * CLIENTCREATESTRUCT.idFirstChild
3278 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3279 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3280 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3281 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3282 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3283 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3284 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3285 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3286 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
3288 /* Win9x: message sequence terminates here. */
3290 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3291 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
3292 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3293 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3294 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3295 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3296 { HCBT_SETFOCUS
, hook
|optional
},
3297 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3298 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3299 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3300 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3301 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3302 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3304 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3305 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3306 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3307 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3310 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
3311 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
3312 /* restore the 1st MDI child */
3313 { WM_SETREDRAW
, sent
|wparam
, 0 },
3314 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3315 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3316 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3317 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3318 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3319 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3321 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3322 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3323 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3324 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3325 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3326 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
3327 /* create the 2nd MDI child */
3328 { HCBT_CREATEWND
, hook
},
3329 { WM_NCCREATE
, sent
},
3330 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3331 { WM_CREATE
, sent
},
3332 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3333 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3335 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3336 { WM_GETMINMAXINFO
, sent
},
3337 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3338 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3339 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3340 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3341 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3343 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3344 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3345 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3346 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3347 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3348 /* Win2k sends wparam set to
3349 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3350 * while Win9x doesn't bother to set child window id according to
3351 * CLIENTCREATESTRUCT.idFirstChild
3353 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3354 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3355 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3356 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3357 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3358 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3359 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3360 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3362 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3363 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3365 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3367 /* Win9x: message sequence terminates here. */
3369 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3370 { HCBT_SETFOCUS
, hook
},
3371 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
3372 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
3373 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3374 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3375 { WM_SETFOCUS
, sent
}, /* in MDI client */
3376 { HCBT_SETFOCUS
, hook
},
3377 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3378 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3379 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3380 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3381 { WM_SETFOCUS
, sent
|defwinproc
},
3383 { WM_MDIACTIVATE
, sent
|defwinproc
},
3385 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3386 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3387 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3388 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3391 /* WM_MDICREATE MDI child window, initially visible and maximized */
3392 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
3393 { WM_MDICREATE
, sent
},
3394 { HCBT_CREATEWND
, hook
},
3395 { WM_NCCREATE
, sent
},
3396 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3397 { WM_CREATE
, sent
},
3398 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3399 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3401 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3402 { WM_GETMINMAXINFO
, sent
},
3403 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3404 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3405 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3406 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
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
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3413 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3415 /* Win2k sends wparam set to
3416 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3417 * while Win9x doesn't bother to set child window id according to
3418 * CLIENTCREATESTRUCT.idFirstChild
3420 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3421 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3422 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3424 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3426 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3427 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3428 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3430 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3431 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3433 /* Win9x: message sequence terminates here. */
3435 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3436 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3437 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3438 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3439 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
3440 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
3441 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3442 { HCBT_SETFOCUS
, hook
|optional
},
3443 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3444 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3445 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3446 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3447 { WM_SETFOCUS
, sent
|defwinproc
},
3449 { WM_MDIACTIVATE
, sent
|defwinproc
},
3452 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3453 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3454 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3455 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3458 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3459 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3460 { 0x0093, sent
|defwinproc
|optional
},
3461 { 0x0093, sent
|defwinproc
|optional
},
3462 { 0x0093, sent
|defwinproc
|optional
},
3463 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3464 { WM_MOVE
, sent
|defwinproc
},
3465 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3468 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3469 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3470 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3471 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3474 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3475 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3476 { 0x0093, sent
|optional
},
3477 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3478 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3480 { 0x0093, sent
|optional
},
3481 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3482 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client, not sent on Win7. */
3483 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3484 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
3485 { 0x0093, sent
|defwinproc
|optional
},
3486 { 0x0093, sent
|defwinproc
|optional
},
3487 { 0x0093, sent
|defwinproc
|optional
},
3488 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3489 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3493 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3494 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
3495 { HCBT_CREATEWND
, hook
},
3496 { WM_GETMINMAXINFO
, sent
},
3497 { WM_NCCREATE
, sent
},
3498 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3499 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
3500 { WM_CREATE
, sent
},
3501 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3502 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3503 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3504 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
3505 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3507 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3508 { WM_GETMINMAXINFO
, sent
},
3509 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3510 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3511 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3512 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3513 { WM_MOVE
, sent
|defwinproc
},
3514 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3516 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3517 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3518 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3519 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3520 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
3521 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3522 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3523 /* Win2k sends wparam set to
3524 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3525 * while Win9x doesn't bother to set child window id according to
3526 * CLIENTCREATESTRUCT.idFirstChild
3528 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3531 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3532 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
3533 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
3534 { HCBT_SYSCOMMAND
, hook
},
3535 { WM_CLOSE
, sent
|defwinproc
},
3536 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3538 /* bring the 1st MDI child to top */
3539 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
3540 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
3542 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3544 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
3545 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3546 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3548 /* maximize the 1st MDI child */
3549 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3550 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3551 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3552 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3553 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3554 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3555 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3557 /* restore the 2nd MDI child */
3558 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
3559 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
3560 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3561 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3563 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3565 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3566 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3568 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3570 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
3572 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3573 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3574 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3575 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3576 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3578 /* bring the 1st MDI child to top */
3579 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3580 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3581 { HCBT_SETFOCUS
, hook
},
3582 { WM_KILLFOCUS
, sent
|defwinproc
},
3583 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
3584 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3585 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3586 { WM_SETFOCUS
, sent
}, /* in MDI client */
3587 { HCBT_SETFOCUS
, hook
},
3588 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3589 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3590 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3591 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3592 { WM_SETFOCUS
, sent
|defwinproc
},
3593 { WM_MDIACTIVATE
, sent
|defwinproc
},
3594 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3596 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3597 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3598 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3599 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3600 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3601 { WM_MDIREFRESHMENU
, sent
},
3603 { HCBT_DESTROYWND
, hook
},
3604 /* Win2k sends wparam set to
3605 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3606 * while Win9x doesn't bother to set child window id according to
3607 * CLIENTCREATESTRUCT.idFirstChild
3609 { 0x0090, sent
|defwinproc
|optional
},
3610 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3611 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
3612 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3613 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3614 { WM_ERASEBKGND
, sent
|parent
|optional
},
3615 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3617 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3618 { WM_DESTROY
, sent
|defwinproc
},
3619 { WM_NCDESTROY
, sent
|defwinproc
},
3622 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3623 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
3624 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3625 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3626 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3627 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3628 { WM_ERASEBKGND
, sent
|parent
|optional
},
3629 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3631 { HCBT_SETFOCUS
, hook
},
3632 { WM_KILLFOCUS
, sent
},
3633 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3634 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3635 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3636 { WM_SETFOCUS
, sent
}, /* in MDI client */
3637 { HCBT_SETFOCUS
, hook
},
3638 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3639 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3640 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3641 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3642 { WM_SETFOCUS
, sent
},
3645 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3646 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3647 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3648 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3651 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3652 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3653 { 0x0093, sent
|defwinproc
|optional
},
3654 { 0x0093, sent
|defwinproc
|optional
},
3655 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3656 { WM_MOVE
, sent
|defwinproc
},
3657 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3660 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3661 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3662 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3663 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3666 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3667 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3668 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3669 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3672 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3673 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3674 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3675 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3678 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3679 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3680 { 0x0093, sent
|defwinproc
|optional
},
3681 { 0x0093, sent
|defwinproc
|optional
},
3682 { 0x0093, sent
|defwinproc
|optional
},
3683 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3684 { WM_MOVE
, sent
|defwinproc
},
3685 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3688 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3689 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3690 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3691 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3694 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3695 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3696 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3697 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3698 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3699 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI client */
3701 { 0x0093, sent
|defwinproc
|optional
},
3702 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
3703 { 0x0093, sent
|defwinproc
|optional
},
3704 { 0x0093, sent
|defwinproc
|optional
},
3705 { 0x0093, sent
|defwinproc
|optional
},
3706 { 0x0093, sent
|optional
},
3708 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3709 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3710 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI client */
3711 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame */
3712 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3713 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3716 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3717 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3718 { 0x0093, sent
|defwinproc
|optional
},
3719 { 0x0093, sent
|defwinproc
|optional
},
3720 { 0x0093, sent
|defwinproc
|optional
},
3721 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3722 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3723 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3724 { 0x0093, sent
|optional
},
3726 { WM_NCACTIVATE
, sent
|wparam
, 0 },
3727 { WM_MDIACTIVATE
, sent
},
3729 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3730 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3731 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3733 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3735 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3736 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3737 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3740 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3741 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3742 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3743 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3746 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3747 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3748 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3749 { WM_MOVE
, sent
|defwinproc
},
3750 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3753 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3754 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3755 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3756 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3757 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3758 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3759 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI client */
3760 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3761 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3763 { HCBT_SETFOCUS
, hook
},
3764 { WM_KILLFOCUS
, sent
},
3765 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3766 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3767 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3768 { WM_SETFOCUS
, sent
}, /* in MDI client */
3770 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3772 { HCBT_DESTROYWND
, hook
},
3773 /* Win2k sends wparam set to
3774 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3775 * while Win9x doesn't bother to set child window id according to
3776 * CLIENTCREATESTRUCT.idFirstChild
3778 { 0x0090, sent
|optional
},
3779 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3781 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3782 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3783 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3784 { WM_ERASEBKGND
, sent
|parent
|optional
},
3785 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3787 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3788 { WM_DESTROY
, sent
},
3789 { WM_NCDESTROY
, sent
},
3792 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3793 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3794 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3795 { WM_GETMINMAXINFO
, sent
},
3796 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3797 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3798 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3799 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3801 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3802 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3803 { HCBT_SETFOCUS
, hook
|optional
},
3804 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3805 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3806 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3807 { HCBT_SETFOCUS
, hook
|optional
},
3808 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3809 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3810 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3811 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3812 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3813 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3814 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3815 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3817 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3818 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3819 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3820 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3821 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3824 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3825 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3826 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3827 { WM_GETMINMAXINFO
, sent
},
3828 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
3829 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3830 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3831 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3832 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3834 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3835 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3836 { HCBT_SETFOCUS
, hook
|optional
},
3837 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3838 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3839 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3840 { HCBT_SETFOCUS
, hook
|optional
},
3841 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3842 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3843 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3844 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3845 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3846 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3847 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
3848 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child, not sent on Win8+. */
3849 { WM_SIZE
, sent
|defwinproc
|optional
},
3850 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* w1064v1809. */
3853 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3854 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3855 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3856 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3857 { WM_GETMINMAXINFO
, sent
},
3858 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3859 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3860 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3861 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3862 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3863 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3864 { WM_MOVE
, sent
|defwinproc
},
3865 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3867 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3868 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3869 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3870 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3871 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3872 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3874 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3875 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3876 { 0x0093, sent
|defwinproc
|optional
},
3877 { 0x0094, sent
|defwinproc
|optional
},
3878 { 0x0094, sent
|defwinproc
|optional
},
3879 { 0x0094, sent
|defwinproc
|optional
},
3880 { 0x0094, sent
|defwinproc
|optional
},
3881 { 0x0093, sent
|defwinproc
|optional
},
3882 { 0x0093, sent
|defwinproc
|optional
},
3883 { 0x0091, sent
|defwinproc
|optional
},
3884 { 0x0092, sent
|defwinproc
|optional
},
3885 { 0x0092, sent
|defwinproc
|optional
},
3886 { 0x0092, sent
|defwinproc
|optional
},
3887 { 0x0092, sent
|defwinproc
|optional
},
3888 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3889 { WM_MOVE
, sent
|defwinproc
},
3890 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3891 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3893 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3894 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3895 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3896 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3898 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3899 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3900 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3901 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3902 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3903 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3904 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3905 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3906 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3907 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3909 { 0x0093, sent
|optional
},
3910 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3911 { 0x0093, sent
|defwinproc
|optional
},
3912 { 0x0093, sent
|defwinproc
|optional
},
3913 { 0x0093, sent
|defwinproc
|optional
},
3914 { 0x0091, sent
|defwinproc
|optional
},
3915 { 0x0092, sent
|defwinproc
|optional
},
3916 { 0x0092, sent
|defwinproc
|optional
},
3917 { 0x0092, sent
|defwinproc
|optional
},
3918 { 0x0092, sent
|defwinproc
|optional
},
3919 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3920 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3921 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3924 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3925 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3926 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3927 { WM_GETMINMAXINFO
, sent
},
3928 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3929 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3930 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3931 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3932 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3934 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3935 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3936 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3937 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3938 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3941 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3942 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3943 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3944 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3945 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3946 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3947 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3948 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3950 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3951 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3952 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3953 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3954 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3957 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3958 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3959 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3960 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3961 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3962 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3963 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3964 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3965 { WM_MOVE
, sent
|defwinproc
},
3966 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3967 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3968 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3969 { HCBT_SETFOCUS
, hook
},
3970 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3971 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3972 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3973 { WM_SETFOCUS
, sent
},
3976 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3977 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
3978 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
3979 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3980 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3981 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3982 { WM_MOVE
, sent
|defwinproc
},
3983 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
3984 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
3985 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3986 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3987 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3988 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
}, /* MDI client */
3991 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3992 static const struct message WmRestoreMDIchildInvisibleSeq
[] = {
3993 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3994 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3995 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3996 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3997 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3998 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3999 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
4001 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
4002 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
4003 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
4004 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
4005 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
4009 static HWND mdi_client
;
4010 static WNDPROC old_mdi_client_proc
;
4012 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4014 struct recvd_message msg
;
4016 /* do not log painting messages */
4017 if (message
!= WM_PAINT
&&
4018 message
!= WM_NCPAINT
&&
4019 message
!= WM_SYNCPAINT
&&
4020 message
!= WM_ERASEBKGND
&&
4021 message
!= WM_NCHITTEST
&&
4022 message
!= WM_GETTEXT
&&
4023 message
!= WM_MDIGETACTIVE
&&
4024 !ignore_message( message
))
4027 msg
.message
= message
;
4028 msg
.flags
= sent
|wparam
|lparam
;
4029 msg
.wParam
= wParam
;
4030 msg
.lParam
= lParam
;
4031 msg
.descr
= "mdi client";
4035 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
4038 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4040 static LONG defwndproc_counter
= 0;
4042 struct recvd_message msg
;
4044 /* do not log painting messages */
4045 if (message
!= WM_PAINT
&&
4046 message
!= WM_NCPAINT
&&
4047 message
!= WM_SYNCPAINT
&&
4048 message
!= WM_ERASEBKGND
&&
4049 message
!= WM_NCHITTEST
&&
4050 message
!= WM_GETTEXT
&&
4051 !ignore_message( message
))
4055 case WM_MDIACTIVATE
:
4057 HWND active
, client
= GetParent(hwnd
);
4059 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
4061 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
4062 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
4064 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
4070 msg
.message
= message
;
4071 msg
.flags
= sent
|wparam
|lparam
;
4072 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4073 msg
.wParam
= wParam
;
4074 msg
.lParam
= lParam
;
4075 msg
.descr
= "mdi child";
4079 defwndproc_counter
++;
4080 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
4081 defwndproc_counter
--;
4086 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4088 static LONG defwndproc_counter
= 0;
4090 struct recvd_message msg
;
4092 /* do not log painting messages */
4093 if (message
!= WM_PAINT
&&
4094 message
!= WM_NCPAINT
&&
4095 message
!= WM_SYNCPAINT
&&
4096 message
!= WM_ERASEBKGND
&&
4097 message
!= WM_NCHITTEST
&&
4098 message
!= WM_GETTEXT
&&
4099 !ignore_message( message
))
4102 msg
.message
= message
;
4103 msg
.flags
= sent
|wparam
|lparam
;
4104 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4105 msg
.wParam
= wParam
;
4106 msg
.lParam
= lParam
;
4107 msg
.descr
= "mdi frame";
4111 defwndproc_counter
++;
4112 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
4113 defwndproc_counter
--;
4118 static void mdi_register_classes(void)
4124 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
4127 cls
.hInstance
= GetModuleHandleA(0);
4129 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
4130 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
4131 cls
.lpszMenuName
= NULL
;
4132 cls
.lpszClassName
= "MDI_frame_class";
4133 register_class(&cls
);
4135 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
4136 cls
.lpszClassName
= "MDI_child_class";
4137 register_class(&cls
);
4139 ret
= GetClassInfoA(0, "MDIClient", &cls
);
4140 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
4141 old_mdi_client_proc
= cls
.lpfnWndProc
;
4142 cls
.hInstance
= GetModuleHandleA(0);
4143 cls
.lpfnWndProc
= mdi_client_hook_proc
;
4144 cls
.lpszClassName
= "MDI_client_class";
4145 register_class(&cls
);
4148 static void test_mdi_messages(void)
4150 MDICREATESTRUCTA mdi_cs
;
4151 CLIENTCREATESTRUCT client_cs
;
4152 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
4155 HMENU hMenu
= CreateMenu();
4158 mdi_register_classes();
4162 if (winetest_debug
> 1) trace("creating MDI frame window\n");
4163 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
4164 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
4165 WS_MAXIMIZEBOX
| WS_VISIBLE
,
4166 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
4167 GetDesktopWindow(), hMenu
,
4168 GetModuleHandleA(0), NULL
);
4169 ok(!!mdi_frame
, "Failed to create window, error %lu.\n", GetLastError());
4170 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
4172 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4173 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
4175 if (winetest_debug
> 1) trace("creating MDI client window\n");
4176 GetClientRect(mdi_frame
, &rc
);
4177 client_cs
.hWindowMenu
= 0;
4178 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
4179 mdi_client
= CreateWindowExA(0, "MDI_client_class",
4181 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
4182 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
4183 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4184 ok(!!mdi_client
, "Failed to create window, error %lu.\n", GetLastError());
4185 SetWindowLongA(mdi_client
, 0, 0xdeadbeef);
4187 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
4188 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4189 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
4191 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4192 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4193 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4198 if (winetest_debug
> 1) trace("creating invisible MDI child window\n");
4199 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4201 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4202 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4203 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4206 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
4207 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
4209 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4210 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4212 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4213 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4215 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4216 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4217 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4219 ShowWindow(mdi_child
, SW_HIDE
);
4220 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
4223 ShowWindow(mdi_child
, SW_SHOW
);
4224 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
4226 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4227 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4229 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4230 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4232 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4233 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4234 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4236 DestroyWindow(mdi_child
);
4239 if (winetest_debug
> 1) trace("creating visible MDI child window\n");
4240 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4241 WS_CHILD
| WS_VISIBLE
,
4242 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4243 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4244 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4245 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
4247 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4248 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4250 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4251 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4253 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4254 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4255 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4258 DestroyWindow(mdi_child
);
4259 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4261 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4262 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4264 /* Win2k: MDI client still returns a just destroyed child as active
4265 * Win9x: MDI client returns 0
4267 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4268 ok(active_child
== mdi_child
|| /* win2k */
4269 !active_child
, /* win9x */
4270 "wrong active MDI child %p\n", active_child
);
4271 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4275 if (winetest_debug
> 1) trace("creating invisible MDI child window\n");
4276 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4278 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4279 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4280 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4281 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
4283 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
4284 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
4286 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4287 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4289 /* Win2k: MDI client still returns a just destroyed child as active
4290 * Win9x: MDI client returns mdi_child2
4292 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4293 ok(active_child
== mdi_child
|| /* win2k */
4294 active_child
== mdi_child2
, /* win9x */
4295 "wrong active MDI child %p\n", active_child
);
4296 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4299 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4300 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
4302 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4303 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4305 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4306 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4307 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4310 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4311 ok(GetFocus() == mdi_child2
|| /* win2k */
4312 GetFocus() == 0, /* win9x */
4313 "wrong focus window %p\n", GetFocus());
4318 ShowWindow(mdi_child2
, SW_HIDE
);
4319 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4321 ShowWindow(mdi_child2
, SW_RESTORE
);
4322 ok_sequence(WmRestoreMDIchildInvisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
4325 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4326 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4328 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4329 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4330 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4336 ShowWindow(mdi_child2
, SW_HIDE
);
4337 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4339 ShowWindow(mdi_child2
, SW_SHOW
);
4340 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
4342 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4343 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4345 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4346 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
4348 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4349 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4351 ShowWindow(mdi_child2
, SW_RESTORE
);
4352 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
4354 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4355 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4357 ShowWindow(mdi_child2
, SW_MINIMIZE
);
4358 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", FALSE
);
4360 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4361 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4363 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4364 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4365 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4368 ShowWindow(mdi_child2
, SW_RESTORE
);
4369 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
4371 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4372 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4374 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4375 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4376 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4382 ShowWindow(mdi_child2
, SW_HIDE
);
4383 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4385 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4386 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4388 DestroyWindow(mdi_child2
);
4389 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
4391 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4392 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4394 if (winetest_debug
> 1) trace("Testing WM_CHILDACTIVATE\n");
4396 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4397 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_DISABLED
,
4398 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4399 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4401 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4402 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
,
4403 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4404 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4406 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4407 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4408 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4411 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4412 ok_sequence(WmChildActivateDisabledWindowSeq
, "WM_CHILDACTIVATE sent to disabled window", FALSE
);
4414 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4415 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4416 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4419 EnableWindow(mdi_child
, TRUE
);
4421 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4422 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4423 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4426 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4427 ok_sequence(WmChildActivateWindowSeq
, "WM_CHILDACTIVATE sent to enabled window", FALSE
);
4429 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4430 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4431 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4434 DestroyWindow(mdi_child
);
4435 DestroyWindow(mdi_child2
);
4438 /* test for maximized MDI children */
4439 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 1\n");
4440 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4441 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4442 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4443 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4444 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4445 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
4446 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4448 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4449 ok(GetFocus() == mdi_child
|| /* win2k */
4450 GetFocus() == 0, /* win9x */
4451 "wrong focus window %p\n", GetFocus());
4453 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4454 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4455 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4458 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 2\n");
4459 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4460 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4461 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4462 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4463 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4464 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4465 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4466 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4468 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4469 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4471 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4472 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4473 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4476 if (winetest_debug
> 1) trace("destroying maximized visible MDI child window 2\n");
4477 DestroyWindow(mdi_child2
);
4478 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4480 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4482 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4483 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4485 /* Win2k: MDI client still returns a just destroyed child as active
4486 * Win9x: MDI client returns 0
4488 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4489 ok(active_child
== mdi_child2
|| /* win2k */
4490 !active_child
, /* win9x */
4491 "wrong active MDI child %p\n", active_child
);
4494 ShowWindow(mdi_child
, SW_MAXIMIZE
);
4495 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4498 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4499 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4501 if (winetest_debug
> 1) trace("re-creating maximized visible MDI child window 2\n");
4502 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4503 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4504 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4505 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4506 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4507 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4508 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4509 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4511 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4512 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4514 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4515 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4516 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4519 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
4520 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
4521 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
4523 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4524 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4525 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4527 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4528 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4529 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4532 DestroyWindow(mdi_child
);
4533 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4535 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4536 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4538 /* Win2k: MDI client still returns a just destroyed child as active
4539 * Win9x: MDI client returns 0
4541 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4542 ok(active_child
== mdi_child
|| /* win2k */
4543 !active_child
, /* win9x */
4544 "wrong active MDI child %p\n", active_child
);
4547 if (winetest_debug
> 1) trace("creating maximized invisible MDI child window\n");
4548 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4549 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
4550 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4551 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4552 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4553 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
4554 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4555 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
4556 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
4558 /* Win2k: MDI client still returns a just destroyed child as active
4559 * Win9x: MDI client returns 0
4561 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4562 ok(active_child
== mdi_child
|| /* win2k */
4563 !active_child
|| active_child
== mdi_child2
, /* win9x */
4564 "wrong active MDI child %p\n", active_child
);
4567 if (winetest_debug
> 1) trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4568 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4569 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
4570 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4571 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4572 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4574 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4575 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4576 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4579 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4582 /* end of test for maximized MDI children */
4585 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 1(Switch test)\n");
4586 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4587 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4588 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4589 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4590 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4591 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
4592 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
4594 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4595 ok(GetFocus() == mdi_child
|| /* win2k */
4596 GetFocus() == 0, /* win9x */
4597 "wrong focus window %p(Switch test)\n", GetFocus());
4599 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4600 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4601 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4604 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 2(Switch test)\n");
4605 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4606 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4607 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4608 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4609 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4610 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
4612 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
4613 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
4615 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4616 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
4618 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4619 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
4620 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4623 if (winetest_debug
> 1) trace("Switch child window.\n");
4624 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
4625 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
4626 if (winetest_debug
> 1) trace("end of test for switch maximized MDI children\n");
4629 /* Prepare for switching test of not maximized MDI children */
4630 ShowWindow( mdi_child
, SW_NORMAL
);
4631 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
4632 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
4633 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
4634 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4637 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
4638 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
4639 if (winetest_debug
> 1) trace("end of test for switch not maximized MDI children\n");
4642 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4645 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4650 /* end of tests for switch maximized/not maximized MDI children */
4652 mdi_cs
.szClass
= "MDI_child_Class";
4653 mdi_cs
.szTitle
= "MDI child";
4654 mdi_cs
.hOwner
= GetModuleHandleA(0);
4657 mdi_cs
.cx
= CW_USEDEFAULT
;
4658 mdi_cs
.cy
= CW_USEDEFAULT
;
4659 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
4661 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
4662 ok(mdi_child
!= 0, "MDI child creation failed\n");
4663 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
4665 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
4667 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4668 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4670 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
4671 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4672 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4674 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4675 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4676 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4679 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4680 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
4682 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
4683 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4684 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4689 val
= GetWindowLongA(mdi_client
, 0);
4690 ok(val
== 0xdeadbeef || broken(val
== 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%lx\n", val
);
4691 DestroyWindow(mdi_client
);
4692 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4694 /* test maximization of MDI child with invisible parent */
4695 client_cs
.hWindowMenu
= 0;
4696 mdi_client
= CreateWindowA("MDI_client_class",
4698 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
4700 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4701 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
4703 ShowWindow(mdi_client
, SW_HIDE
);
4704 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
4706 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4707 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
4709 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4710 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
4712 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
4713 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
4714 zoomed
= IsZoomed(mdi_child
);
4715 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4717 ShowWindow(mdi_client
, SW_SHOW
);
4718 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
4720 DestroyWindow(mdi_child
);
4721 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
4723 /* end of test for maximization of MDI child with invisible parent */
4725 DestroyWindow(mdi_client
);
4726 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4728 DestroyWindow(mdi_frame
);
4729 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
4731 /************************* End of MDI test **********************************/
4733 static void test_WM_SETREDRAW(HWND hwnd
)
4735 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4740 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
4741 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
4743 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
4744 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
4747 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
4748 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
4750 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4751 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
4753 /* restore original WS_VISIBLE state */
4754 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4760 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4762 struct recvd_message msg
;
4764 if (ignore_message( message
)) return 0;
4770 case WM_NCMOUSEMOVE
:
4771 case WM_NCMOUSELEAVE
:
4779 msg
.message
= message
;
4780 msg
.flags
= sent
|wparam
|lparam
;
4781 msg
.wParam
= wParam
;
4782 msg
.lParam
= lParam
;
4783 msg
.descr
= "dialog";
4786 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
4787 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
4791 static INT_PTR CALLBACK
TestModalDlgProc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4793 struct recvd_message msg
;
4795 if (ignore_message( message
)) return 0;
4801 case WM_NCMOUSEMOVE
:
4802 case WM_NCMOUSELEAVE
:
4810 msg
.message
= message
;
4811 msg
.flags
= sent
|wparam
|lparam
;
4812 msg
.wParam
= wParam
;
4813 msg
.lParam
= lParam
;
4814 msg
.descr
= "dialog";
4817 if (message
== WM_INITDIALOG
) EndDialog( hwnd
, 0 );
4821 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4823 DWORD style
, exstyle
;
4827 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4828 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4829 /* do not be confused by WS_DLGFRAME set */
4830 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4832 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
4833 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
4835 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4836 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4837 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4838 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
4840 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
4842 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4843 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
4844 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
4846 /* a subsequent call should do nothing */
4847 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4848 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4849 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4853 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
4854 ok( ret
, "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4855 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4856 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
4857 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
4860 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4862 DWORD style
, exstyle
;
4866 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4867 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4868 /* do not be confused by WS_DLGFRAME set */
4869 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4871 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
4872 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
4874 si
.cbSize
= sizeof(si
);
4875 si
.fMask
= SIF_RANGE
;
4878 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4879 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4880 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4882 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4884 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4885 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
4886 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
4888 /* a subsequent call should do nothing */
4889 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4890 if (style
& WS_HSCROLL
)
4891 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4892 else if (style
& WS_VSCROLL
)
4893 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4895 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4897 si
.fMask
= SIF_PAGE
;
4899 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4900 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4904 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4905 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4907 si
.fMask
= SIF_RANGE
;
4908 si
.nMin
= 0xdeadbeef;
4909 si
.nMax
= 0xdeadbeef;
4910 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4911 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
4912 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4913 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4914 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4917 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4918 static void test_scroll_messages(HWND hwnd
)
4929 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4930 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
4931 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4932 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4933 /* values of min and max are undefined */
4936 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4937 ok( ret
, "SetScrollRange error %ld\n", GetLastError());
4938 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4939 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4944 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4945 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
4946 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4947 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4948 /* values of min and max are undefined */
4951 si
.cbSize
= sizeof(si
);
4952 si
.fMask
= SIF_RANGE
;
4955 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4956 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4957 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4960 si
.fMask
= SIF_PAGE
;
4962 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4963 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4964 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4969 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4970 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4971 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4974 si
.fMask
= SIF_RANGE
;
4975 si
.nMin
= 0xdeadbeef;
4976 si
.nMax
= 0xdeadbeef;
4977 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
4978 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
4979 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
4980 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4981 /* values of min and max are undefined */
4984 /* set WS_HSCROLL */
4985 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4986 /* clear WS_HSCROLL */
4987 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4989 /* set WS_HSCROLL */
4990 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4991 /* clear WS_HSCROLL */
4992 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4994 /* set WS_VSCROLL */
4995 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4996 /* clear WS_VSCROLL */
4997 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4999 /* set WS_VSCROLL */
5000 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
5001 /* clear WS_VSCROLL */
5002 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
5005 static void test_showwindow(void)
5007 HWND hwnd
, hwnd2
, hchild
;
5010 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5011 100, 100, 200, 200, 0, 0, 0, NULL
);
5012 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5013 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5014 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
5015 ok (hchild
!= 0, "Failed to create child\n");
5018 /* ShowWindow( SW_SHOWNA) for invisible top level window */
5019 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
5020 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5021 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
5023 /* ShowWindow( SW_SHOWNA) for now visible top level window */
5024 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
5025 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5026 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
5027 /* back to invisible */
5028 ShowWindow(hchild
, SW_HIDE
);
5029 ShowWindow(hwnd
, SW_HIDE
);
5031 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
5032 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
5033 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5034 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
5035 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
5036 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
5038 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
5039 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5040 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
5041 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
5042 ShowWindow( hwnd
, SW_SHOW
);
5044 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
5045 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5046 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
5048 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
5049 ShowWindow( hchild
, SW_HIDE
);
5051 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
5052 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5053 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
5056 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
5057 DestroyWindow(hchild
);
5058 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
5060 DestroyWindow(hwnd
);
5065 * 1. Create invisible maximized popup window.
5066 * 2. Move and resize it.
5067 * 3. Show it maximized.
5069 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5070 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
5071 100, 100, 200, 200, 0, 0, 0, NULL
);
5072 ok (hwnd
!= 0, "Failed to create popup window\n");
5073 ok(IsZoomed(hwnd
), "window should be maximized\n");
5074 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5076 GetWindowRect(hwnd
, &rc
);
5077 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
5078 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
5079 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc
));
5080 /* Reset window's size & position */
5081 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
5082 ok(IsZoomed(hwnd
), "window should be maximized\n");
5085 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5086 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5087 ok(IsZoomed(hwnd
), "window should be maximized\n");
5088 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
5090 GetWindowRect(hwnd
, &rc
);
5091 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
5092 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
5093 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc
));
5094 DestroyWindow(hwnd
);
5098 * 1. Create invisible maximized popup window.
5099 * 2. Show it maximized.
5101 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5102 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
5103 100, 100, 200, 200, 0, 0, 0, NULL
);
5104 ok (hwnd
!= 0, "Failed to create popup window\n");
5105 ok(IsZoomed(hwnd
), "window should be maximized\n");
5106 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5108 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5109 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5110 ok(IsZoomed(hwnd
), "window should be maximized\n");
5111 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
5112 DestroyWindow(hwnd
);
5116 * 1. Create visible maximized popup window.
5118 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
5119 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
5120 100, 100, 200, 200, 0, 0, 0, NULL
);
5121 ok (hwnd
!= 0, "Failed to create popup window\n");
5122 ok(IsZoomed(hwnd
), "window should be maximized\n");
5123 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5124 DestroyWindow(hwnd
);
5128 * 1. Create visible popup window.
5131 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
5132 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
5133 100, 100, 200, 200, 0, 0, 0, NULL
);
5134 ok (hwnd
!= 0, "Failed to create popup window\n");
5135 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
5136 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
5138 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
5139 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5140 ok(IsZoomed(hwnd
), "window should be maximized\n");
5141 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
5142 DestroyWindow(hwnd
);
5146 * 1. Restoring a minimized window.
5148 hwnd
= CreateWindowA("TestWindowClass", "window1", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5149 ok(hwnd
!= NULL
, "Failed to create window\n");
5151 hwnd2
= CreateWindowA("static", "window2", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5152 ok(hwnd2
!= NULL
, "Failed to create window\n");
5154 ShowWindow(hwnd
, SW_MINIMIZE
);
5155 SetActiveWindow(hwnd2
);
5156 ok(GetActiveWindow() == hwnd2
, "Unexpected active window\n");
5159 ShowWindow(hwnd
, SW_RESTORE
);
5161 ok_sequence(WmShowRestoreMinimizedOverlappedSeq
,
5162 "ShowWindow(hwnd, SW_RESTORE): minimized overlapped", TRUE
);
5164 ShowWindow(hwnd
, SW_MINIMIZE
);
5165 SetActiveWindow(hwnd2
);
5166 ok(GetActiveWindow() == hwnd2
, "Unexpected active window\n");
5169 ShowWindow(hwnd
, SW_SHOWNOACTIVATE
);
5171 ok_sequence(WmShowNoActivateMinimizedOverlappedSeq
,
5172 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): minimized overlapped", TRUE
);
5174 DestroyWindow(hwnd2
);
5175 DestroyWindow(hwnd
);
5179 * 1. Restoring a minimized but active window.
5181 hwnd
= CreateWindowA("TestWindowClass", "parent", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5182 ok(hwnd
!= NULL
, "Failed to create window\n");
5184 ShowWindow(hwnd
, SW_MINIMIZE
);
5185 SetActiveWindow(hwnd
);
5186 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
5189 ShowWindow(hwnd
, SW_RESTORE
);
5191 ok_sequence(WmShowRestoreActiveMinimizedOverlappedSeq
,
5192 "ShowWindow(hwnd, SW_RESTORE): active minimized overlapped", TRUE
);
5194 ShowWindow(hwnd
, SW_MINIMIZE
);
5195 SetActiveWindow(hwnd
);
5196 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
5199 ShowWindow(hwnd
, SW_SHOWNOACTIVATE
);
5201 ok_sequence(WmShowNoActivateActiveMinimizedOverlappedSeq
,
5202 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): active minimized overlapped", TRUE
);
5204 DestroyWindow(hwnd
);
5208 static void test_sys_menu(void)
5214 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5215 100, 100, 200, 200, 0, 0, 0, NULL
);
5216 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5220 /* test existing window without CS_NOCLOSE style */
5221 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5222 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5224 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5225 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5226 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
5228 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
5229 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
5231 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5232 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5233 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
5235 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
5236 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
5238 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5239 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5240 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
5242 /* test whether removing WS_SYSMENU destroys a system menu */
5243 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
5244 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5246 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5247 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5249 DestroyWindow(hwnd
);
5251 /* test new window with CS_NOCLOSE style */
5252 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5253 100, 100, 200, 200, 0, 0, 0, NULL
);
5254 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5256 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5257 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5259 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5260 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5262 DestroyWindow(hwnd
);
5264 /* test new window without WS_SYSMENU style */
5265 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
5266 100, 100, 200, 200, 0, 0, 0, NULL
);
5267 ok(hwnd
!= 0, "Failed to create overlapped window\n");
5269 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5270 ok(!hmenu
, "GetSystemMenu error %ld\n", GetLastError());
5272 DestroyWindow(hwnd
);
5275 /* For shown WS_OVERLAPPEDWINDOW */
5276 static const struct message WmSetIcon_1
[] = {
5277 { WM_SETICON
, sent
},
5278 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
5279 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5280 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
5284 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
5285 static const struct message WmSetIcon_2
[] = {
5286 { WM_SETICON
, sent
},
5290 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
5291 static const struct message WmInitEndSession
[] = {
5293 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
5297 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
5298 static const struct message WmInitEndSession_2
[] = {
5300 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
5304 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
5305 static const struct message WmInitEndSession_3
[] = {
5307 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
5311 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
5312 static const struct message WmInitEndSession_4
[] = {
5314 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
5318 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
5319 static const struct message WmInitEndSession_5
[] = {
5321 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
5325 static const struct message WmOptionalPaint
[] = {
5326 { WM_PAINT
, sent
|optional
},
5327 { WM_NCPAINT
, sent
|beginpaint
|optional
},
5328 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
5329 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
5333 static const struct message WmZOrder
[] = {
5334 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
5335 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
5336 { HCBT_ACTIVATE
, hook
},
5337 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
5338 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
5339 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
5340 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
5341 { WM_GETTEXT
, sent
|optional
},
5342 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
5343 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
5344 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
5345 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5346 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5347 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
5348 { HCBT_SETFOCUS
, hook
},
5349 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5350 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5351 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5352 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5353 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
5354 { WM_GETTEXT
, sent
|optional
},
5355 { WM_NCCALCSIZE
, sent
|optional
},
5356 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
5360 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
5365 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
5370 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5371 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5373 PostMessageA(hwnd
, WM_USER
, 0, 0);
5375 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5376 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5378 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5379 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5381 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5382 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5384 PostMessageA(hwnd
, WM_USER
, 0, 0);
5386 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5387 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5389 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5390 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5392 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
5393 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5394 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5396 PostMessageA(hwnd
, WM_USER
, 0, 0);
5398 /* new incoming message causes it to become signaled again */
5399 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5400 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5402 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5403 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5404 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5405 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5407 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
5408 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5409 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5410 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5412 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_INPUTAVAILABLE
);
5413 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5415 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5416 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5418 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
5419 ret
= QueueUserAPC( apc_test_proc
, GetCurrentThread(), 0 );
5420 ok(ret
, "QueueUserAPC failed %lu\n", GetLastError());
5422 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, 0 );
5423 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5425 /* but even with MWMO_ALERTABLE window events are preferred */
5426 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5428 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5429 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5431 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5432 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5434 /* the APC call is still queued */
5435 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5436 ok(ret
== WAIT_IO_COMPLETION
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5439 static void test_WM_DEVICECHANGE(HWND hwnd
)
5444 static const WPARAM wparams
[] = {0,
5445 DBT_DEVNODES_CHANGED
,
5446 DBT_QUERYCHANGECONFIG
,
5448 DBT_CONFIGCHANGECANCELED
,
5451 DBT_CONFIGMGPRIVATE
, /* 0x7fff */
5452 DBT_DEVICEARRIVAL
, /* 0x8000 */
5453 DBT_DEVICEQUERYREMOVE
,
5454 DBT_DEVICEQUERYREMOVEFAILED
,
5455 DBT_DEVICEREMOVEPENDING
,
5456 DBT_DEVICEREMOVECOMPLETE
,
5457 DBT_DEVICETYPESPECIFIC
,
5460 for (i
= 0; i
< ARRAY_SIZE(wparams
); i
++)
5462 SetLastError(0xdeadbeef);
5463 ret
= PostMessageA(hwnd
, WM_DEVICECHANGE
, wparams
[i
], 0);
5464 if (wparams
[i
] & 0x8000)
5466 ok(ret
== FALSE
, "PostMessage returned %ld\n", ret
);
5467 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY
, "PostMessage error %08lx\n", GetLastError());
5471 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5472 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5473 memset(&msg
, 0, sizeof(msg
));
5474 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5475 ok(msg
.message
== WM_DEVICECHANGE
, "got %04x instead of WM_DEVICECHANGE\n", msg
.message
);
5480 static DWORD CALLBACK
hide_window_thread( LPVOID arg
)
5484 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
5485 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5490 static DWORD CALLBACK
show_window_thread( LPVOID arg
)
5494 /* function will not return if ShowWindow(SW_SHOW) calls SendMessage() */
5495 ok( ShowWindow( hwnd
, SW_SHOW
), "ShowWindow(SW_SHOW) expected TRUE\n" ); /* actually it's 24... */
5500 /* Helper function to easier test SetWindowPos messages */
5501 #define test_msg_setpos( expected_list, flags, todo ) \
5502 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
5503 static void test_msg_setpos_(const struct message
*expected_list
, UINT flags
, BOOL todo
, const char *file
, int line
)
5509 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5510 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5511 ok (hwnd
!= 0, "Failed to create popup window\n");
5512 SetWindowPos(hwnd
, NULL
, 0, 0, 100, 100, flags
);
5513 ok_sequence_(expected_list
, "SetWindowPos:show_popup_first_show_window", todo
, file
, line
);
5514 DestroyWindow(hwnd
);
5517 /* test if we receive the right sequence of messages */
5518 static void test_messages(void)
5522 HWND hwnd
, hparent
, hchild
;
5523 HWND hchild2
, hbutton
;
5532 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5533 100, 100, 200, 200, 0, 0, 0, NULL
);
5534 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5535 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5537 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5538 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
5539 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
5541 /* test WM_SETREDRAW on a not visible top level window */
5542 test_WM_SETREDRAW(hwnd
);
5544 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5546 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
5547 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
5549 ok(GetActiveWindow() == hwnd
, "window should be active\n");
5550 ok(GetFocus() == hwnd
, "window should have input focus\n");
5551 ShowWindow(hwnd
, SW_HIDE
);
5553 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5555 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5556 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5558 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5560 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5561 hthread
= CreateThread( NULL
, 0, hide_window_thread
, hwnd
, 0, &tid
);
5562 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
5563 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5564 CloseHandle(hthread
);
5566 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5568 ShowWindow(hwnd
, SW_SHOW
);
5570 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
5572 /* test ShowWindow(SW_SHOW) on a visible window - multi-threaded */
5573 hthread
= CreateThread( NULL
, 0, show_window_thread
, hwnd
, 0, &tid
);
5574 ok( hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError() );
5575 ok( WaitForSingleObject( hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
5576 CloseHandle( hthread
);
5578 ok_sequence( WmEmptySeq
, "ShowWindow(SW_SHOW):overlapped", FALSE
);
5580 ShowWindow(hwnd
, SW_HIDE
);
5582 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5584 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5586 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
5589 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
5591 ShowWindow(hwnd
, SW_RESTORE
);
5593 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5597 ShowWindow(hwnd
, SW_MINIMIZE
);
5599 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE
);
5602 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
5604 ShowWindow(hwnd
, SW_RESTORE
);
5606 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", FALSE
);
5610 ShowWindow(hwnd
, SW_SHOW
);
5612 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
5614 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5615 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
5616 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
5617 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
5619 /* test WM_SETREDRAW on a visible top level window */
5620 ShowWindow(hwnd
, SW_SHOW
);
5622 test_WM_SETREDRAW(hwnd
);
5624 if (winetest_debug
> 1) trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
5625 test_scroll_messages(hwnd
);
5627 /* test resizing and moving */
5628 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
5629 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
5632 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
5633 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
5636 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
5637 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
5641 /* popups don't get WM_GETMINMAXINFO */
5642 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
5643 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5645 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
5646 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
5648 DestroyWindow(hwnd
);
5649 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
5651 /* Test if windows are correctly drawn when first shown */
5653 /* Visible, redraw */
5656 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5657 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5658 ok (hwnd
!= 0, "Failed to create popup window\n");
5659 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5660 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_visible", FALSE
);
5661 DestroyWindow(hwnd
);
5663 /* Invisible, show, message */
5666 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5667 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5668 ok (hwnd
!= 0, "Failed to create popup window\n");
5669 ShowWindow(hwnd
, SW_SHOW
);
5670 SendMessageW(hwnd
, WM_PAINT
, 0, 0);
5671 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_show", FALSE
);
5672 DestroyWindow(hwnd
);
5674 /* Invisible, show maximized, redraw */
5677 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5678 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5679 ok (hwnd
!= 0, "Failed to create popup window\n");
5680 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5681 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5682 ok_sequence(WmShowPopupFirstDrawSeq_2
, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE
);
5683 DestroyWindow(hwnd
);
5685 /* Test SetWindowPos */
5686 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
, FALSE
);
5687 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, 0, FALSE
);
5688 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
,
5689 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_NOZORDER
, FALSE
);
5691 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOSIZE
, FALSE
);
5692 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOMOVE
, FALSE
);
5693 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTSIZE
, FALSE
);
5694 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTMOVE
, FALSE
);
5695 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOZORDER
, FALSE
);
5697 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
, FALSE
);
5698 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTMOVE
, FALSE
);
5699 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTSIZE
, FALSE
);
5700 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOMOVE
, FALSE
);
5701 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOSIZE
, FALSE
);
5702 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOZORDER
, FALSE
);
5704 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
, FALSE
);
5705 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTMOVE
, FALSE
);
5706 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTSIZE
, FALSE
);
5707 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOMOVE
, FALSE
);
5708 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOSIZE
, FALSE
);
5709 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOZORDER
, FALSE
);
5711 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
, FALSE
);
5712 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTMOVE
, FALSE
);
5713 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTSIZE
, FALSE
);
5714 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOMOVE
, FALSE
);
5715 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOSIZE
, FALSE
);
5716 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOZORDER
, FALSE
);
5718 /* Test SetWindowPos with child windows */
5720 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5721 100, 100, 200, 200, 0, 0, 0, NULL
);
5722 ok (hparent
!= 0, "Failed to create parent window\n");
5724 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5725 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5726 ok (hchild
!= 0, "Failed to create child window\n");
5728 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5729 ok_sequence(WmFirstDrawChildSeq1
, /* Expect no messages for the child */
5730 "SetWindowPos:show_popup_first_show_window_child1", FALSE
);
5731 DestroyWindow(hchild
);
5732 DestroyWindow(hparent
);
5735 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
,
5736 100, 100, 200, 200, 0, 0, 0, NULL
);
5737 ok (hparent
!= 0, "Failed to create parent window\n");
5739 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5740 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5741 ok (hchild
!= 0, "Failed to create child window\n");
5743 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5744 ok_sequence(WmFirstDrawChildSeq2
, /* Expect child to be redrawn */
5745 "SetWindowPos:show_popup_first_show_window_child2", FALSE
);
5746 DestroyWindow(hchild
);
5747 DestroyWindow(hparent
);
5749 /* Test message sequence for extreme position and size */
5752 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5753 -10, -10, 10000, 10000, NULL
, 0, 0, NULL
);
5754 ok (hwnd
!= 0, "Failed to create popup window\n");
5755 ok_sequence(WmShowPopupExtremeLocationSeq
, "RedrawWindow:show_popup_extreme_location", FALSE
);
5756 DestroyWindow(hwnd
);
5759 /* Test child windows */
5761 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5762 100, 100, 200, 200, 0, 0, 0, NULL
);
5763 ok (hparent
!= 0, "Failed to create parent window\n");
5766 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
5767 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5768 ok (hchild
!= 0, "Failed to create child window\n");
5769 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
5770 DestroyWindow(hchild
);
5773 /* visible child window with a caption */
5774 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
5775 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
5776 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5777 ok (hchild
!= 0, "Failed to create child window\n");
5778 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
5780 if (winetest_debug
> 1) trace("testing scroll APIs on a visible child window %p\n", hchild
);
5781 test_scroll_messages(hchild
);
5783 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5784 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
5786 DestroyWindow(hchild
);
5789 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5790 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5791 ok (hchild
!= 0, "Failed to create child window\n");
5792 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5794 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
5795 100, 100, 50, 50, hparent
, 0, 0, NULL
);
5796 ok (hchild2
!= 0, "Failed to create child2 window\n");
5799 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
5800 0, 100, 50, 50, hchild
, 0, 0, NULL
);
5801 ok (hbutton
!= 0, "Failed to create button window\n");
5803 /* test WM_SETREDRAW on a not visible child window */
5804 test_WM_SETREDRAW(hchild
);
5806 ShowWindow(hchild
, SW_SHOW
);
5807 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5809 /* check parent messages too */
5810 log_all_parent_messages
++;
5811 ShowWindow(hchild
, SW_HIDE
);
5812 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
5813 log_all_parent_messages
--;
5815 ShowWindow(hchild
, SW_SHOW
);
5816 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5818 ShowWindow(hchild
, SW_HIDE
);
5819 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
5821 ShowWindow(hchild
, SW_SHOW
);
5822 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5824 /* test WM_SETREDRAW on a visible child window */
5825 test_WM_SETREDRAW(hchild
);
5827 log_all_parent_messages
++;
5828 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
5829 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
5830 log_all_parent_messages
--;
5832 ShowWindow(hchild
, SW_HIDE
);
5834 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5835 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
5837 ShowWindow(hchild
, SW_HIDE
);
5839 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
5840 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
5842 /* DestroyWindow sequence below expects that a child has focus */
5846 DestroyWindow(hchild
);
5847 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
5848 DestroyWindow(hchild2
);
5849 DestroyWindow(hbutton
);
5852 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
5853 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5854 ok (hchild
!= 0, "Failed to create child popup window\n");
5855 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
5856 DestroyWindow(hchild
);
5858 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5860 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
5861 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5862 ok (hchild
!= 0, "Failed to create popup window\n");
5863 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5864 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5865 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5867 ShowWindow(hchild
, SW_SHOW
);
5868 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5870 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5871 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5873 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5874 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
5875 DestroyWindow(hchild
);
5877 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5878 * changes nothing in message sequences.
5881 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5882 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5883 ok (hchild
!= 0, "Failed to create popup window\n");
5884 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5885 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5886 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5888 ShowWindow(hchild
, SW_SHOW
);
5889 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5891 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5892 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5893 DestroyWindow(hchild
);
5896 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
5897 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5898 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5899 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
5902 if (winetest_debug
> 1) trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
5903 test_scroll_messages(hwnd
);
5909 SendMessageA(hwnd
, WM_NULL
, 0, 0);
5912 after_end_dialog
= TRUE
;
5913 EndDialog( hwnd
, 0 );
5914 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
5916 DestroyWindow(hwnd
);
5917 after_end_dialog
= FALSE
;
5918 test_def_id
= FALSE
;
5920 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
5921 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5923 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
5924 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
5925 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5927 if (winetest_debug
> 1) trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
5928 ShowWindow(hwnd
, SW_SHOW
);
5929 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
5933 ret
= DrawMenuBar(hwnd
);
5934 ok(ret
, "DrawMenuBar failed: %ld\n", GetLastError());
5936 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5937 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
5939 DestroyWindow(hwnd
);
5941 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_CHILD
|WS_VISIBLE
,
5942 0, 0, 100, 100, hparent
, 0, GetModuleHandleA(0), NULL
);
5943 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5946 ret
= DrawMenuBar(hwnd
);
5947 ok(ret
, "DrawMenuBar failed: %ld\n", GetLastError());
5949 ok_sequence(WmEmptySeq
, "DrawMenuBar for a child window", FALSE
);
5951 DestroyWindow(hwnd
);
5954 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
5955 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
5957 DestroyWindow(hparent
);
5960 /* Message sequence for SetMenu */
5961 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
5962 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %ld\n", GetLastError());
5963 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
5965 hmenu
= CreateMenu();
5966 ok (hmenu
!= 0, "Failed to create menu\n");
5967 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
5968 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5969 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
5970 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5971 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5972 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
5973 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5974 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
5975 ShowWindow(hwnd
, SW_SHOW
);
5976 UpdateWindow( hwnd
);
5979 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5980 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
5981 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
5982 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
5984 UpdateWindow( hwnd
);
5987 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
5989 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5991 DestroyWindow(hwnd
);
5994 /* Message sequence for EnableWindow */
5995 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5996 100, 100, 200, 200, 0, 0, 0, NULL
);
5997 ok (hparent
!= 0, "Failed to create parent window\n");
5998 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5999 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6000 ok (hchild
!= 0, "Failed to create child window\n");
6006 EnableWindow(hparent
, FALSE
);
6007 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
6009 EnableWindow(hparent
, FALSE
);
6010 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(FALSE)", FALSE
);
6012 EnableWindow(hparent
, TRUE
);
6013 ok_sequence(WmEnableWindowSeq_3
, "EnableWindow(TRUE)", FALSE
);
6015 EnableWindow(hparent
, TRUE
);
6016 ok_sequence(WmEnableWindowSeq_4
, "EnableWindow(TRUE)", FALSE
);
6021 test_MsgWaitForMultipleObjects(hparent
);
6022 test_WM_DEVICECHANGE(hparent
);
6024 /* the following test causes an exception in user.exe under win9x */
6025 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
6027 DestroyWindow(hparent
);
6031 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
6032 /* PeekMessage(NULL) fails, but still removes the message */
6033 SetLastError(0xdeadbeef);
6034 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
6035 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
6036 GetLastError() == 0xdeadbeef, /* NT4 */
6037 "last error is %ld\n", GetLastError() );
6038 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
6039 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
6041 DestroyWindow(hchild
);
6042 DestroyWindow(hparent
);
6045 /* Message sequences for WM_SETICON */
6046 if (winetest_debug
> 1) trace("testing WM_SETICON\n");
6047 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
6048 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6050 ShowWindow(hwnd
, SW_SHOW
);
6054 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6055 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
6057 ShowWindow(hwnd
, SW_HIDE
);
6060 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6061 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
6062 DestroyWindow(hwnd
);
6065 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
6066 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6068 ShowWindow(hwnd
, SW_SHOW
);
6072 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6073 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
6075 ShowWindow(hwnd
, SW_HIDE
);
6078 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6079 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
6082 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
6085 todo_wine
win_skip( "Message 0x3b not supported\n" );
6088 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
6089 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %Id\n", res
);
6090 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
6091 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
6092 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %Id\n", res
);
6093 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
6094 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
6095 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %Id\n", res
);
6098 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
6099 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
6100 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %Id\n", res
);
6101 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
6102 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
6103 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %Id\n", res
);
6105 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
6106 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
6107 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %Id\n", res
);
6109 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
6110 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
6111 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %Id\n", res
);
6114 DestroyWindow(hwnd
);
6118 static const struct message WmFrameChanged
[] = {
6119 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
, 0 },
6120 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0xf },
6121 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
6122 |SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0xf },
6123 { WM_GETTEXT
, sent
|optional
},
6124 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6125 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
6129 static const struct message WmFrameChanged_move
[] = {
6130 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
, 0 },
6131 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0x3 },
6132 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
6133 |SWP_NOSIZE
|SWP_NOCLIENTSIZE
, 0x3 },
6134 { WM_MOVE
, sent
|defwinproc
, 0 },
6135 { WM_GETTEXT
, sent
|optional
},
6136 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6137 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
6141 static void test_setwindowpos(void)
6148 const INT winX
= 100;
6149 const INT winY
= 100;
6150 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
6152 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
6153 X
, Y
, winX
, winY
, 0,
6156 GetWindowRect(hwnd
, &rc
);
6157 expect(sysX
+ X
, rc
.right
);
6158 expect(winY
+ Y
, rc
.bottom
);
6162 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 50, 50, winX
, winY
, 0);
6163 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
6164 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id\n", res
);
6166 GetWindowRect(hwnd
, &rc
);
6167 expect(sysX
+ X
, rc
.right
);
6168 expect(winY
+ Y
, rc
.bottom
);
6170 res
= SetWindowPos( hwnd
, 0, 0, 0, 0, 0,
6171 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
6172 ok_sequence(WmFrameChanged
, "FrameChanged", FALSE
);
6173 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id.\n", res
);
6175 GetWindowRect(hwnd
, &rc
);
6176 expect(sysX
+ X
, rc
.right
);
6177 expect(winY
+ Y
, rc
.bottom
);
6179 res
= SetWindowPos( hwnd
, 0, 0, 0, 0, 0,
6180 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
6181 ok_sequence(WmFrameChanged_move
, "FrameChanged", FALSE
);
6182 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id.\n", res
);
6184 GetWindowRect(hwnd
, &rc
);
6185 expect(sysX
, rc
.right
);
6186 expect(winY
, rc
.bottom
);
6188 DestroyWindow(hwnd
);
6191 static void invisible_parent_tests(void)
6193 HWND hparent
, hchild
;
6195 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
6196 100, 100, 200, 200, 0, 0, 0, NULL
);
6197 ok (hparent
!= 0, "Failed to create parent window\n");
6200 /* test showing child with hidden parent */
6202 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6203 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6204 ok (hchild
!= 0, "Failed to create child window\n");
6205 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
6207 ShowWindow( hchild
, SW_MINIMIZE
);
6208 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
6209 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6210 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6215 ShowWindow( hchild
, SW_MINIMIZE
);
6216 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
6218 DestroyWindow(hchild
);
6219 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6220 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6223 ShowWindow( hchild
, SW_MAXIMIZE
);
6224 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
6225 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6226 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6231 ShowWindow( hchild
, SW_MAXIMIZE
);
6232 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
6234 DestroyWindow(hchild
);
6235 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6236 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6239 ShowWindow( hchild
, SW_RESTORE
);
6240 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
6241 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6242 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6244 DestroyWindow(hchild
);
6245 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6246 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6249 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
6250 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
6251 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6252 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6257 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
6258 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
6260 DestroyWindow(hchild
);
6261 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6262 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6265 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
6266 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
6267 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
6268 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6269 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6271 DestroyWindow(hchild
);
6272 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6273 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6276 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
6277 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
6278 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6279 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6284 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
6285 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
6287 DestroyWindow(hchild
);
6288 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6289 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6292 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
6293 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
6294 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
6296 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
6298 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6300 DestroyWindow(hchild
);
6301 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6302 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6305 ShowWindow( hchild
, SW_SHOWNA
);
6306 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
6307 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6308 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6313 ShowWindow( hchild
, SW_SHOWNA
);
6314 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
6316 DestroyWindow(hchild
);
6317 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6318 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6321 ShowWindow( hchild
, SW_SHOW
);
6322 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
6323 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6324 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6329 ShowWindow( hchild
, SW_SHOW
);
6330 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
6332 ShowWindow( hchild
, SW_HIDE
);
6333 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
6334 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
6335 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6337 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6338 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
6339 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6340 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6342 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6343 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
6344 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
6345 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6347 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6349 DestroyWindow(hchild
);
6350 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
6352 DestroyWindow(hparent
);
6356 /****************** button message test *************************/
6357 #define ID_BUTTON 0x000e
6359 static const struct message WmSetFocusButtonSeq
[] =
6361 { HCBT_SETFOCUS
, hook
},
6362 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6363 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6364 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6365 { WM_SETFOCUS
, sent
|wparam
, 0 },
6366 { WM_CTLCOLORBTN
, sent
|parent
},
6367 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6368 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6371 static const struct message WmKillFocusButtonSeq
[] =
6373 { HCBT_SETFOCUS
, hook
},
6374 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6375 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6376 { WM_CTLCOLORBTN
, sent
|parent
},
6377 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6378 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6379 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6380 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6382 { WM_CTLCOLORBTN
, sent
|parent
},
6385 static const struct message WmSetFocusStaticSeq
[] =
6387 { HCBT_SETFOCUS
, hook
},
6388 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6389 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6390 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6391 { WM_SETFOCUS
, sent
|wparam
, 0 },
6392 { WM_CTLCOLORSTATIC
, sent
|parent
},
6393 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6394 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
6395 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6398 static const struct message WmKillFocusStaticSeq
[] =
6400 { HCBT_SETFOCUS
, hook
},
6401 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6402 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6403 { WM_CTLCOLORSTATIC
, sent
|parent
},
6404 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6405 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6406 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6407 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6409 { WM_CTLCOLORSTATIC
, sent
|parent
},
6412 static const struct message WmSetFocusOwnerdrawSeq
[] =
6414 { HCBT_SETFOCUS
, hook
},
6415 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6416 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6417 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6418 { WM_SETFOCUS
, sent
|wparam
, 0 },
6419 { WM_CTLCOLORBTN
, sent
|parent
},
6420 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
6421 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6422 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6425 static const struct message WmKillFocusOwnerdrawSeq
[] =
6427 { HCBT_SETFOCUS
, hook
},
6428 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6429 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6430 { WM_CTLCOLORBTN
, sent
|parent
},
6431 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
6432 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6433 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6434 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6435 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6437 { WM_CTLCOLORBTN
, sent
|parent
},
6438 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6441 static const struct message WmLButtonDownSeq
[] =
6443 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6444 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6445 { HCBT_SETFOCUS
, hook
},
6446 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6447 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6448 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6449 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6450 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6451 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6452 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6453 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6456 static const struct message WmLButtonDownStaticSeq
[] =
6458 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6459 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6460 { HCBT_SETFOCUS
, hook
},
6461 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6462 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6463 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6464 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6465 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6466 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6467 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6468 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6471 static const struct message WmLButtonUpSeq
[] =
6473 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6474 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6475 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6476 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6477 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6478 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6481 static const struct message WmLButtonUpStaticSeq
[] =
6483 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6484 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6485 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6486 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6487 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6488 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6491 static const struct message WmLButtonUpAutoSeq
[] =
6493 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6494 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6495 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6496 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6497 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
6498 { BM_SETCHECK
, sent
|defwinproc
},
6499 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
, 0, 0 }, /* Sent here on Win7. */
6500 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6501 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6502 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
, 0, 0 }, /* Sent here on Win8+. */
6503 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6506 static const struct message WmLButtonUpBrokenSeq
[] =
6508 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6511 static const struct message WmSetFontButtonSeq
[] =
6513 { WM_SETFONT
, sent
},
6515 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6516 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6517 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
6520 static const struct message WmSetFontStaticSeq
[] =
6522 { WM_SETFONT
, sent
},
6524 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6525 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6528 static const struct message WmSetTextButtonSeq
[] =
6530 { WM_SETTEXT
, sent
},
6531 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6532 { WM_CTLCOLORBTN
, sent
|parent
},
6533 { WM_CTLCOLORBTN
, sent
|parent
},
6534 { WM_COMMAND
, sent
|parent
|optional
},
6535 { WM_DRAWITEM
, sent
|parent
|optional
},
6538 static const struct message WmSetTextStaticSeq
[] =
6540 { WM_SETTEXT
, sent
},
6541 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6542 { WM_CTLCOLORSTATIC
, sent
|parent
},
6543 { WM_CTLCOLORSTATIC
, sent
|parent
},
6546 static const struct message WmSetTextGroupSeq
[] =
6548 { WM_SETTEXT
, sent
},
6549 { WM_CTLCOLORSTATIC
, sent
|parent
},
6550 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6551 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6552 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6555 static const struct message WmSetTextInvisibleSeq
[] =
6557 { WM_SETTEXT
, sent
},
6558 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6561 static const struct message WmSetStyleButtonSeq
[] =
6563 { BM_SETSTYLE
, sent
},
6564 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6565 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6567 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6568 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6569 { WM_CTLCOLORBTN
, sent
|parent
},
6572 static const struct message WmSetStyleStaticSeq
[] =
6574 { BM_SETSTYLE
, sent
},
6575 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6576 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6578 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6579 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6580 { WM_CTLCOLORSTATIC
, sent
|parent
},
6583 static const struct message WmSetStyleUserSeq
[] =
6585 { BM_SETSTYLE
, sent
},
6586 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6587 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6589 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6590 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6591 { WM_CTLCOLORBTN
, sent
|parent
},
6592 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
6595 static const struct message WmSetStyleOwnerdrawSeq
[] =
6597 { BM_SETSTYLE
, sent
},
6598 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6599 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6601 { WM_NCPAINT
, sent
|optional
}, /* FIXME: Wine sends it */
6602 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6603 { WM_CTLCOLORBTN
, sent
|parent
},
6604 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
6605 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6608 static const struct message WmSetStateButtonSeq
[] =
6610 { BM_SETSTATE
, sent
},
6611 { WM_CTLCOLORBTN
, sent
|parent
},
6612 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6613 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6616 static const struct message WmSetStateStaticSeq
[] =
6618 { BM_SETSTATE
, sent
},
6619 { WM_CTLCOLORSTATIC
, sent
|parent
},
6620 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6621 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6624 static const struct message WmSetStateUserSeq
[] =
6626 { BM_SETSTATE
, sent
},
6627 { WM_CTLCOLORBTN
, sent
|parent
},
6628 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
6629 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6630 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6633 static const struct message WmSetStateOwnerdrawSeq
[] =
6635 { BM_SETSTATE
, sent
},
6636 { WM_CTLCOLORBTN
, sent
|parent
},
6637 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
6638 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6639 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6642 static const struct message WmClearStateButtonSeq
[] =
6644 { BM_SETSTATE
, sent
},
6645 { WM_CTLCOLORBTN
, sent
|parent
},
6646 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
6647 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6648 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6651 static const struct message WmDisableButtonSeq
[] =
6653 { WM_LBUTTONDOWN
, sent
},
6654 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6655 { BM_SETSTATE
, sent
|defwinproc
},
6656 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6657 { WM_CTLCOLORBTN
, sent
|optional
},
6658 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6659 { WM_LBUTTONUP
, sent
},
6660 { BM_SETSTATE
, sent
|defwinproc
},
6661 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
},
6662 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6663 { BM_SETCHECK
, sent
|defwinproc
|optional
},
6664 { WM_CTLCOLORBTN
, sent
|optional
},
6665 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6666 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6667 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6668 { WM_CAPTURECHANGED
, sent
|defwinproc
},
6669 { WM_COMMAND
, sent
},
6672 static const struct message WmClearStateOwnerdrawSeq
[] =
6674 { BM_SETSTATE
, sent
},
6675 { WM_CTLCOLORBTN
, sent
|parent
},
6676 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
6677 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6678 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6681 static const struct message WmSetCheckIgnoredSeq
[] =
6683 { BM_SETCHECK
, sent
},
6684 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6687 static const struct message WmSetCheckStaticSeq
[] =
6689 { BM_SETCHECK
, sent
},
6690 { WM_CTLCOLORSTATIC
, sent
|parent
},
6691 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
6692 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6696 static WNDPROC old_button_proc
;
6698 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6700 static LONG defwndproc_counter
= 0;
6702 struct recvd_message msg
;
6704 if (ignore_message( message
)) return 0;
6712 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
6714 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6720 MSG
*msg
= (MSG
*)lParam
;
6721 lParam
= MAKELPARAM(msg
->message
, msg
->wParam
);
6723 wParam
= (ULONG_PTR
)GetMenu(hwnd
);
6728 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6733 msg
.message
= message
;
6734 msg
.flags
= sent
|wparam
|lparam
;
6735 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6736 msg
.wParam
= wParam
;
6737 msg
.lParam
= lParam
;
6738 msg
.descr
= "button";
6742 defwndproc_counter
++;
6743 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
6744 defwndproc_counter
--;
6749 static void subclass_button(void)
6754 ret
= GetClassInfoA(0, "button", &cls
);
6755 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
6757 old_button_proc
= cls
.lpfnWndProc
;
6759 cls
.hInstance
= GetModuleHandleA(NULL
);
6760 cls
.lpfnWndProc
= button_hook_proc
;
6761 cls
.lpszClassName
= "my_button_class";
6762 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6763 register_class(&cls
);
6766 static void test_button_messages(void)
6772 const struct message
*setfocus
;
6773 const struct message
*killfocus
;
6774 const struct message
*setstyle
;
6775 const struct message
*setstate
;
6776 const struct message
*clearstate
;
6777 const struct message
*setcheck
;
6778 const struct message
*lbuttondown
;
6779 const struct message
*lbuttonup
;
6780 const struct message
*setfont
;
6781 const struct message
*settext
;
6783 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6784 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6785 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6786 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6787 WmSetTextButtonSeq
},
6788 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
6789 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6790 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6791 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6792 WmSetTextButtonSeq
},
6793 { BS_CHECKBOX
, DLGC_BUTTON
,
6794 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6795 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6796 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6797 WmSetTextStaticSeq
},
6798 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
6799 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6800 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6801 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6802 WmSetTextStaticSeq
},
6803 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6804 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6805 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6806 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6807 WmSetTextStaticSeq
},
6808 { BS_3STATE
, DLGC_BUTTON
,
6809 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6810 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6811 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6812 WmSetTextStaticSeq
},
6813 { BS_AUTO3STATE
, DLGC_BUTTON
,
6814 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6815 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6816 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6817 WmSetTextStaticSeq
},
6818 { BS_GROUPBOX
, DLGC_STATIC
,
6819 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6820 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
,
6821 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6822 WmSetTextGroupSeq
},
6823 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6824 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
6825 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
,
6826 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6827 WmSetTextButtonSeq
},
6828 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6829 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6830 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6831 NULL
/* avoid infinite loop */, WmLButtonUpBrokenSeq
, WmSetFontStaticSeq
,
6832 WmSetTextStaticSeq
},
6833 { BS_OWNERDRAW
, DLGC_BUTTON
,
6834 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
6835 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
,
6836 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6837 WmSetTextButtonSeq
},
6839 LOGFONTA logfont
= { 0 };
6840 HFONT zfont
, hfont2
;
6845 /* selection with VK_SPACE should capture button window */
6846 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
6847 0, 0, 50, 14, 0, 0, 0, NULL
);
6848 ok(hwnd
!= 0, "Failed to create button window\n");
6851 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
6852 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6853 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
6854 DestroyWindow(hwnd
);
6858 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6859 100, 100, 200, 200, 0, 0, 0, NULL
);
6860 ok(parent
!= 0, "Failed to create parent window\n");
6862 memset(&logfont
, 0, sizeof(logfont
));
6863 logfont
.lfHeight
= -12;
6864 logfont
.lfWeight
= FW_NORMAL
;
6865 strcpy(logfont
.lfFaceName
, "Tahoma");
6867 hfont2
= CreateFontIndirectA(&logfont
);
6868 ok(hfont2
!= NULL
, "Failed to create Tahoma font\n");
6870 for (i
= 0; i
< ARRAY_SIZE(button
); i
++)
6878 if (winetest_debug
> 1) trace("button style %08lx\n", button
[i
].style
);
6880 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
6881 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
6882 ok(hwnd
!= 0, "Failed to create button window\n");
6884 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6885 style
&= ~(WS_CHILD
| BS_NOTIFY
);
6886 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6887 if (button
[i
].style
== BS_USERBUTTON
)
6888 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %lx\n", style
);
6890 ok(style
== button
[i
].style
, "expected style %lx got %lx\n", button
[i
].style
, style
);
6892 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
6893 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08lx\n", i
, dlg_code
);
6895 ShowWindow(hwnd
, SW_SHOW
);
6902 log_all_parent_messages
++;
6904 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6906 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6907 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6908 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
6911 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6912 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6913 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
6915 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6917 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
6918 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6919 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6920 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
6922 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6923 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
6924 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
6925 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6927 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6928 ok(state
== 0, "expected state 0, got %04lx\n", state
);
6932 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
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
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
6937 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6938 ok(state
== 0x0004, "expected state 0x0004, got %04lx\n", state
);
6940 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6941 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6942 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6946 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
6947 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6948 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6949 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
6951 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6952 ok(state
== 0, "expected state 0, got %04lx\n", state
);
6954 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6955 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6956 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6958 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6959 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04lx\n", state
);
6963 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
6964 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6965 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6966 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
6968 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6969 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04lx\n", state
);
6971 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6972 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6973 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6977 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
6978 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6979 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6980 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
6982 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 1");
6983 sprintf(desc
, "button[%i]: WM_SETTEXT on a visible button", i
);
6984 ok_sequence(button
[i
].settext
, desc
, FALSE
);
6986 ShowWindow(hwnd
, SW_HIDE
);
6990 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 2");
6991 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6992 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6994 ShowWindow(hwnd
, SW_SHOW
);
6995 ShowWindow(parent
, SW_HIDE
);
6999 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 3");
7000 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
7001 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
7003 ShowWindow(parent
, SW_SHOW
);
7006 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
7007 if (button
[i
].style
== BS_PUSHBUTTON
||
7008 button
[i
].style
== BS_DEFPUSHBUTTON
||
7009 button
[i
].style
== BS_GROUPBOX
||
7010 button
[i
].style
== BS_USERBUTTON
||
7011 button
[i
].style
== BS_OWNERDRAW
)
7012 ok(state
== BST_UNCHECKED
, "expected check 0, got %04lx\n", state
);
7014 ok(state
== BST_CHECKED
, "expected check 1, got %04lx\n", state
);
7016 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7017 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
7018 if (button
[i
].style
== BS_RADIOBUTTON
||
7019 button
[i
].style
== BS_AUTORADIOBUTTON
)
7020 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04lx | WS_TABSTOP got %04lx\n", button
[i
].style
, style
);
7022 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
7024 log_all_parent_messages
--;
7026 DestroyWindow(hwnd
);
7028 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
7029 0, 0, 50, 14, 0, 0, 0, NULL
);
7030 ok(hwnd
!= 0, "Failed to create button window\n");
7032 SetForegroundWindow(hwnd
);
7035 SetActiveWindow(hwnd
);
7039 if (button
[i
].lbuttondown
)
7041 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
7042 sprintf(desc
, "button[%i]: WM_LBUTTONDOWN on a button", i
);
7043 ok_sequence(button
[i
].lbuttondown
, desc
, FALSE
);
7046 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
7047 sprintf(desc
, "button[%i]: WM_LBUTTONUP on a button", i
);
7048 ok_sequence(button
[i
].lbuttonup
, desc
, FALSE
);
7051 zfont
= GetStockObject(DEFAULT_GUI_FONT
);
7052 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
7054 sprintf(desc
, "button[%i]: WM_SETFONT on a button", i
);
7055 ok_sequence(button
[i
].setfont
, desc
, FALSE
);
7057 /* Test that original font is not selected back after painting */
7058 hdc
= CreateCompatibleDC(0);
7060 prevfont
= SelectObject(hdc
, hfont2
);
7061 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
7062 SendMessageA(hwnd
, WM_PRINTCLIENT
, (WPARAM
)hdc
, 0);
7063 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i
);
7064 SelectObject(hdc
, prevfont
);
7066 prevfont
= SelectObject(hdc
, hfont2
);
7067 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
7068 SendMessageA(hwnd
, WM_PAINT
, (WPARAM
)hdc
, 0);
7069 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PAINT\n", i
);
7070 SelectObject(hdc
, prevfont
);
7074 DestroyWindow(hwnd
);
7077 DeleteObject(hfont2
);
7078 DestroyWindow(parent
);
7080 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
7082 parent
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7083 100, 100, 200, 200, 0, 0, 0, NULL
);
7084 ok (hwnd
!= 0, "Failed to create overlapped window\n");
7086 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON
| WS_VISIBLE
| WS_CHILD
,
7087 0, 0, 50, 14, parent
, 0, 0, NULL
);
7089 EnableWindow(hwnd
, FALSE
);
7091 SendMessageA(hwnd
, WM_LBUTTONDOWN
, MK_LBUTTON
, 0);
7092 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
7093 ok_sequence(WmDisableButtonSeq
, "Mouseclick on a disabled button", FALSE
);
7095 DestroyWindow(hwnd
);
7096 DestroyWindow(parent
);
7099 static void test_button_bm_get_set_image(void)
7106 ICONINFO icon_info2x2
;
7112 DWORD default_style
= BS_PUSHBUTTON
| WS_TABSTOP
| WS_POPUP
| WS_VISIBLE
;
7116 hbmp1x1
= CreateCompatibleBitmap(hdc
, 1, 1);
7117 hbmp2x2
= CreateCompatibleBitmap(hdc
, 2, 2);
7118 ZeroMemory(&bm
, sizeof(bm
));
7119 ok(GetObjectW(hbmp1x1
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7120 ok(bm
.bmWidth
== 1 && bm
.bmHeight
== 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7121 bm
.bmWidth
, bm
.bmHeight
);
7122 ZeroMemory(&bm
, sizeof(bm
));
7123 ok(GetObjectW(hbmp2x2
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7124 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7125 bm
.bmWidth
, bm
.bmHeight
);
7127 hmask2x2
= CreateCompatibleBitmap(hdc
, 2, 2);
7128 ZeroMemory(&icon_info2x2
, sizeof(icon_info2x2
));
7129 icon_info2x2
.fIcon
= TRUE
;
7130 icon_info2x2
.hbmMask
= hmask2x2
;
7131 icon_info2x2
.hbmColor
= hbmp2x2
;
7132 hicon2x2
= CreateIconIndirect(&icon_info2x2
);
7134 ZeroMemory(&icon_info
, sizeof(icon_info
));
7135 ok(GetIconInfo(hicon2x2
, &icon_info
), "Expect GetIconInfo() success\n");
7136 ZeroMemory(&bm
, sizeof(bm
));
7137 ok(GetObjectW(icon_info
.hbmColor
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7138 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7139 bm
.bmWidth
, bm
.bmHeight
);
7140 DeleteObject(icon_info
.hbmColor
);
7141 DeleteObject(icon_info
.hbmMask
);
7143 /* Set bitmap with BS_BITMAP */
7144 hwnd
= CreateWindowA("Button", "test", default_style
| BS_BITMAP
, 0, 0, 100, 100, 0, 0, 0, 0);
7145 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7146 SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7147 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7148 ok(hbmp
!= 0, "Expect hbmp not 0\n");
7149 ZeroMemory(&bm
, sizeof(bm
));
7150 ok(GetObjectW(hbmp
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7151 ok(bm
.bmWidth
== 1 && bm
.bmHeight
== 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7152 bm
.bmWidth
, bm
.bmHeight
);
7153 DestroyWindow(hwnd
);
7155 /* Set bitmap without BS_BITMAP */
7156 hwnd
= CreateWindowA("Button", "test", default_style
, 0, 0, 100, 100, 0, 0, 0, 0);
7157 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7158 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7159 ok(ret
== 0, "Expect ret to be 0\n");
7160 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7161 ok(hbmp
== NULL
, "Expect hbmp to be NULL\n");
7162 DestroyWindow(hwnd
);
7164 /* Set icon with BS_ICON */
7165 hwnd
= CreateWindowA("Button", "test", default_style
| BS_ICON
, 0, 0, 100, 100, 0, 0, 0, 0);
7166 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7167 SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7168 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7169 ok(hicon
!= NULL
, "Expect hicon not NULL\n");
7170 ZeroMemory(&icon_info
, sizeof(icon_info
));
7171 ok(GetIconInfo(hicon
, &icon_info
), "Expect GetIconInfo() success\n");
7172 ZeroMemory(&bm
, sizeof(bm
));
7173 ok(GetObjectW(icon_info
.hbmColor
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7174 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7175 bm
.bmWidth
, bm
.bmHeight
);
7176 DeleteObject(icon_info
.hbmColor
);
7177 DeleteObject(icon_info
.hbmMask
);
7178 DestroyWindow(hwnd
);
7180 /* Set icon without BS_ICON */
7181 hwnd
= CreateWindowA("Button", "test", default_style
, 0, 0, 100, 100, 0, 0, 0, 0);
7182 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7183 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7184 ok(ret
== 0, "Expect ret to be 0\n");
7185 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7186 ok(hicon
== NULL
, "Expect hicon to be NULL\n");
7187 DestroyWindow(hwnd
);
7189 /* Set icon with BS_BITMAP */
7190 hwnd
= CreateWindowA("Button", "test", default_style
| BS_BITMAP
, 0, 0, 100, 100, 0, 0, 0, 0);
7191 ok(hwnd
!= NULL
, "Expect hwnd to be not NULL\n");
7192 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7193 ok(ret
== 0, "Expect ret to be 0\n");
7194 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7195 ok(hicon
== NULL
, "Expect hicon to be NULL\n");
7196 DestroyWindow(hwnd
);
7198 /* Set bitmap with BS_ICON */
7199 hwnd
= CreateWindowA("Button", "test", default_style
| BS_ICON
, 0, 0, 100, 100, 0, 0, 0, 0);
7200 ok(hwnd
!= NULL
, "Expect hwnd to be not NULL\n");
7201 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7202 ok(ret
== 0, "Expect ret to be 0\n");
7203 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7204 ok(hbmp
== NULL
, "Expect hbmp to be NULL\n");
7205 DestroyWindow(hwnd
);
7207 DestroyIcon(hicon2x2
);
7208 DeleteObject(hmask2x2
);
7209 DeleteObject(hbmp2x2
);
7210 DeleteObject(hbmp1x1
);
7214 #define ID_RADIO1 501
7215 #define ID_RADIO2 502
7216 #define ID_RADIO3 503
7219 static const struct message auto_radio_button_BM_CLICK
[] =
7221 { BM_CLICK
, sent
|wparam
|lparam
, 0, 0 },
7222 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7223 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7224 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
7225 { WM_CTLCOLORSTATIC
, sent
|parent
},
7226 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7227 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7228 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
7229 { WM_CTLCOLORSTATIC
, sent
|parent
},
7230 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7231 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
7232 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
7233 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
7234 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO1
},
7235 { WM_CTLCOLORSTATIC
, sent
|parent
},
7236 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7237 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
7238 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO3
},
7239 { WM_CTLCOLORSTATIC
, sent
|parent
},
7240 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7241 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
7242 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7243 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7244 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO2
, BN_CLICKED
) },
7245 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7246 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7247 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7251 static const struct message auto_radio_button_VK_UP_child
[] =
7253 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_UP
, 0 },
7254 { WM_KEYUP
, sent
|wparam
|lparam
, VK_UP
, 0 },
7258 static const struct message auto_radio_button_VK_UP_parent
[] =
7260 { WM_KEYDOWN
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
7261 { WM_KEYUP
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
7265 static const struct message auto_radio_button_VK_UP_dialog
[] =
7267 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7269 /* optional trailer seen on some windows setups */
7270 { WM_CHANGEUISTATE
, sent
|optional
},
7271 { WM_UPDATEUISTATE
, sent
|optional
},
7272 { WM_UPDATEUISTATE
, sent
|optional
},
7273 { WM_UPDATEUISTATE
, sent
|optional
},
7274 { WM_UPDATEUISTATE
, sent
|optional
},
7275 { WM_UPDATEUISTATE
, sent
|optional
},
7276 { WM_UPDATEUISTATE
, sent
|optional
},
7277 { WM_UPDATEUISTATE
, sent
|optional
},
7278 { WM_UPDATEUISTATE
, sent
|optional
},
7279 { WM_UPDATEUISTATE
, sent
|optional
},
7280 { WM_UPDATEUISTATE
, sent
|optional
},
7281 { WM_UPDATEUISTATE
, sent
|optional
},
7282 { WM_UPDATEUISTATE
, sent
|optional
},
7283 { WM_UPDATEUISTATE
, sent
|optional
},
7284 { WM_UPDATEUISTATE
, sent
|optional
},
7285 { WM_UPDATEUISTATE
, sent
|optional
},
7286 { WM_UPDATEUISTATE
, sent
|optional
},
7287 { WM_UPDATEUISTATE
, sent
|optional
},
7288 { WM_UPDATEUISTATE
, sent
|optional
},
7289 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7290 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7291 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7292 { WM_UPDATEUISTATE
, sent
|optional
},
7293 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7294 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7295 { WM_UPDATEUISTATE
, sent
|optional
},
7296 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
7297 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
7298 { WM_UPDATEUISTATE
, sent
|optional
},
7299 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7300 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7304 static const struct message auto_radio_button_VK_DOWN_dialog
[] =
7306 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7307 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
7308 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7309 { HCBT_SETFOCUS
, hook
},
7310 { WM_KILLFOCUS
, sent
, 0, 0 },
7311 { WM_CTLCOLORSTATIC
, sent
|parent
},
7312 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO3
, BN_KILLFOCUS
) },
7313 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
7314 { WM_SETFOCUS
, sent
, 0, 0 },
7315 { WM_CTLCOLORSTATIC
, sent
|parent
},
7316 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_SETFOCUS
) },
7317 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
7318 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7319 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7320 { DM_GETDEFID
, sent
|parent
, 0, 0 },
7321 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7322 { BM_CLICK
, sent
|wparam
|lparam
, 1, 0 },
7323 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7324 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7325 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
7326 { WM_CTLCOLORSTATIC
, sent
|parent
},
7327 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7328 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7329 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO1
},
7330 { WM_CTLCOLORSTATIC
, sent
|parent
},
7331 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7332 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
7333 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
7334 { WM_CTLCOLORSTATIC
, sent
|parent
},
7335 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7336 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
7337 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO3
},
7338 { WM_CTLCOLORSTATIC
, sent
|parent
},
7339 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7340 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
7341 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
7342 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
7343 { WM_CTLCOLORSTATIC
, sent
|parent
},
7344 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7345 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7346 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7347 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
7348 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7349 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7350 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7352 { WM_CTLCOLORSTATIC
, sent
|parent
},
7356 static const struct message auto_radio_button_VK_DOWN_radio3
[] =
7358 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7359 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO2
},
7360 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO3
},
7361 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7362 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
7363 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7364 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7365 { WM_GETDLGCODE
, sent
|wparam
|lparam
|parent
, 0, 0 },
7366 { WM_USER
, sent
|parent
, 0, 0 },
7367 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7371 static const struct message auto_radio_button_VK_UP_radio1
[] =
7373 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7377 static INT_PTR WINAPI
radio_test_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
7379 ParentMsgCheckProcA(hwnd
, msg
, wp
, lp
);
7383 static void test_autoradio_BM_CLICK(void)
7385 HWND parent
, radio1
, radio2
, radio3
;
7392 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc
, 0);
7393 ok(parent
!= 0, "failed to create parent window\n");
7395 radio1
= GetDlgItem(parent
, ID_RADIO1
);
7396 radio2
= GetDlgItem(parent
, ID_RADIO2
);
7397 radio3
= GetDlgItem(parent
, ID_RADIO3
);
7399 /* this avoids focus messages in the generated sequence */
7405 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7406 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7407 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7408 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7409 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7410 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7412 SendMessageA(radio1
, BM_SETCHECK
, BST_CHECKED
, 0);
7414 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7415 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7416 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7417 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7418 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7419 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7421 SendMessageA(radio2
, BM_SETCHECK
, BST_CHECKED
, 0);
7423 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7424 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7425 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7426 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7427 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7428 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7430 SendMessageA(radio3
, BM_SETCHECK
, BST_CHECKED
, 0);
7432 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7433 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7434 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7435 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7436 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7437 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7439 GetWindowRect(radio2
, &rc
);
7440 SetCursorPos(rc
.left
+1, rc
.top
+1);
7445 log_all_parent_messages
++;
7447 SendMessageA(radio2
, BM_CLICK
, 0, 0);
7448 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7449 ok_sequence(auto_radio_button_BM_CLICK
, "BM_CLICK on auto-radio button", FALSE
);
7451 log_all_parent_messages
--;
7453 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7454 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7455 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7456 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7457 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7458 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7460 DestroyWindow(parent
);
7463 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)
7464 static void test_radio_dbg(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
, int line
)
7468 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7469 ok_(__FILE__
,line
)(ret
== state1
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7470 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7471 ok_(__FILE__
,line
)(ret
== state2
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7472 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7473 ok_(__FILE__
,line
)(ret
== state3
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7476 static void set_radio(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
)
7478 SendMessageA(radio1
, BM_SETCHECK
, state1
? BST_CHECKED
: BST_UNCHECKED
, 0);
7479 SendMessageA(radio2
, BM_SETCHECK
, state2
? BST_CHECKED
: BST_UNCHECKED
, 0);
7480 SendMessageA(radio3
, BM_SETCHECK
, state3
? BST_CHECKED
: BST_UNCHECKED
, 0);
7483 static void test_autoradio_kbd_move(void)
7485 HWND parent
, radio1
, radio2
, radio3
, hwnd
;
7492 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc
, 0);
7493 ok(parent
!= 0, "failed to create parent window\n");
7495 radio1
= GetDlgItem(parent
, ID_RADIO1
);
7496 radio2
= GetDlgItem(parent
, ID_RADIO2
);
7497 radio3
= GetDlgItem(parent
, ID_RADIO3
);
7502 test_radio(radio1
, 0, radio2
, 0, radio3
, 0);
7503 set_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7504 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7511 log_all_parent_messages
++;
7513 SendMessageA(radio3
, WM_KEYDOWN
, VK_UP
, 0);
7514 SendMessageA(radio3
, WM_KEYUP
, VK_UP
, 0);
7515 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7516 ok_sequence(auto_radio_button_VK_UP_child
, "press/release VK_UP on auto-radio button", FALSE
);
7518 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7523 DefDlgProcA(parent
, WM_KEYDOWN
, VK_UP
, 0);
7524 DefDlgProcA(parent
, WM_KEYUP
, VK_UP
, 0);
7525 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7526 ok_sequence(auto_radio_button_VK_UP_parent
, "press/release VK_UP on dialog", FALSE
);
7528 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7531 GetWindowRect(radio3
, &rc
);
7537 msg
.message
= WM_KEYDOWN
;
7540 msg
.pt
.x
= rc
.left
+ 1;
7541 msg
.pt
.y
= rc
.top
+ 1;
7542 ret
= IsDialogMessageA(parent
, &msg
);
7543 ok(ret
, "IsDialogMessage should return TRUE\n");
7544 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7545 if (0) /* actual message sequence is different on every run in some Windows setups */
7546 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #1", FALSE
);
7547 /* what really matters is that nothing has changed */
7548 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7550 set_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7551 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7556 ret
= IsDialogMessageA(parent
, &msg
);
7557 ok(ret
, "IsDialogMessage should return TRUE\n");
7558 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7559 if (0) /* actual message sequence is different on every run in some Windows setups */
7560 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #2", FALSE
);
7561 /* what really matters is that nothing has changed */
7562 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7564 /* switch from radio3 ro radio1 */
7566 GetWindowRect(radio3
, &rc
);
7572 msg
.message
= WM_KEYDOWN
;
7573 msg
.wParam
= VK_DOWN
;
7575 msg
.pt
.x
= rc
.left
+ 1;
7576 msg
.pt
.y
= rc
.top
+ 1;
7577 ret
= IsDialogMessageA(parent
, &msg
);
7578 ok(ret
, "IsDialogMessage should return TRUE\n");
7579 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7580 ok_sequence(auto_radio_button_VK_DOWN_dialog
, "IsDialogMessage(VK_DOWN)", TRUE
);
7582 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7585 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7586 GetWindowRect(radio1
, &rc
);
7589 msg
.message
= WM_KEYDOWN
;
7590 msg
.wParam
= VK_DOWN
;
7592 msg
.pt
.x
= rc
.left
+ 1;
7593 msg
.pt
.y
= rc
.top
+ 1;
7594 ret
= IsDialogMessageA(parent
, &msg
);
7595 ok(ret
, "IsDialogMessage should return TRUE\n");
7596 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7597 ok_sequence(auto_radio_button_VK_DOWN_radio3
, "down to radio3", TRUE
);
7599 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7602 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7608 msg
.message
= WM_KEYDOWN
;
7611 msg
.pt
.x
= rc
.left
+ 1;
7612 msg
.pt
.y
= rc
.top
+ 1;
7613 ret
= IsDialogMessageA(parent
, &msg
);
7614 ok(ret
, "IsDialogMessage should return TRUE\n");
7615 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7616 ok_sequence(auto_radio_button_VK_UP_radio1
, "up to radio1", TRUE
);
7618 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7621 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7627 msg
.message
= WM_KEYDOWN
;
7630 msg
.pt
.x
= rc
.left
+ 1;
7631 msg
.pt
.y
= rc
.top
+ 1;
7632 ret
= IsDialogMessageA(parent
, &msg
);
7633 ok(ret
, "IsDialogMessage should return TRUE\n");
7634 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7635 if (0) /* actual message sequence is different on every run in some Windows setups */
7636 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #3", FALSE
);
7637 /* what really matters is that nothing has changed */
7638 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7640 log_all_parent_messages
--;
7642 DestroyWindow(parent
);
7645 /****************** static message test *************************/
7646 static const struct message WmSetFontStaticSeq2
[] =
7648 { WM_SETFONT
, sent
},
7649 { WM_PAINT
, sent
|defwinproc
|optional
},
7650 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
7651 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
7655 static WNDPROC old_static_proc
;
7657 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7659 static LONG defwndproc_counter
= 0;
7661 struct recvd_message msg
;
7663 if (ignore_message( message
)) return 0;
7666 msg
.message
= message
;
7667 msg
.flags
= sent
|wparam
|lparam
;
7668 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7669 msg
.wParam
= wParam
;
7670 msg
.lParam
= lParam
;
7671 msg
.descr
= "static";
7674 defwndproc_counter
++;
7675 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
7676 defwndproc_counter
--;
7681 static void subclass_static(void)
7686 ret
= GetClassInfoA(0, "static", &cls
);
7687 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
7689 old_static_proc
= cls
.lpfnWndProc
;
7691 cls
.hInstance
= GetModuleHandleA(NULL
);
7692 cls
.lpfnWndProc
= static_hook_proc
;
7693 cls
.lpszClassName
= "my_static_class";
7694 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7695 register_class(&cls
);
7698 static void test_static_messages(void)
7700 /* FIXME: make as comprehensive as the button message test */
7705 const struct message
*setfont
;
7707 { SS_LEFT
, DLGC_STATIC
,
7708 WmSetFontStaticSeq2
}
7716 for (i
= 0; i
< ARRAY_SIZE(static_ctrl
); i
++)
7718 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
7719 0, 0, 50, 14, 0, 0, 0, NULL
);
7720 ok(hwnd
!= 0, "Failed to create static window\n");
7722 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
7723 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08lx\n", i
, dlg_code
);
7725 ShowWindow(hwnd
, SW_SHOW
);
7730 if (winetest_debug
> 1) trace("static style %08lx\n", static_ctrl
[i
].style
);
7731 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
7732 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
7734 DestroyWindow(hwnd
);
7738 /****************** ComboBox message test *************************/
7739 #define ID_COMBOBOX 0x000f
7741 static const struct message SetCurSelComboSeq
[] =
7743 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7744 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7745 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7746 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7747 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7748 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7749 { LB_GETTEXT
, sent
|wparam
, 0 },
7750 { WM_CTLCOLOREDIT
, sent
|parent
},
7751 { LB_GETITEMDATA
, sent
|wparam
|lparam
, 0, 0 },
7752 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_COMBOBOX
, 0x100010f3 },
7756 static const struct message SetCurSelComboSeq2
[] =
7758 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7759 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7760 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7761 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7762 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7763 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7764 { LB_GETTEXT
, sent
|wparam
, 0 },
7768 static const struct message SetCurSelComboSeq_edit
[] =
7770 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7771 { WM_SETTEXT
, sent
|wparam
, 0 },
7772 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
7776 static const struct message WmKeyDownComboSeq
[] =
7778 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7779 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
7780 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
7781 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
7782 { WM_CTLCOLOREDIT
, sent
|parent
},
7783 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7787 static const struct message WmSetPosComboSeq
[] =
7789 { WM_WINDOWPOSCHANGING
, sent
},
7790 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
7791 { WM_CHILDACTIVATE
, sent
},
7792 { WM_WINDOWPOSCHANGED
, sent
},
7793 { WM_MOVE
, sent
|defwinproc
},
7794 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7795 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
7796 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
7797 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
7798 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7802 static const struct message WMSetFocusComboBoxSeq
[] =
7804 { WM_SETFOCUS
, sent
},
7805 { WM_KILLFOCUS
, sent
|parent
},
7806 { WM_SETFOCUS
, sent
},
7807 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7808 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7809 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7810 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7811 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7815 static const struct message SetFocusButtonSeq
[] =
7817 { WM_KILLFOCUS
, sent
},
7818 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7819 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7820 { WM_LBUTTONUP
, sent
|defwinproc
},
7821 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7822 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7823 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7824 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7825 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7826 { WM_CTLCOLORBTN
, sent
|parent
},
7830 static const struct message SetFocusComboBoxSeq
[] =
7832 { WM_CTLCOLORBTN
, sent
|parent
},
7833 { WM_SETFOCUS
, sent
},
7834 { WM_KILLFOCUS
, sent
|defwinproc
},
7835 { WM_SETFOCUS
, sent
},
7836 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7837 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7838 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7839 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7840 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7844 static const struct message SetFocusButtonSeq2
[] =
7846 { WM_KILLFOCUS
, sent
},
7847 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7848 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7849 { WM_LBUTTONUP
, sent
|defwinproc
},
7850 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7851 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7852 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
7853 { WM_CTLCOLOREDIT
, sent
|parent
},
7854 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7855 { WM_CTLCOLORBTN
, sent
|parent
},
7859 static WNDPROC old_combobox_proc
, edit_window_proc
, lbox_window_proc
;
7861 static LRESULT CALLBACK
combobox_edit_subclass_proc(HWND hwnd
, UINT message
,
7862 WPARAM wParam
, LPARAM lParam
)
7864 static LONG defwndproc_counter
= 0;
7866 struct recvd_message msg
;
7868 /* do not log painting messages */
7869 if (message
!= WM_PAINT
&&
7870 message
!= WM_NCPAINT
&&
7871 message
!= WM_SYNCPAINT
&&
7872 message
!= WM_ERASEBKGND
&&
7873 message
!= WM_NCHITTEST
&&
7874 message
!= WM_GETTEXT
&&
7875 !ignore_message( message
))
7878 msg
.message
= message
;
7879 msg
.flags
= sent
|wparam
|lparam
;
7880 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7881 msg
.wParam
= wParam
;
7882 msg
.lParam
= lParam
;
7883 msg
.descr
= "combo edit";
7887 defwndproc_counter
++;
7888 ret
= CallWindowProcA(edit_window_proc
, hwnd
, message
, wParam
, lParam
);
7889 defwndproc_counter
--;
7894 static LRESULT CALLBACK
combobox_lbox_subclass_proc(HWND hwnd
, UINT message
,
7895 WPARAM wParam
, LPARAM lParam
)
7897 static LONG defwndproc_counter
= 0;
7899 struct recvd_message msg
;
7901 /* do not log painting messages */
7902 if (message
!= WM_PAINT
&&
7903 message
!= WM_NCPAINT
&&
7904 message
!= WM_SYNCPAINT
&&
7905 message
!= WM_ERASEBKGND
&&
7906 message
!= WM_NCHITTEST
&&
7907 !ignore_message( message
))
7910 msg
.message
= message
;
7911 msg
.flags
= sent
|wparam
|lparam
;
7912 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7913 msg
.wParam
= wParam
;
7914 msg
.lParam
= lParam
;
7915 msg
.descr
= "combo lbox";
7919 defwndproc_counter
++;
7920 ret
= CallWindowProcA(lbox_window_proc
, hwnd
, message
, wParam
, lParam
);
7921 defwndproc_counter
--;
7926 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7928 static LONG defwndproc_counter
= 0;
7930 struct recvd_message msg
;
7932 /* do not log painting messages */
7933 if (message
!= WM_PAINT
&&
7934 message
!= WM_NCPAINT
&&
7935 message
!= WM_SYNCPAINT
&&
7936 message
!= WM_ERASEBKGND
&&
7937 message
!= WM_NCHITTEST
&&
7938 message
!= WM_GETTEXT
&&
7939 !ignore_message( message
))
7942 msg
.message
= message
;
7943 msg
.flags
= sent
|wparam
|lparam
;
7944 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7945 msg
.wParam
= wParam
;
7946 msg
.lParam
= lParam
;
7947 msg
.descr
= "combo";
7951 defwndproc_counter
++;
7952 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
7953 defwndproc_counter
--;
7958 static void subclass_combobox(void)
7963 ret
= GetClassInfoA(0, "ComboBox", &cls
);
7964 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
7966 old_combobox_proc
= cls
.lpfnWndProc
;
7968 cls
.hInstance
= GetModuleHandleA(NULL
);
7969 cls
.lpfnWndProc
= combobox_hook_proc
;
7970 cls
.lpszClassName
= "my_combobox_class";
7971 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7972 register_class(&cls
);
7975 static void test_combobox_messages(void)
7977 HWND parent
, combo
, button
, edit
, lbox
;
7979 COMBOBOXINFO cbInfo
;
7982 subclass_combobox();
7984 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7985 100, 100, 200, 200, 0, 0, 0, NULL
);
7986 ok(parent
!= 0, "Failed to create parent window\n");
7989 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
7990 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
7991 ok(combo
!= 0, "Failed to create combobox window\n");
7993 UpdateWindow(combo
);
7995 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
7996 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08Ix\n", ret
);
7998 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
7999 ok(ret
== 0, "expected 0, got %Id\n", ret
);
8000 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
8001 ok(ret
== 1, "expected 1, got %Id\n", ret
);
8002 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
8003 ok(ret
== 2, "expected 2, got %Id\n", ret
);
8005 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8009 log_all_parent_messages
++;
8010 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
8011 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
8012 log_all_parent_messages
--;
8013 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
8016 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
8017 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
8019 DestroyWindow(combo
);
8020 DestroyWindow(parent
);
8022 /* Start again. Test combobox text selection when getting and losing focus */
8023 parent
= CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8024 10, 10, 300, 300, NULL
, NULL
, NULL
, NULL
);
8025 ok(parent
!= 0, "Failed to create parent window\n");
8027 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWN
,
8028 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
8029 ok(combo
!= 0, "Failed to create combobox window\n");
8031 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
8032 SetLastError(0xdeadbeef);
8033 res
= GetComboBoxInfo(combo
, &cbInfo
);
8034 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8035 edit
= cbInfo
.hwndItem
;
8037 edit_window_proc
= (WNDPROC
)SetWindowLongPtrA(edit
, GWLP_WNDPROC
,
8038 (ULONG_PTR
)combobox_edit_subclass_proc
);
8040 button
= CreateWindowExA(0, "Button", "OK", WS_CHILD
| WS_VISIBLE
| BS_DEFPUSHBUTTON
,
8041 5, 50, 100, 20, parent
, NULL
,
8042 (HINSTANCE
)GetWindowLongPtrA(parent
, GWLP_HINSTANCE
), NULL
);
8043 ok(button
!= 0, "Failed to create button window\n");
8046 log_all_parent_messages
++;
8047 SendMessageA(combo
, WM_SETFOCUS
, 0, (LPARAM
)edit
);
8048 log_all_parent_messages
--;
8049 ok_sequence(WMSetFocusComboBoxSeq
, "WM_SETFOCUS on a ComboBox", TRUE
);
8052 log_all_parent_messages
++;
8054 log_all_parent_messages
--;
8055 ok_sequence(SetFocusButtonSeq
, "SetFocus on a Button", TRUE
);
8057 SendMessageA(combo
, WM_SETTEXT
, 0, (LPARAM
)"Wine Test");
8060 log_all_parent_messages
++;
8062 log_all_parent_messages
--;
8063 ok_sequence(SetFocusComboBoxSeq
, "SetFocus on a ComboBox", TRUE
);
8066 log_all_parent_messages
++;
8068 log_all_parent_messages
--;
8069 ok_sequence(SetFocusButtonSeq2
, "SetFocus on a Button (2)", TRUE
);
8072 SendMessageA(combo
, WM_SETREDRAW
, FALSE
, 0);
8074 log_all_parent_messages
++;
8075 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8076 log_all_parent_messages
--;
8077 ok_sequence(SetCurSelComboSeq_edit
, "CB_SETCURSEL on a ComboBox with edit control", FALSE
);
8079 DestroyWindow(button
);
8080 DestroyWindow(combo
);
8082 combo
= CreateWindowExA(0, "my_combobox_class", "test",
8083 WS_CHILD
| WS_VISIBLE
| CBS_OWNERDRAWFIXED
| CBS_DROPDOWNLIST
,
8084 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
8085 ok(combo
!= 0, "Failed to create combobox window\n");
8087 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
8088 ok(ret
== 0, "expected 0, got %Id\n", ret
);
8090 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
8091 SetLastError(0xdeadbeef);
8092 res
= GetComboBoxInfo(combo
, &cbInfo
);
8093 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8094 lbox
= cbInfo
.hwndList
;
8095 lbox_window_proc
= (WNDPROC
)SetWindowLongPtrA(lbox
, GWLP_WNDPROC
,
8096 (ULONG_PTR
)combobox_lbox_subclass_proc
);
8099 log_all_parent_messages
++;
8100 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8101 log_all_parent_messages
--;
8102 ok_sequence(SetCurSelComboSeq
, "CB_SETCURSEL on a ComboBox", FALSE
);
8104 ShowWindow(combo
, SW_HIDE
);
8106 log_all_parent_messages
++;
8107 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8108 log_all_parent_messages
--;
8109 ok_sequence(SetCurSelComboSeq2
, "CB_SETCURSEL on a ComboBox", FALSE
);
8111 DestroyWindow(combo
);
8112 DestroyWindow(parent
);
8115 /****************** WM_IME_KEYDOWN message test *******************/
8117 static const struct message WmImeKeydownMsgSeq_0
[] =
8119 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
8120 { WM_CHAR
, wparam
, 'A' },
8124 static const struct message WmImeKeydownMsgSeq_1
[] =
8126 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
8127 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
8131 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8133 struct recvd_message msg
;
8136 msg
.message
= message
;
8137 msg
.flags
= wparam
|lparam
;
8138 msg
.wParam
= wParam
;
8139 msg
.lParam
= lParam
;
8140 msg
.descr
= "wmime_keydown";
8143 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8146 static void register_wmime_keydown_class(void)
8150 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
8151 cls
.lpfnWndProc
= wmime_keydown_procA
;
8152 cls
.hInstance
= GetModuleHandleA(0);
8153 cls
.lpszClassName
= "wmime_keydown_class";
8154 register_class(&cls
);
8157 static void test_wmime_keydown_message(void)
8162 if (winetest_debug
> 1) trace("Message sequences by WM_IME_KEYDOWN\n");
8164 register_wmime_keydown_class();
8165 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
8166 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
8171 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
8172 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
8173 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
8175 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
8177 TranslateMessage(&msg
);
8178 DispatchMessageA(&msg
);
8180 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
8182 DestroyWindow(hwnd
);
8185 /************* painting message test ********************/
8187 void dump_region(HRGN hrgn
)
8190 RGNDATA
*data
= NULL
;
8195 printf( "null region\n" );
8198 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
8199 if (!(data
= malloc( size
))) return;
8200 GetRegionData( hrgn
, size
, data
);
8201 printf("%ld rects:", data
->rdh
.nCount
);
8202 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
8203 printf( " %s", wine_dbgstr_rect( rect
));
8208 #define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn )
8209 static void check_update_rgn_( int line
, HWND hwnd
, HRGN hrgn
)
8213 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
8214 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
8216 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
8217 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
8218 if (ret
== NULLREGION
)
8220 ok_(__FILE__
,line
)( !hrgn
, "Update region shouldn't be empty\n" );
8224 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
8226 ok_(__FILE__
,line
)( 0, "Regions are different\n" );
8227 if (winetest_debug
> 0)
8229 printf( "Update region: " );
8230 dump_region( update
);
8231 printf( "Wanted region: " );
8232 dump_region( hrgn
);
8236 GetRgnBox( update
, &r1
);
8237 GetUpdateRect( hwnd
, &r2
, FALSE
);
8238 ok_(__FILE__
,line
)( EqualRect( &r1
, &r2
), "Rectangles are different: %s / %s\n",
8239 wine_dbgstr_rect( &r1
), wine_dbgstr_rect( &r2
));
8241 DeleteObject( tmp
);
8242 DeleteObject( update
);
8245 static const struct message WmInvalidateRgn
[] = {
8246 { WM_NCPAINT
, sent
},
8247 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8251 static const struct message WmGetUpdateRect
[] = {
8252 { WM_NCPAINT
, sent
},
8253 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8258 static const struct message WmInvalidateFull
[] = {
8259 { WM_NCPAINT
, sent
|wparam
, 1 },
8260 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8264 static const struct message WmInvalidateErase
[] = {
8265 { WM_NCPAINT
, sent
|wparam
, 1 },
8266 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8267 { WM_ERASEBKGND
, sent
},
8271 static const struct message WmInvalidatePaint
[] = {
8273 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
8274 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8278 static const struct message WmInvalidateErasePaint
[] = {
8280 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
8281 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8282 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8286 static const struct message WmInvalidateErasePaint2
[] = {
8288 { WM_NCPAINT
, sent
|beginpaint
},
8289 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8290 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8294 static const struct message WmErase
[] = {
8295 { WM_ERASEBKGND
, sent
},
8299 static const struct message WmPaint
[] = {
8304 static const struct message WmParentOnlyPaint
[] = {
8305 { WM_PAINT
, sent
|parent
},
8309 static const struct message WmInvalidateParent
[] = {
8310 { WM_NCPAINT
, sent
|parent
},
8311 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
8312 { WM_ERASEBKGND
, sent
|parent
},
8316 static const struct message WmInvalidateParentChild
[] = {
8317 { WM_NCPAINT
, sent
|parent
},
8318 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
8319 { WM_ERASEBKGND
, sent
|parent
},
8320 { WM_NCPAINT
, sent
},
8321 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8322 { WM_ERASEBKGND
, sent
},
8326 static const struct message WmInvalidateParentChild2
[] = {
8327 { WM_ERASEBKGND
, sent
|parent
},
8328 { WM_NCPAINT
, sent
},
8329 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8330 { WM_ERASEBKGND
, sent
},
8334 static const struct message WmParentPaint
[] = {
8335 { WM_PAINT
, sent
|parent
},
8340 static const struct message WmParentPaintNc
[] = {
8341 { WM_PAINT
, sent
|parent
},
8343 { WM_NCPAINT
, sent
|beginpaint
},
8344 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8345 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8346 { WM_GETMINMAXINFO
, sent
|optional
},
8350 static const struct message WmChildPaintNc
[] = {
8352 { WM_NCPAINT
, sent
|beginpaint
},
8353 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8354 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8358 static const struct message WmParentErasePaint
[] = {
8359 { WM_PAINT
, sent
|parent
},
8360 { WM_NCPAINT
, sent
|parent
|beginpaint
},
8361 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
8362 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
8364 { WM_NCPAINT
, sent
|beginpaint
},
8365 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8366 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8370 static const struct message WmParentOnlyNcPaint
[] = {
8371 { WM_PAINT
, sent
|parent
},
8372 { WM_NCPAINT
, sent
|parent
|beginpaint
},
8373 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
8377 static const struct message WmSetParentStyle
[] = {
8378 { WM_STYLECHANGING
, sent
|parent
},
8379 { WM_STYLECHANGED
, sent
|parent
},
8383 static void test_paint_messages(void)
8390 HWND hparent
, hchild
;
8391 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
8392 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
8393 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
8394 100, 100, 200, 200, 0, 0, 0, NULL
);
8395 ok (hwnd
!= 0, "Failed to create overlapped window\n");
8397 ShowWindow( hwnd
, SW_SHOW
);
8398 UpdateWindow( hwnd
);
8402 check_update_rgn( hwnd
, 0 );
8403 SetRectRgn( hrgn
, 10, 10, 20, 20 );
8404 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8405 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8406 check_update_rgn( hwnd
, hrgn
);
8407 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
8408 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
8409 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8410 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
8411 check_update_rgn( hwnd
, hrgn
);
8412 /* validate everything */
8413 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8414 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8415 check_update_rgn( hwnd
, 0 );
8417 /* test empty region */
8418 SetRectRgn( hrgn
, 10, 10, 10, 15 );
8419 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8420 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8421 check_update_rgn( hwnd
, 0 );
8422 /* test empty rect */
8423 SetRect( &rect
, 10, 10, 10, 15 );
8424 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8425 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8426 check_update_rgn( hwnd
, 0 );
8428 /* test a zeroed rectangle */
8429 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8430 SetRect( &rect
, 0, 0, 0, 0 );
8431 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8432 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8433 check_update_rgn( hwnd
, 0 );
8435 /* a well ordered rectangle */
8436 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8437 SetRect( &rect
, 10, 5, 17, 21 );
8438 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8439 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8440 SetRectRgn( hrgn
, 10, 5, 17, 21 );
8441 check_update_rgn( hwnd
, hrgn
);
8443 /* empty rectangle, top and bottom are swapped but left and right have
8445 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8446 SetRect( &rect
, 5, 30, 5, 10 );
8447 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8448 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8449 check_update_rgn( hwnd
, 0 );
8451 /* empty rectangle, left and right are swapped but top and bottom have
8453 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8454 SetRect( &rect
, 17, 10, 5, 10 );
8455 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8456 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8457 check_update_rgn( hwnd
, 0 );
8459 /* Left and right are swapped */
8460 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8461 SetRect( &rect
, 21, 12, 7, 30 );
8462 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8463 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8464 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8465 check_update_rgn( hwnd
, hrgn
);
8467 /* Top and bottom are swapped */
8468 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8469 SetRect( &rect
, 7, 30, 21, 12 );
8470 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8471 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8472 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8473 check_update_rgn( hwnd
, hrgn
);
8475 /* both reference points are swapped */
8476 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8477 SetRect( &rect
, 21, 30, 7, 12 );
8478 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8479 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8480 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8481 check_update_rgn( hwnd
, hrgn
);
8483 /* flush pending messages */
8487 GetClientRect( hwnd
, &rect
);
8488 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
8489 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
8490 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8492 SetRectEmpty( &rect
);
8493 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) failed\n");
8494 check_update_rgn( hwnd
, hrgn
);
8495 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8497 ok_sequence( WmPaint
, "Paint", FALSE
);
8498 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8499 check_update_rgn( hwnd
, 0 );
8501 SetRectEmpty( &rect
);
8502 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8503 "RedrawWindow failed\n");
8504 check_update_rgn( hwnd
, 0 );
8506 SetRectEmpty( &rect
);
8507 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_VALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8508 "RedrawWindow failed\n");
8509 check_update_rgn( hwnd
, 0 );
8511 GetWindowRect( hwnd
, &rect
);
8512 ok(RedrawWindow(0, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8513 "RedrawWindow failed\n");
8514 check_update_rgn( hwnd
, 0 );
8517 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8518 "RedrawWindow failed\n");
8519 check_update_rgn( hwnd
, hrgn
);
8520 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8522 ok_sequence( WmPaint
, "Paint", FALSE
);
8523 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8524 check_update_rgn( hwnd
, 0 );
8526 ok(RedrawWindow(GetDesktopWindow(), &rect
, 0,
8527 RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8528 "RedrawWindow failed\n");
8529 ret
= GetUpdateRgn( hwnd
, hrgn2
, FALSE
);
8530 ok( ret
== NULLREGION
|| broken(ret
== SIMPLEREGION
), /* <= win7 */
8531 "region should be null (%d)\n", ret
);
8532 if (ret
== SIMPLEREGION
) ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8533 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8536 ok(RedrawWindow(GetDesktopWindow(), NULL
, 0,
8537 RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8538 "RedrawWindow failed\n");
8539 ret
= GetUpdateRgn( hwnd
, hrgn2
, FALSE
);
8540 ok( ret
== NULLREGION
|| broken(ret
== SIMPLEREGION
), /* <= win7 */
8541 "region should be null (%d)\n", ret
);
8542 if (ret
== SIMPLEREGION
) ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8543 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8546 SetRectRgn( hrgn2
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8547 ok(RedrawWindow(0, NULL
, hrgn2
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8548 "RedrawWindow failed\n");
8549 check_update_rgn( hwnd
, hrgn
);
8550 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8552 ok_sequence( WmPaint
, "Paint", FALSE
);
8553 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8554 check_update_rgn( hwnd
, 0 );
8556 ok(RedrawWindow(0, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
),
8557 "RedrawWindow failed\n");
8558 check_update_rgn( hwnd
, 0 );
8560 ok(RedrawWindow(0, NULL
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
),
8561 "RedrawWindow failed\n");
8562 check_update_rgn( hwnd
, hrgn
);
8563 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8565 ok_sequence( WmPaint
, "Paint", FALSE
);
8566 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8567 check_update_rgn( hwnd
, 0 );
8569 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
8570 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8572 SetRectEmpty( &rect
);
8573 if (ValidateRect(0, &rect
) && /* not supported on Win9x */
8574 GetUpdateRect(hwnd
, NULL
, FALSE
)) /* or >= Win 8 */
8576 check_update_rgn( hwnd
, hrgn
);
8577 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8579 ok_sequence( WmPaint
, "Paint", FALSE
);
8580 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8581 check_update_rgn( hwnd
, 0 );
8584 SetLastError(0xdeadbeef);
8585 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
8586 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
8587 "wrong error code %ld\n", GetLastError());
8588 check_update_rgn( hwnd
, 0 );
8590 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8592 SetLastError(0xdeadbeef);
8593 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
8594 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
8595 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8596 "wrong error code %ld\n", GetLastError());
8597 check_update_rgn( hwnd
, 0 );
8599 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8601 SetLastError(0xdeadbeef);
8602 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
8603 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
8604 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8605 "wrong error code %ld\n", GetLastError());
8606 check_update_rgn( hwnd
, 0 );
8608 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8610 /* now with frame */
8611 SetRectRgn( hrgn
, -5, -5, 20, 20 );
8613 /* flush pending messages */
8616 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8617 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
8619 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
8620 check_update_rgn( hwnd
, hrgn
);
8623 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
8624 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
8627 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
8628 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
8630 GetClientRect( hwnd
, &rect
);
8631 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8632 check_update_rgn( hwnd
, hrgn
);
8635 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
8636 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8639 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
8640 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
8641 check_update_rgn( hwnd
, 0 );
8644 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
8645 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
8646 check_update_rgn( hwnd
, 0 );
8649 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8650 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8651 SetRectRgn( hrgn
, 0, 0, 50, 100 );
8652 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
8653 SetRectRgn( hrgn
, 50, 0, 100, 100 );
8654 check_update_rgn( hwnd
, hrgn
);
8655 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
8656 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
8657 check_update_rgn( hwnd
, 0 );
8660 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8661 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
8662 SetRectRgn( hrgn
, 0, 0, 100, 50 );
8663 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
8664 ok_sequence( WmErase
, "Erase", FALSE
);
8665 SetRectRgn( hrgn
, 0, 50, 100, 100 );
8666 check_update_rgn( hwnd
, hrgn
);
8669 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8670 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
8671 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8672 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
8673 ok_sequence( WmPaint
, "Paint", FALSE
);
8676 SetRectRgn( hrgn
, -4, -4, -2, -2 );
8677 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8678 SetRectRgn( hrgn
, -200, -200, -198, -198 );
8679 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
8680 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
8683 SetRectRgn( hrgn
, -4, -4, -2, -2 );
8684 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8685 SetRectRgn( hrgn
, -4, -4, -3, -3 );
8686 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
8687 SetRectRgn( hrgn
, 0, 0, 1, 1 );
8688 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
8689 ok_sequence( WmPaint
, "Paint", FALSE
);
8692 SetRectRgn( hrgn
, -4, -4, -1, -1 );
8693 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8694 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
8695 /* make sure no WM_PAINT was generated */
8697 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
8700 SetRectRgn( hrgn
, -4, -4, -1, -1 );
8701 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8702 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
8704 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
8706 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
8707 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
8708 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
8709 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
8710 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
8711 /* this will send WM_NCPAINT and validate the non client area */
8712 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
8713 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
8715 DispatchMessageA( &msg
);
8717 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
8719 DestroyWindow( hwnd
);
8721 /* now test with a child window */
8723 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
8724 100, 100, 200, 200, 0, 0, 0, NULL
);
8725 ok (hparent
!= 0, "Failed to create parent window\n");
8727 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
8728 10, 10, 100, 100, hparent
, 0, 0, NULL
);
8729 ok (hchild
!= 0, "Failed to create child window\n");
8731 ShowWindow( hparent
, SW_SHOW
);
8732 UpdateWindow( hparent
);
8733 UpdateWindow( hchild
);
8736 log_all_parent_messages
++;
8738 SetRect( &rect
, 0, 0, 50, 50 );
8739 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8740 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8741 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
8743 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8745 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
8746 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
8747 check_update_rgn( hchild
, hrgn
);
8748 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8749 check_update_rgn( hparent
, hrgn
);
8750 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8751 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
8752 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8753 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8756 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
8758 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8759 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8760 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
8761 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8762 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8764 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8765 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8766 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
8768 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8770 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8771 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8772 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
8774 /* flush all paint messages */
8778 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
8779 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8780 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8781 check_update_rgn( hparent
, hrgn
);
8782 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8783 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8784 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8785 check_update_rgn( hparent
, hrgn
);
8787 /* flush all paint messages */
8789 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8792 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
8793 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8794 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8795 check_update_rgn( hparent
, hrgn
);
8796 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8797 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8798 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
8799 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
8800 check_update_rgn( hparent
, hrgn
);
8801 /* flush all paint messages */
8805 /* same as above but parent gets completely validated */
8806 SetRect( &rect
, 20, 20, 30, 30 );
8807 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8808 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8809 check_update_rgn( hparent
, hrgn
);
8810 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8811 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8812 check_update_rgn( hparent
, 0 ); /* no update region */
8814 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
8816 /* make sure RDW_VALIDATE on child doesn't have the same effect */
8818 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8819 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8820 check_update_rgn( hparent
, hrgn
);
8821 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
8822 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8823 check_update_rgn( hparent
, hrgn
);
8825 /* same as above but normal WM_PAINT doesn't validate parent */
8827 SetRect( &rect
, 20, 20, 30, 30 );
8828 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8829 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8830 check_update_rgn( hparent
, hrgn
);
8831 /* no WM_PAINT in child while parent still pending */
8832 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8833 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8834 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8835 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
8838 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8839 /* no WM_PAINT in child while parent still pending */
8840 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8841 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8842 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
8843 /* now that parent is valid child should get WM_PAINT */
8844 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8845 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8846 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8847 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
8849 /* same thing with WS_CLIPCHILDREN in parent */
8851 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8852 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8853 /* changing style invalidates non client area, but we need to invalidate something else to see it */
8854 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
8855 ok_sequence( WmEmptySeq
, "No message", FALSE
);
8856 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
8857 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
8860 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8861 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8862 check_update_rgn( hparent
, hrgn
);
8863 /* no WM_PAINT in child while parent still pending */
8864 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8865 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8866 /* WM_PAINT in parent first */
8867 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8868 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
8870 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
8872 SetRect( &rect
, 0, 0, 30, 30 );
8873 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
8874 SetRectRgn( hrgn
, 0, 0, 30, 30 );
8875 check_update_rgn( hparent
, hrgn
);
8877 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
8879 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8881 SetRect( &rect
, -10, 0, 30, 30 );
8882 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8883 SetRect( &rect
, 0, 0, 20, 20 );
8884 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8885 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8886 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
8888 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8890 SetRect( &rect
, -10, 0, 30, 30 );
8891 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8892 SetRect( &rect
, 0, 0, 100, 100 );
8893 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8894 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8895 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
8896 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8897 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
8899 /* WS_CLIPCHILDREN doesn't exclude children from update region */
8901 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
8902 GetClientRect( hparent
, &rect
);
8903 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8904 check_update_rgn( hparent
, hrgn
);
8907 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8908 GetClientRect( hparent
, &rect
);
8909 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8910 check_update_rgn( hparent
, hrgn
);
8913 /* test RDW_INTERNALPAINT behavior */
8916 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
8918 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8920 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
8922 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8924 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8926 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8928 style
= GetWindowLongA(hparent
, GWL_STYLE
);
8929 ok(style
& WS_CLIPCHILDREN
, "Got unexpected style %#lx.\n", style
);
8930 UpdateWindow( hparent
);
8933 if (winetest_debug
> 1) trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
8934 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8935 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8936 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8938 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
8940 UpdateWindow( hparent
);
8943 if (winetest_debug
> 1) trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
8944 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8945 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8946 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8948 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8950 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8951 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8952 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8954 ok_sequence( WmParentPaint
, "WmParentPaint", 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 without 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_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
8968 UpdateWindow( hparent
);
8971 if (winetest_debug
> 1) trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without 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 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
8979 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
8981 UpdateWindow( hparent
);
8984 if (winetest_debug
> 1) trace("testing SetWindowPos(-10000, -10000) on child\n");
8985 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
8986 check_update_rgn( hchild
, 0 );
8989 #if 0 /* this one doesn't pass under Wine yet */
8990 UpdateWindow( hparent
);
8993 if (winetest_debug
> 1) trace("testing ShowWindow(SW_MINIMIZE) on child\n");
8994 ShowWindow( hchild
, SW_MINIMIZE
);
8995 check_update_rgn( hchild
, 0 );
8999 UpdateWindow( hparent
);
9002 if (winetest_debug
> 1) trace("testing SetWindowPos(-10000, -10000) on parent\n");
9003 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9004 check_update_rgn( hparent
, 0 );
9007 log_all_parent_messages
--;
9008 DestroyWindow( hparent
);
9009 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
9011 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
9013 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
9014 100, 100, 200, 200, 0, 0, 0, NULL
);
9015 ok (hparent
!= 0, "Failed to create parent window\n");
9017 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
9018 10, 10, 100, 100, hparent
, 0, 0, NULL
);
9019 ok (hchild
!= 0, "Failed to create child window\n");
9021 ShowWindow( hparent
, SW_SHOW
);
9022 UpdateWindow( hparent
);
9023 UpdateWindow( hchild
);
9027 /* moving child outside of parent boundaries changes update region */
9028 SetRect( &rect
, 0, 0, 40, 40 );
9029 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
9030 SetRectRgn( hrgn
, 0, 0, 40, 40 );
9031 check_update_rgn( hchild
, hrgn
);
9032 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
9033 SetRectRgn( hrgn
, 10, 0, 40, 40 );
9034 check_update_rgn( hchild
, hrgn
);
9035 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
9036 SetRectRgn( hrgn
, 10, 10, 40, 40 );
9037 check_update_rgn( hchild
, hrgn
);
9039 /* moving parent off-screen does too */
9040 SetRect( &rect
, 0, 0, 100, 100 );
9041 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
9042 SetRectRgn( hrgn
, 0, 0, 100, 100 );
9043 check_update_rgn( hparent
, hrgn
);
9044 SetRectRgn( hrgn
, 10, 10, 40, 40 );
9045 check_update_rgn( hchild
, hrgn
);
9046 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
9047 GetUpdateRect( hparent
, &rect2
, FALSE
);
9048 if (!EqualRect( &rect2
, &rect
)) /* Win 8 and later don't crop update to screen */
9053 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
9054 check_update_rgn( hparent
, hrgn
);
9055 SetRectRgn( hrgn
, rect
.left
+ 10, rect
.top
+ 10, 40, 40 );
9056 check_update_rgn( hchild
, hrgn
);
9058 /* invalidated region is cropped by the parent rects */
9059 SetRect( &rect
, 0, 0, 50, 50 );
9060 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
9061 SetRectRgn( hrgn
, rect2
.left
+ 10, rect2
.top
+ 10, 50, 50 );
9062 check_update_rgn( hchild
, hrgn
);
9064 DestroyWindow( hparent
);
9065 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
9068 DeleteObject( hrgn
);
9069 DeleteObject( hrgn2
);
9072 static void visualize_region_differences( HWND hwnd
, HWND hother
, HRGN hrgn_expect
, HRGN hrgn_actual
)
9074 HBRUSH b_expectonly
, b_actualonly
, b_intersect
;
9075 HRGN hrgn_intersect
;
9076 HWND hstatic
, hshow
, hhide
;
9081 DWORD start_time
, elapsed
, timeout
= 60 * 1000;
9082 BOOL toggle
= TRUE
, stop
= FALSE
;
9084 start_time
= GetTickCount();
9086 b_expectonly
= CreateSolidBrush( RGB( 64, 64, 255 ));
9087 b_actualonly
= CreateSolidBrush( RGB( 255, 64, 64 ));
9088 b_intersect
= CreateSolidBrush( RGB( 159, 64, 159 ));
9090 hrgn_intersect
= CreateRectRgn( 0, 0, 0, 0 );
9091 CombineRgn( hrgn_intersect
, hrgn_expect
, hrgn_actual
, RGN_AND
);
9093 GetClientRect( hwnd
, &rect
);
9094 hdc
= GetDC( hwnd
);
9095 hbitmap
= CreateCompatibleBitmap( hdc
, rect
.right
, rect
.bottom
);
9096 hdctmp
= CreateCompatibleDC( hdc
);
9097 ReleaseDC( hwnd
, hdc
);
9099 SelectObject( hdctmp
, hbitmap
);
9100 FillRgn( hdctmp
, hrgn_expect
, b_expectonly
);
9101 FillRgn( hdctmp
, hrgn_actual
, b_actualonly
);
9102 FillRgn( hdctmp
, hrgn_intersect
, b_intersect
);
9104 DeleteObject( hdctmp
);
9105 DeleteObject( hrgn_intersect
);
9106 DeleteObject( b_intersect
);
9107 DeleteObject( b_actualonly
);
9108 DeleteObject( b_expectonly
);
9110 hstatic
= CreateWindowExA( 0, WC_STATICA
, "", WS_CHILD
| SS_BITMAP
,
9111 0, 0, rect
.right
, rect
.bottom
, hwnd
, 0, 0, NULL
);
9112 SendMessageA( hstatic
, STM_SETIMAGE
, IMAGE_BITMAP
, (LPARAM
)hbitmap
);
9119 if (stop
) toggle
= hshow
== hother
;
9125 hdwp
= BeginDeferWindowPos( !!hhide
+ !!hshow
);
9128 DeferWindowPos( hdwp
, hhide
, NULL
, 0, 0, 0, 0,
9129 SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
);
9133 DeferWindowPos( hdwp
, hshow
, HWND_TOP
, 0, 0, 0, 0,
9134 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
);
9136 EndDeferWindowPos( hdwp
);
9144 if ((elapsed
= GetTickCount() - start_time
) >= timeout
)
9149 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, timeout
- elapsed
, QS_ALLINPUT
);
9150 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9152 TranslateMessage( &msg
);
9153 DispatchMessageA( &msg
);
9154 if (msg
.message
== WM_MOUSEMOVE
)
9156 start_time
= GetTickCount();
9158 else if (msg
.message
== WM_LBUTTONUP
|| (msg
.message
== WM_CHAR
&& msg
.wParam
== VK_SPACE
))
9162 else if (msg
.message
== WM_RBUTTONUP
|| (msg
.message
== WM_CHAR
&& msg
.wParam
== VK_RETURN
))
9169 DestroyWindow( hstatic
);
9170 DeleteObject( hbitmap
);
9173 #define subtest_swp_paint_regions(w,p,c) subtest_swp_paint_regions_(__LINE__,w,p,c)
9175 static void subtest_swp_paint_regions_( int line
, int wrap_toplevel
, LPCSTR parent_class
, LPCSTR child_class
)
9177 static const struct exposure_test
{
9178 int ex_style
, style
;
9179 BOOL shuffle_zorder
;
9180 } exposure_tests
[] = {
9181 { 0, WS_CLIPCHILDREN
, FALSE
},
9183 { WS_EX_COMPOSITED
, WS_CLIPCHILDREN
, TRUE
},
9184 { WS_EX_COMPOSITED
, 0, FALSE
},
9185 { WS_EX_COMPOSITED
, 0, TRUE
},
9188 HWND htoplevel
= NULL
, hparent
, hchild
, hauxchild
;
9189 const RECT rect_old
= { 10, 10, 100, 100 };
9190 HRGN hrgn_old_vis
= CreateRectRgn( 0, 0, 0, 0 );
9191 HRGN hrgn_new_vis
= CreateRectRgn( 0, 0, 0, 0 );
9192 HRGN hrgn_expect
= CreateRectRgn( 0, 0, 0, 0 );
9193 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9194 HRGN hrgn_old_vis_child
= CreateRectRgn( 0, 0, 0, 0 );
9195 HRGN hrgn_new_vis_child
= CreateRectRgn( 0, 0, 0, 0 );
9196 HRGN hrgn_expect_child
= CreateRectRgn( 0, 0, 0, 0 );
9197 HRGN hrgn_actual_child
= CreateRectRgn( 0, 0, 0, 0 );
9199 BOOL is_composition_possible
, has_parentdc_anomaly
;
9200 WNDCLASSA parent_wc
;
9204 htoplevel
= CreateWindowExA( 0, "SimpleWindowClass", "Test toplevel", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9205 100, 100, 400, 400, 0, 0, 0, NULL
);
9206 ok( htoplevel
!= 0, "Failed to create top-level window: %lu\n", GetLastError() );
9207 base_style
= WS_CHILD
| WS_VISIBLE
;
9211 base_style
= WS_OVERLAPPEDWINDOW
| WS_VISIBLE
;
9214 ok( GetClassInfoA( GetModuleHandleA( NULL
), parent_class
, &parent_wc
),
9215 "GetClassInfoA failed\n" );
9217 is_composition_possible
= (base_style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
9218 (parent_wc
.style
& CS_PARENTDC
) == 0;
9220 has_parentdc_anomaly
= (base_style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
9221 (parent_wc
.style
& CS_PARENTDC
) != 0;
9223 hparent
= CreateWindowExA( 0, parent_class
, "Test parent", base_style
,
9224 80, 80, 200, 200, htoplevel
, 0, 0, NULL
);
9225 ok( hparent
!= 0, "Creating parent window (%s) returned error %lu\n",
9226 debugstr_a( parent_class
), GetLastError() );
9228 hchild
= CreateWindowExA( 0, child_class
, "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
9229 rect_old
.left
, rect_old
.top
,
9230 rect_old
.right
- rect_old
.left
, rect_old
.bottom
- rect_old
.top
,
9231 hparent
, 0, 0, NULL
);
9232 ok( hchild
!= 0, "Creating child window (%s) returned error %lu\n",
9233 debugstr_a( child_class
), GetLastError() );
9235 hauxchild
= CreateWindowExA( 0, child_class
, "Auxiliary child for z order test", WS_CHILD
| WS_VISIBLE
,
9236 110, 0, 0, 0, hparent
, 0, 0, NULL
);
9237 ok( hauxchild
!= 0, "Creating child window (%s) returned error %lu\n",
9238 debugstr_a( child_class
), GetLastError() );
9240 for (i
= 0; i
< ARRAY_SIZE(exposure_tests
); i
++)
9242 const struct exposure_test
*extest
= &exposure_tests
[i
];
9243 BOOL has_ws_ex_composited
= (extest
->ex_style
& WS_EX_COMPOSITED
) != 0;
9244 BOOL is_composited
= is_composition_possible
&& has_ws_ex_composited
;
9245 BOOL is_zorder_redraw
= is_composited
&& extest
->shuffle_zorder
;
9248 winetest_push_context( "%d: SetWindowPos redraw #%Id (ex_style = %#x, style = %#x, shuffle_zorder = %d)",
9249 line
, i
, extest
->ex_style
, extest
->style
, extest
->shuffle_zorder
);
9251 SetWindowLongA( hparent
, GWL_EXSTYLE
, extest
->ex_style
);
9252 SetWindowLongA( hparent
, GWL_STYLE
, base_style
| extest
->style
);
9253 RedrawWindow( hparent
, NULL
, NULL
, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9255 for (delta
= -20; delta
<= 0; delta
+= 20)
9257 RECT rect_old_vis
, rect_new
, rect_new_vis
;
9258 RECT rect_parent_clip
, rect_child_clip
;
9259 RECT rect_old_vis_child
, rect_new_vis_child
;
9262 winetest_push_context( "delta = %+d", delta
);
9264 SetWindowPos( hchild
, HWND_TOP
,
9267 rect_old
.right
- rect_old
.left
,
9268 rect_old
.bottom
- rect_old
.top
,
9271 rect_new
= rect_old
;
9272 OffsetRect( &rect_new
, delta
, delta
);
9274 rect_old_vis_child
= rect_old
;
9275 MapWindowPoints( hparent
, hchild
, (POINT
*)&rect_old_vis_child
, 2 );
9277 SetRectRgn( hrgn_actual
, 0, 0, 0, 0 );
9278 SetRectRgn( hrgn_actual_child
, 0, 0, 0, 0 );
9280 UpdateWindow( hparent
);
9283 if (extest
->shuffle_zorder
)
9285 /* bring sibling to top/bottom first so we can trigger z-order change */
9286 SetWindowPos( hauxchild
, HWND_TOP
, 0, 0, 0, 0,
9287 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
9290 SetWindowPos( hchild
, HWND_TOP
,
9293 rect_new
.right
- rect_new
.left
,
9294 rect_new
.bottom
- rect_new
.top
,
9296 (extest
->shuffle_zorder
? 0 : SWP_NOZORDER
) );
9298 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9299 "GetUpdateRgn on parentshall succeed\n" );
9300 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9301 "GetUpdateRgn on child shall succeed\n" );
9303 /* Compute parent window expose region */
9304 GetClientRect( hparent
, &rect_parent_clip
);
9305 IntersectRect( &rect_old_vis
, &rect_old
, &rect_parent_clip
);
9306 SetRectRgn( hrgn_old_vis
, rect_old_vis
.left
, rect_old_vis
.top
, rect_old_vis
.right
, rect_old_vis
.bottom
);
9307 IntersectRect( &rect_new_vis
, &rect_new
, &rect_parent_clip
);
9308 SetRectRgn( hrgn_new_vis
, rect_new_vis
.left
, rect_new_vis
.top
, rect_new_vis
.right
, rect_new_vis
.bottom
);
9310 if (!EqualRect( &rect_old
, &rect_new
) || is_zorder_redraw
)
9312 CombineRgn( hrgn_expect
, hrgn_old_vis
, hrgn_new_vis
, is_composited
? RGN_OR
: RGN_DIFF
);
9316 SetRectRgn( hrgn_expect
, 0, 0, 0, 0 );
9319 rgn_ok
= EqualRgn( hrgn_expect
, hrgn_actual
);
9320 if (!rgn_ok
&& broken( has_parentdc_anomaly
&& is_composited
/* Win7 */ ))
9322 if (winetest_debug
> 1)
9324 trace( "Forcing non-composited update region (broken)\n" );
9330 ok( !!rgn_ok
, "Parent update region shall match expected region\n" );
9333 if (!rgn_ok
&& winetest_debug
> 1)
9335 trace( "Expected parent update region: " );
9336 dump_region( hrgn_expect
);
9337 trace( "Actual parent update region: " );
9338 dump_region( hrgn_actual
);
9339 trace( "Old child window visible area: %s\n", wine_dbgstr_rect( &rect_old_vis
) );
9340 trace( "New child window visible area: %s\n", wine_dbgstr_rect( &rect_new_vis
) );
9343 if (winetest_interactive
)
9347 visualize_region_differences( hparent
, hchild
, hrgn_expect
, hrgn_actual
);
9350 /* Let the position change be visible to the user */
9354 rect_new_vis_child
= rect_new
;
9355 MapWindowPoints( hparent
, hchild
, (POINT
*)&rect_new_vis_child
, 2 );
9357 /* Compute child window expose region */
9358 GetClientRect( hchild
, &rect_child_clip
);
9361 RECT rect_outer_clip
;
9362 GetClientRect( hparent
, &rect_outer_clip
);
9363 MapWindowPoints( hparent
, hchild
, (POINT
*)&rect_outer_clip
, 2 );
9364 IntersectRect( &rect_child_clip
, &rect_child_clip
, &rect_outer_clip
);
9366 IntersectRect( &rect_old_vis_child
, &rect_old_vis_child
, &rect_child_clip
);
9367 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
);
9368 IntersectRect( &rect_new_vis_child
, &rect_new_vis_child
, &rect_child_clip
);
9369 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
);
9371 if (!EqualRect( &rect_old
, &rect_new
) || is_zorder_redraw
)
9373 CombineRgn( hrgn_expect_child
, hrgn_new_vis_child
, hrgn_old_vis_child
, is_composited
? RGN_OR
: RGN_DIFF
);
9377 SetRectRgn( hrgn_expect_child
, 0, 0, 0, 0 );
9380 rgn_ok
= EqualRgn( hrgn_expect_child
, hrgn_actual_child
);
9381 if (!rgn_ok
&& broken( has_parentdc_anomaly
&& is_composited
/* Win7 */ ))
9383 if (winetest_debug
> 1)
9385 trace( "Forcing non-composited update region (broken)\n" );
9391 ok( !!rgn_ok
, "Child update region shall match expected region\n" );
9394 if (!rgn_ok
&& winetest_debug
> 1)
9396 trace( "Expected child update region: " );
9397 dump_region( hrgn_expect_child
);
9398 trace( "Actual child update region: " );
9399 dump_region( hrgn_actual_child
);
9400 trace( "Old child window client visible area: %s\n", wine_dbgstr_rect( &rect_old_vis_child
) );
9401 trace( "New child window client visible area: %s\n", wine_dbgstr_rect( &rect_new_vis_child
) );
9404 if (winetest_interactive
)
9408 visualize_region_differences( hchild
, NULL
, hrgn_expect_child
, hrgn_actual_child
);
9411 /* Let the position change be visible to the user */
9415 winetest_pop_context();
9418 winetest_pop_context();
9421 DestroyWindow( hauxchild
);
9422 DestroyWindow( hchild
);
9423 DestroyWindow( hparent
);
9424 if (htoplevel
) DestroyWindow( htoplevel
);
9426 DeleteObject( hrgn_actual_child
);
9427 DeleteObject( hrgn_expect_child
);
9428 DeleteObject( hrgn_new_vis_child
);
9429 DeleteObject( hrgn_old_vis_child
);
9430 DeleteObject( hrgn_actual
);
9431 DeleteObject( hrgn_expect
);
9432 DeleteObject( hrgn_new_vis
);
9433 DeleteObject( hrgn_old_vis
);
9436 static void test_swp_paint_regions(void)
9438 subtest_swp_paint_regions( 1, "SimpleWindowClass", "SimpleWindowClass" );
9439 subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClass" );
9440 subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClassWithParentDC" );
9441 subtest_swp_paint_regions( 0, "SimpleWindowClassWithParentDC", "SimpleWindowClass" );
9444 static void test_swp_paint_region_on_show(void)
9446 HRGN hrgn_actual_child
= CreateRectRgn( 0, 0, 0, 0 );
9447 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9448 const RECT rect_1
= { 10, 10, 100, 100 };
9449 const RECT rect_2
= { 20, 20, 120, 120 };
9450 RECT rect_expect_child
, rect_expect
;
9451 RECT rect_actual_child
, rect_actual
;
9452 HWND hparent
, hchild
;
9455 hparent
= CreateWindowExA( 0, "SimpleWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9456 80, 80, 200, 200, NULL
, 0, 0, NULL
);
9457 ok( hparent
!= 0, "Creating parent window returned error %lu\n", GetLastError() );
9459 hchild
= CreateWindowExA( 0, "SimpleWindowClass", "Test child", WS_CHILD
| WS_BORDER
,
9460 0, 0, 100, 100, hparent
, 0, 0, NULL
);
9461 ok( hchild
!= 0, "Creating child window returned error %lu\n", GetLastError() );
9463 if (winetest_debug
> 1) trace("testing show window (no move / size)\n");
9465 SetWindowPos( hchild
, HWND_TOP
,
9466 rect_1
.left
, rect_1
.top
, rect_1
.right
- rect_1
.left
, rect_1
.bottom
- rect_1
.top
,
9467 SWP_HIDEWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9469 UpdateWindow( hparent
);
9472 SetWindowPos( hchild
, HWND_TOP
, 0, 0, 0, 0,
9473 SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOMOVE
);
9475 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9476 "GetUpdateRgn on parent shall succeed\n" );
9477 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9478 "GetUpdateRgn on child shall succeed\n" );
9480 result
= GetRgnBox( hrgn_actual
, &rect_actual
);
9481 ok( result
== SIMPLEREGION
, "GetRgnBox (on parent) returned %d\n", result
);
9482 if (result
== COMPLEXREGION
) dump_region( hrgn_actual
);
9484 rect_expect
= rect_1
;
9485 ok( EqualRect( &rect_actual
, &rect_expect
), "parent update region: got %s, expected %s\n",
9486 wine_dbgstr_rect( &rect_actual
), wine_dbgstr_rect( &rect_expect
) );
9488 result
= GetRgnBox( hrgn_actual_child
, &rect_actual_child
);
9489 ok( result
== SIMPLEREGION
, "GetRgnBox (on child) returned %d\n", result
);
9490 if (result
== COMPLEXREGION
) dump_region( hrgn_actual_child
);
9492 ok( GetClientRect( hchild
, &rect_expect_child
), "GetClientRect failed\n" );
9493 ok( EqualRect( &rect_actual_child
, &rect_expect_child
), "child update region: got %s, expected %s\n",
9494 wine_dbgstr_rect( &rect_actual_child
), wine_dbgstr_rect( &rect_expect_child
) );
9496 if (winetest_debug
> 1) trace("testing show window (with move / resize)\n");
9498 SetWindowPos( hchild
, HWND_TOP
,
9499 rect_1
.left
, rect_1
.top
, rect_1
.right
- rect_1
.left
, rect_1
.bottom
- rect_1
.top
,
9500 SWP_HIDEWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9502 UpdateWindow( hparent
);
9505 SetWindowPos( hchild
, HWND_TOP
,
9508 rect_2
.right
- rect_2
.left
,
9509 rect_2
.bottom
- rect_2
.top
,
9510 SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9512 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9513 "GetUpdateRgn on parent shall succeed\n" );
9514 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9515 "GetUpdateRgn on child shall succeed\n" );
9517 result
= GetRgnBox( hrgn_actual
, &rect_actual
);
9518 ok( result
== SIMPLEREGION
, "GetRgnBox (on parent) returned %d\n", result
);
9519 if (result
== COMPLEXREGION
) dump_region( hrgn_actual
);
9521 rect_expect
= rect_2
;
9522 ok( EqualRect( &rect_actual
, &rect_expect
), "parent update region: got %s, expected %s\n",
9523 wine_dbgstr_rect( &rect_actual
), wine_dbgstr_rect( &rect_expect
) );
9525 result
= GetRgnBox( hrgn_actual_child
, &rect_actual_child
);
9526 ok( result
== SIMPLEREGION
, "GetRgnBox (on child) returned %d\n", result
);
9527 if (result
== COMPLEXREGION
) dump_region( hrgn_actual_child
);
9529 ok( GetClientRect( hchild
, &rect_expect_child
), "GetClientRect failed\n" );
9530 ok( EqualRect( &rect_actual_child
, &rect_expect_child
), "child update region: got %s, expected %s\n",
9531 wine_dbgstr_rect( &rect_actual_child
), wine_dbgstr_rect( &rect_expect_child
) );
9533 DestroyWindow( hchild
);
9534 DestroyWindow( hparent
);
9535 DeleteObject( hrgn_actual_child
);
9536 DeleteObject( hrgn_actual
);
9539 static void test_swp_paint_region_on_extend_zerosize(void)
9541 HRGN hrgn_actual_child
= CreateRectRgn( 0, 0, 0, 0 );
9542 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9543 const RECT rect_1
= { 10, 10, 100, 100 };
9544 RECT rect_expect_child
, rect_expect
;
9545 RECT rect_actual_child
, rect_actual
;
9546 HWND hparent
, hchild
;
9549 hparent
= CreateWindowExA( 0, "SimpleWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9550 80, 80, 200, 200, NULL
, 0, 0, NULL
);
9551 ok( hparent
!= 0, "Creating parent window returned error %lu\n", GetLastError() );
9553 hchild
= CreateWindowExA( 0, "SimpleWindowClass", "Test child (no border)", WS_CHILD
| WS_VISIBLE
,
9554 10, 10, 0, 0, hparent
, 0, 0, NULL
);
9555 ok( hchild
!= 0, "Creating child window returned error %lu\n", GetLastError() );
9557 if (winetest_debug
> 1) trace("testing extending zero-size window\n");
9559 UpdateWindow( hparent
);
9562 SetWindowPos( hchild
, HWND_TOP
,
9565 rect_1
.right
- rect_1
.left
,
9566 rect_1
.bottom
- rect_1
.top
,
9567 SWP_NOACTIVATE
| SWP_NOZORDER
);
9569 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9570 "GetUpdateRgn on parent shall succeed\n" );
9571 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9572 "GetUpdateRgn on child shall succeed\n" );
9574 result
= GetRgnBox( hrgn_actual
, &rect_actual
);
9575 ok( result
== SIMPLEREGION
, "GetRgnBox (on parent) returned %d\n", result
);
9576 if (result
== COMPLEXREGION
) dump_region( hrgn_actual
);
9578 rect_expect
= rect_1
;
9579 ok( EqualRect( &rect_actual
, &rect_expect
), "parent update region: got %s, expected %s\n",
9580 wine_dbgstr_rect( &rect_actual
), wine_dbgstr_rect( &rect_expect
) );
9582 result
= GetRgnBox( hrgn_actual_child
, &rect_actual_child
);
9583 ok( result
== SIMPLEREGION
, "GetRgnBox (on child) returned %d\n", result
);
9584 if (result
== COMPLEXREGION
) dump_region( hrgn_actual_child
);
9586 ok( GetClientRect( hchild
, &rect_expect_child
), "GetClientRect failed\n" );
9587 ok( EqualRect( &rect_actual_child
, &rect_expect_child
), "child update region: got %s, expected %s\n",
9588 wine_dbgstr_rect( &rect_actual_child
), wine_dbgstr_rect( &rect_expect_child
) );
9590 DestroyWindow( hchild
);
9591 DestroyWindow( hparent
);
9592 DeleteObject( hrgn_actual_child
);
9593 DeleteObject( hrgn_actual
);
9596 static void subtest_hvredraw(HWND hparent
, UINT class_style
, DWORD style
)
9598 static const struct movesize_test
{
9600 } movesize_tests
[] = {
9609 HRGN hrgn_old_vis
= CreateRectRgn( 0, 0, 0, 0 );
9610 HRGN hrgn_new_vis
= CreateRectRgn( 0, 0, 0, 0 );
9611 HRGN hrgn_expect
= CreateRectRgn( 0, 0, 0, 0 );
9612 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9613 const int x0
= 100, y0
= 100, w0
= 150, h0
= 150;
9617 .style
= class_style
,
9618 .lpfnWndProc
= DefWindowProcA
,
9619 .hInstance
= GetModuleHandleA(0),
9620 .hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
),
9621 .hbrBackground
= GetStockObject(WHITE_BRUSH
),
9622 .lpszClassName
= "TestHVRedrawClass"
9625 register_class(&cls
);
9627 hwnd
= CreateWindowExA( 0, cls
.lpszClassName
, "Test window", style
, x0
, y0
, w0
, h0
, hparent
, 0, 0, NULL
);
9628 ok(hwnd
!= NULL
, "Failed to create the window\n");
9630 ShowWindow( hwnd
, SW_SHOW
);
9631 UpdateWindow( hwnd
);
9633 for (i
= 0; i
< ARRAY_SIZE(movesize_tests
); i
++)
9635 const struct movesize_test
*test
= &movesize_tests
[i
];
9636 int is_redraw
= (test
->dw
!= 0 && (class_style
& CS_HREDRAW
)) ||
9637 (test
->dh
!= 0 && (class_style
& CS_VREDRAW
));
9638 RECT rect_old_vis
, rect_new_vis
;
9641 winetest_push_context( "%x %08lx SetWindowPos redraw #%Id (%d, %d, %d, %d)",
9642 class_style
, style
, i
, test
->dx
, test
->dy
, test
->dw
, test
->dh
);
9644 SetWindowPos( hwnd
, HWND_TOP
, x0
, y0
, w0
, h0
, SWP_NOACTIVATE
);
9646 GetClientRect( hwnd
, &rect_old_vis
);
9647 SetRectRgn( hrgn_old_vis
, rect_old_vis
.left
, rect_old_vis
.top
, rect_old_vis
.right
, rect_old_vis
.bottom
);
9649 UpdateWindow( hparent
);
9652 SetWindowPos( hwnd
, HWND_TOP
,
9653 x0
+ test
->dx
, y0
+ test
->dy
,
9654 w0
+ test
->dw
, h0
+ test
->dh
, SWP_NOACTIVATE
);
9655 ok( GetUpdateRgn( hwnd
, hrgn_actual
, FALSE
) != ERROR
, "GetUpdateRgn shall succeed\n" );
9657 GetClientRect( hwnd
, &rect_new_vis
);
9658 SetRectRgn( hrgn_new_vis
, rect_new_vis
.left
, rect_new_vis
.top
, rect_new_vis
.right
, rect_new_vis
.bottom
);
9659 CombineRgn( hrgn_expect
, hrgn_new_vis
, hrgn_old_vis
, is_redraw
? RGN_COPY
: RGN_DIFF
);
9661 rgn_ok
= EqualRgn( hrgn_expect
, hrgn_actual
);
9662 ok( !!rgn_ok
, "Update region shall match expected region\n" );
9666 trace( "Expected update region: " );
9667 dump_region( hrgn_expect
);
9668 trace( "Actual update region: " );
9669 dump_region( hrgn_actual
);
9670 trace( "Old window visible area: %s\n", wine_dbgstr_rect( &rect_old_vis
) );
9671 trace( "New window visible area: %s\n", wine_dbgstr_rect( &rect_new_vis
) );
9674 if (winetest_interactive
)
9678 visualize_region_differences( hwnd
, NULL
, hrgn_expect
, hrgn_actual
);
9681 /* Let the position change be visible to the user */
9685 winetest_pop_context();
9688 DestroyWindow( hwnd
);
9689 DeleteObject( hrgn_actual
);
9690 DeleteObject( hrgn_expect
);
9691 DeleteObject( hrgn_new_vis
);
9692 DeleteObject( hrgn_old_vis
);
9693 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
9697 static void test_hvredraw(void)
9701 subtest_hvredraw( NULL
, CS_HREDRAW
, WS_OVERLAPPEDWINDOW
);
9702 subtest_hvredraw( NULL
, CS_VREDRAW
, WS_OVERLAPPEDWINDOW
);
9703 subtest_hvredraw( NULL
, CS_HREDRAW
|CS_VREDRAW
, WS_OVERLAPPEDWINDOW
);
9705 htoplevel
= CreateWindowExA( 0, "SimpleWindowClass", "Test toplevel",
9706 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_VISIBLE
,
9707 100, 100, 400, 400, 0, 0, 0, NULL
);
9708 ok( htoplevel
!= 0, "Failed to create top-level window: %lu\n", GetLastError() );
9710 subtest_hvredraw( htoplevel
, CS_HREDRAW
, WS_CHILD
| WS_BORDER
);
9711 subtest_hvredraw( htoplevel
, CS_VREDRAW
, WS_CHILD
| WS_BORDER
);
9712 subtest_hvredraw( htoplevel
, CS_HREDRAW
|CS_VREDRAW
, WS_CHILD
| WS_BORDER
);
9714 DestroyWindow( htoplevel
);
9717 struct run_in_temp_desktop_args
9722 void (*test_func
)(void);
9725 static DWORD WINAPI
run_in_temp_desktop_thread_func(LPVOID param
)
9727 HDESK prev_thr_desktop
, prev_inp_desktop
, post_inp_desktop
, temp_desktop
;
9728 char temp_desktop_name
[1024], curr_desktop_name
[1024];
9729 struct run_in_temp_desktop_args
*args
= param
;
9730 const char *file
= args
->file
;
9731 int line
= args
->line
;
9736 result
= QueryPerformanceCounter( &qpc
);
9737 ok_(file
, line
)( result
, "QueryPerformanceCounter error %lu\n", GetLastError() );
9740 * Temporary desktops from previous runs may leak due to a Windows bug.
9741 * Generate a unique name that is unlikely to collide with previous runs.
9743 result
= snprintf( temp_desktop_name
, ARRAY_SIZE(temp_desktop_name
),
9744 "WineTest-%08lX-%08lX-%08lX%08lX-%s",
9745 GetCurrentProcessId(), GetCurrentThreadId(),
9746 qpc
.HighPart
, qpc
.LowPart
, args
->name
);
9747 ok_(file
, line
)( result
> 0 && result
< ARRAY_SIZE(temp_desktop_name
),
9748 "sprintf returned %d (out of memory, or name too long?)\n", result
);
9750 if (winetest_debug
> 1)
9751 trace_(file
, line
)( "creating desktop: %s\n", debugstr_a( temp_desktop_name
) );
9753 temp_desktop
= CreateDesktopA( temp_desktop_name
, NULL
, NULL
, 0, GENERIC_ALL
, NULL
);
9754 ok_(file
, line
)( temp_desktop
!= NULL
, "CreateDesktopA(%s, ..) error %lu\n",
9755 debugstr_a( temp_desktop_name
), GetLastError() );
9757 prev_inp_desktop
= OpenInputDesktop( 0, FALSE
, DESKTOP_SWITCHDESKTOP
);
9758 ok_(file
, line
)( prev_inp_desktop
!= NULL
, "OpenInputDesktop [prev] error %lu\n", GetLastError() );
9760 if (winetest_debug
> 1)
9761 trace_(file
, line
)( "sanity check: no concurrent WineTest desktop\n" );
9764 * Check if the desktop has not been properly restored. This is done to
9765 * avoid any possible hard-to-debug failures due to unexpected desktop.
9767 result
= GetUserObjectInformationA( prev_inp_desktop
, UOI_NAME
,
9768 curr_desktop_name
, sizeof(curr_desktop_name
), &length
);
9769 ok_(file
, line
)( result
, "GetUserObjectInformationA error %lu [rl = %lu]\n",
9770 GetLastError(), length
);
9771 ok_(file
, line
)( _strnicmp( curr_desktop_name
, temp_desktop_name
, 8 ) != 0,
9772 "unexpected input desktop name %s (concurrent WineTest run?)\n",
9773 debugstr_a( curr_desktop_name
) );
9775 if (winetest_debug
> 1)
9776 trace_(file
, line
)( "switching desktop to: %s (%p)\n", debugstr_a( temp_desktop_name
), temp_desktop
);
9778 result
= SwitchDesktop( temp_desktop
);
9779 ok_(file
, line
)( result
, "SwitchDesktop(temp_desktop=%p) error %lu\n",
9780 temp_desktop
, GetLastError() );
9782 prev_thr_desktop
= GetThreadDesktop( GetCurrentThreadId() );
9783 ok_(file
, line
)( prev_thr_desktop
!= NULL
, "GetThreadDesktop error %lu\n", GetLastError() );
9785 result
= SetThreadDesktop( temp_desktop
);
9786 ok_(file
, line
)( result
, "SetThreadDesktop(temp_desktop=%p) error %lu\n",
9787 temp_desktop
, GetLastError() );
9789 if (winetest_debug
> 1)
9790 trace_(file
, line
)( "running test function %s()\n", args
->name
);
9794 if (winetest_debug
> 1)
9795 trace_(file
, line
)( "sanity check: input desktop has not been changed\n" );
9798 * Check if the input desktop has been tampered with. This is done to
9799 * avoid any possible hard-to-debug failures due to unexpected desktop.
9801 post_inp_desktop
= OpenInputDesktop( 0, FALSE
, DESKTOP_ENUMERATE
);
9802 ok_(file
, line
)( post_inp_desktop
!= NULL
, "OpenInputDesktop [post] error %lu\n", GetLastError() );
9804 result
= GetUserObjectInformationA( post_inp_desktop
, UOI_NAME
,
9805 curr_desktop_name
, sizeof(curr_desktop_name
), &length
);
9806 ok_(file
, line
)( result
, "GetUserObjectInformationA(post_inp_desktop=%p) error %lu [rl = %lu]\n",
9807 post_inp_desktop
, GetLastError(), length
);
9809 ok_(file
, line
)( strcmp( curr_desktop_name
, temp_desktop_name
) == 0,
9810 "different desktop name: %s != %s (no switch or concurrent WineTest run?)\n",
9811 debugstr_a( curr_desktop_name
), debugstr_a( temp_desktop_name
) );
9813 result
= CloseDesktop( post_inp_desktop
);
9814 ok_(file
, line
)( result
, "CloseDesktop(post_inp_desktop=%p) error %lu\n",
9815 post_inp_desktop
, GetLastError() );
9817 if (winetest_debug
> 1)
9818 trace_(file
, line
)( "restoring previous desktop\n" );
9820 result
= SetThreadDesktop( prev_thr_desktop
);
9821 ok_(file
, line
)( result
|| broken( GetLastError() == ERROR_BUSY
) /* == W10 */,
9822 "SetThreadDesktop(prev_thr_desktop=%p) error %lu\n",
9823 prev_thr_desktop
, GetLastError() );
9825 result
= SwitchDesktop( prev_inp_desktop
);
9826 ok_(file
, line
)( result
, "SwitchDesktop(prev_inp_desktop=%p) error %lu\n",
9827 prev_inp_desktop
, GetLastError() );
9829 result
= CloseDesktop( prev_inp_desktop
);
9830 ok_(file
, line
)( result
, "CloseDesktop(prev_inp_desktop=%p) error %lu\n",
9831 prev_inp_desktop
, GetLastError() );
9833 if (winetest_debug
> 1)
9834 trace_(file
, line
)( "closing desktop: %s (%p)\n", debugstr_a( temp_desktop_name
), temp_desktop
);
9836 result
= CloseDesktop( temp_desktop
);
9837 ok_(file
, line
)( result
|| broken( GetLastError() == ERROR_BUSY
) /* == W10 */,
9838 "CloseDesktop(temp_desktop=%p) error %lu\n",
9839 temp_desktop
, GetLastError() );
9844 #define run_in_temp_desktop(f) run_in_temp_desktop_(__FILE__, __LINE__, #f, f)
9845 static void run_in_temp_desktop_(const char *file
, int line
, const char *name
, void (*test_func
)(void))
9847 struct run_in_temp_desktop_args args
;
9854 args
.test_func
= test_func
;
9856 thread
= CreateThread( NULL
, 0, run_in_temp_desktop_thread_func
, &args
, 0, NULL
);
9857 ok_(file
, line
)( thread
!= NULL
, "CreateThread error %lu\n", GetLastError() );
9859 result
= WaitForSingleObject( thread
, INFINITE
);
9860 ok_(file
, line
)( result
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lu, error %lu\n",
9861 result
, GetLastError() );
9863 CloseHandle( thread
);
9872 HANDLE getmessage_complete
;
9875 static DWORD WINAPI
thread_proc(void *param
)
9878 struct wnd_event
*wnd_event
= param
;
9880 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
9881 100, 100, 200, 200, 0, 0, 0, NULL
);
9882 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
9884 SetEvent(wnd_event
->start_event
);
9886 while (GetMessageA(&msg
, 0, 0, 0))
9888 TranslateMessage(&msg
);
9889 DispatchMessageA(&msg
);
9892 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
9897 static DWORD CALLBACK
create_grand_child_thread( void *param
)
9899 struct wnd_event
*wnd_event
= param
;
9903 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
9904 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
9905 ok (hchild
!= 0, "Failed to create child window\n");
9908 SetEvent( wnd_event
->start_event
);
9912 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
9913 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
9914 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9919 static DWORD CALLBACK
create_child_thread( void *param
)
9921 struct wnd_event
*wnd_event
= param
;
9922 struct wnd_event child_event
;
9926 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
9927 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
9928 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
9929 SetFocus( child_event
.hwnd
);
9932 child_event
.start_event
= wnd_event
->start_event
;
9933 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
9936 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
9937 if (ret
!= 1) break;
9938 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9940 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
9941 ok( !ret
, "WaitForSingleObject failed %lx\n", ret
);
9945 static const char manifest_dep
[] =
9946 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
9947 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
9948 " <file name=\"testdep.dll\" />"
9951 static const char manifest_main
[] =
9952 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
9953 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
9955 " <dependentAssembly>"
9956 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
9957 " </dependentAssembly>"
9961 static void create_manifest_file(const char *filename
, const char *manifest
)
9963 WCHAR path
[MAX_PATH
];
9967 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
9968 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
9969 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError());
9970 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
9974 static HANDLE
test_create(const char *file
)
9976 WCHAR path
[MAX_PATH
];
9980 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
9981 memset(&actctx
, 0, sizeof(ACTCTXW
));
9982 actctx
.cbSize
= sizeof(ACTCTXW
);
9983 actctx
.lpSource
= path
;
9985 handle
= CreateActCtxW(&actctx
);
9986 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %lu\n", GetLastError());
9988 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%ld\n", actctx
.cbSize
);
9989 ok(actctx
.dwFlags
== 0, "dwFlags=%ld\n", actctx
.dwFlags
);
9990 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
9991 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
9992 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
9993 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
9994 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
9995 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
9996 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
10001 static void test_interthread_messages(void)
10003 HANDLE hThread
, context
, handle
, event
;
10009 int len
, expected_len
;
10010 struct wnd_event wnd_event
;
10013 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
10014 if (!wnd_event
.start_event
)
10016 win_skip("skipping interthread message test under win9x\n");
10020 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
10021 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
10023 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10025 CloseHandle(wnd_event
.start_event
);
10027 SetLastError(0xdeadbeef);
10028 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
10029 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
10030 "wrong error code %ld\n", GetLastError());
10032 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
10033 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
10035 expected_len
= lstrlenA("window caption text");
10036 memset(buf
, 0, sizeof(buf
));
10037 SetLastError(0xdeadbeef);
10038 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
10039 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
10040 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
10042 msg
.hwnd
= wnd_event
.hwnd
;
10043 msg
.message
= WM_GETTEXT
;
10044 msg
.wParam
= sizeof(buf
);
10045 msg
.lParam
= (LPARAM
)buf
;
10046 memset(buf
, 0, sizeof(buf
));
10047 SetLastError(0xdeadbeef);
10048 len
= DispatchMessageA(&msg
);
10049 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
10050 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %ld\n", len
, GetLastError());
10052 /* the following test causes an exception in user.exe under win9x */
10053 msg
.hwnd
= wnd_event
.hwnd
;
10054 msg
.message
= WM_TIMER
;
10056 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
10057 SetLastError(0xdeadbeef);
10058 len
= DispatchMessageA(&msg
);
10059 ok(!len
&& GetLastError() == 0xdeadbeef,
10060 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len
, GetLastError());
10062 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
10063 ok( ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
10065 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10066 CloseHandle(hThread
);
10068 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
10070 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
10071 100, 100, 200, 200, 0, 0, 0, NULL
);
10072 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
10075 log_all_parent_messages
++;
10076 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
10077 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
10078 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
10081 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
10082 if (ret
!= 1) break;
10083 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10085 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
10086 /* now wait for the thread without processing messages; this shouldn't deadlock */
10087 SetEvent( wnd_event
.stop_event
);
10088 ret
= WaitForSingleObject( hThread
, 5000 );
10089 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
10090 CloseHandle( hThread
);
10092 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
10093 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
10094 CloseHandle( wnd_event
.grand_child
);
10096 CloseHandle( wnd_event
.start_event
);
10097 CloseHandle( wnd_event
.stop_event
);
10099 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
10100 log_all_parent_messages
--;
10101 DestroyWindow( wnd_event
.hwnd
);
10103 /* Activation context tests */
10104 create_manifest_file("testdep1.manifest", manifest_dep
);
10105 create_manifest_file("main.manifest", manifest_main
);
10107 context
= test_create("main.manifest");
10108 DeleteFileA("testdep1.manifest");
10109 DeleteFileA("main.manifest");
10111 handle
= (void*)0xdeadbeef;
10112 ret
= GetCurrentActCtx(&handle
);
10113 ok(ret
, "GetCurrentActCtx failed: %lu\n", GetLastError());
10114 ok(handle
== 0, "active context %p\n", handle
);
10116 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
10117 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
10118 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
10119 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10120 CloseHandle(wnd_event
.start_event
);
10122 /* context is activated after thread creation, so it doesn't inherit it by default */
10123 ret
= ActivateActCtx(context
, &cookie
);
10124 ok(ret
, "activation failed: %lu\n", GetLastError());
10127 ret
= GetCurrentActCtx(&handle
);
10128 ok(ret
, "GetCurrentActCtx failed: %lu\n", GetLastError());
10129 ok(handle
!= 0, "active context %p\n", handle
);
10130 ReleaseActCtx(handle
);
10132 /* destination window will test for active context */
10133 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
10134 ok(ret
, "thread window returned %d\n", ret
);
10136 event
= CreateEventW(NULL
, 0, 0, NULL
);
10137 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
10138 ok(ret
, "thread window returned %d\n", ret
);
10139 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10140 CloseHandle(event
);
10142 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
10143 ok(ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
10145 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10146 CloseHandle(hThread
);
10148 ret
= DeactivateActCtx(0, cookie
);
10149 ok(ret
, "DeactivateActCtx failed: %lu\n", GetLastError());
10150 ReleaseActCtx(context
);
10154 static const struct message WmVkN
[] = {
10155 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10156 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10157 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
10158 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
10159 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
10160 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10161 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10162 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10165 static const struct message WmShiftVkN
[] = {
10166 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10167 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10168 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
10169 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10170 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10171 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
10172 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
10173 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
10174 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10175 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10176 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10177 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
10178 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10179 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10182 static const struct message WmCtrlVkN
[] = {
10183 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10184 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10185 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10186 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10187 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10188 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
10189 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
10190 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
10191 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10192 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10193 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10194 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10195 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10196 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10199 static const struct message WmCtrlVkN_2
[] = {
10200 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10201 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10202 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10203 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10204 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10205 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
10206 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10207 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10208 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10209 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10210 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10211 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10214 static const struct message WmAltVkN
[] = {
10215 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10216 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10217 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10218 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10219 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10220 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
10221 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
10222 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
10223 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
10224 { HCBT_SYSCOMMAND
, hook
},
10225 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10226 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
10227 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
10228 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
10229 { WM_INITMENU
, sent
|defwinproc
},
10230 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10231 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
10232 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
10233 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10234 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
10235 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10236 { WM_EXITMENULOOP
, sent
|defwinproc
},
10237 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
10238 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
10239 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10240 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10241 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10242 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10243 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10244 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10247 static const struct message WmAltVkN_2
[] = {
10248 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10249 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10250 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10251 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10252 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10253 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
10254 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10255 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10256 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10257 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10258 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10259 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10262 static const struct message WmCtrlAltVkN
[] = {
10263 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10264 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10265 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10266 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10267 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10268 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10269 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10270 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10271 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
10272 { WM_CHAR
, optional
},
10273 { WM_CHAR
, sent
|optional
},
10274 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10275 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10276 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10277 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10278 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10279 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10280 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10281 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10282 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10285 static const struct message WmCtrlShiftVkN
[] = {
10286 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10287 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10288 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10289 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10290 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10291 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
10292 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10293 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10294 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
10295 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10296 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10297 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10298 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
10299 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10300 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10301 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10302 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10303 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10306 static const struct message WmCtrlAltShiftVkN
[] = {
10307 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10308 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10309 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10310 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10311 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10312 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10313 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
10314 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
10315 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
10316 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10317 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10318 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
10319 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10320 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10321 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10322 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
10323 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
10324 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
10325 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10326 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10327 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 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 WmAltPressRelease
[] = {
10334 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10335 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10336 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10337 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10338 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10339 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10340 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
10341 { HCBT_SYSCOMMAND
, hook
},
10342 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10343 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
10344 { WM_INITMENU
, sent
|defwinproc
},
10345 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10346 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
10347 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 1 },
10349 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
10351 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10352 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0, },
10353 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10354 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
10355 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10356 { WM_EXITMENULOOP
, sent
|defwinproc
},
10357 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10358 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10359 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10362 static const struct message WmShiftMouseButton
[] = {
10363 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10364 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10365 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
10366 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
10367 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
10368 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
10369 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
10370 { WM_LBUTTONUP
, wparam
|optional
, MK_SHIFT
, 0 }, /* < w1064v1809 */
10371 { WM_LBUTTONUP
, sent
|wparam
|optional
, MK_SHIFT
, 0 }, /* < w1064v1809 */
10372 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
10373 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10374 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10375 { WM_LBUTTONUP
, optional
, 0, 0 }, /* >= w1064v1809 */
10376 { WM_LBUTTONUP
, sent
|optional
, 0, 0 }, /* >= w1064v1809 */
10379 static const struct message WmF1Seq
[] = {
10380 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
10381 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
10382 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
10383 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
10384 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
10385 { WM_HELP
, sent
|defwinproc
},
10386 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
10387 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
10388 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
10391 static const struct message WmVkAppsSeq
[] = {
10392 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
10393 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
10394 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
10395 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
10396 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
10397 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
10398 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
10399 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
10402 static const struct message WmVkF10Seq
[] = {
10403 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
10404 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
10405 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
10406 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
10407 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
10408 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
10409 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
10410 { HCBT_SYSCOMMAND
, hook
},
10411 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10412 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
10413 { WM_INITMENU
, sent
|defwinproc
},
10414 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10415 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
10416 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 1 },
10418 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
10420 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
10421 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10422 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0, },
10423 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10424 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
10425 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10426 { WM_EXITMENULOOP
, sent
|defwinproc
},
10427 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
10428 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
10429 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
10432 static const struct message WmShiftF10Seq
[] = {
10433 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10434 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10435 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
10436 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
10437 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
10438 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
10439 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
10440 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
10441 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
10442 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
10443 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
10444 { HCBT_SYSCOMMAND
, hook
},
10445 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10446 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
10447 { WM_INITMENU
, sent
|defwinproc
},
10448 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10449 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
10450 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 1 },
10451 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
10452 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
10453 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10454 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
10455 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10456 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
10457 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
10458 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10459 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
10460 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
10461 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
10465 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
10469 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
10471 struct recvd_message log_msg
;
10473 /* ignore some unwanted messages */
10474 if (msg
.message
== WM_MOUSEMOVE
||
10475 msg
.message
== WM_TIMER
||
10476 ignore_message( msg
.message
))
10479 log_msg
.hwnd
= msg
.hwnd
;
10480 log_msg
.message
= msg
.message
;
10481 log_msg
.flags
= wparam
|lparam
;
10482 log_msg
.wParam
= msg
.wParam
;
10483 log_msg
.lParam
= msg
.lParam
;
10484 log_msg
.descr
= "accel";
10485 add_message(&log_msg
);
10487 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
10489 TranslateMessage(&msg
);
10490 DispatchMessageA(&msg
);
10495 static void test_accelerators(void)
10501 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
10502 100, 100, 200, 200, 0, 0, 0, NULL
);
10503 BOOL us_kbd
= (GetKeyboardLayout(0) == (HKL
)(ULONG_PTR
)0x04090409);
10506 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
10507 UpdateWindow(hwnd
);
10512 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
10514 state
= GetKeyState(VK_SHIFT
);
10515 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
10516 state
= GetKeyState(VK_CAPITAL
);
10517 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
10519 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
10520 ok(!!hAccel
, "Failed to load accelerators, error %lu.\n", GetLastError());
10523 pump_msg_loop(hwnd
, 0);
10528 skip("skipping ascii VK events on non-us keyboard\n");
10532 if (winetest_debug
> 1) trace("testing VK_N press/release\n");
10534 keybd_event('N', 0, 0, 0);
10535 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10536 pump_msg_loop(hwnd
, hAccel
);
10537 if (!sequence_cnt
) /* we didn't get any message */
10539 skip( "queuing key events not supported\n" );
10542 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
10544 if (winetest_debug
> 1) trace("testing Shift+VK_N press/release\n");
10546 keybd_event(VK_SHIFT
, 0, 0, 0);
10547 keybd_event('N', 0, 0, 0);
10548 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10549 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10550 pump_msg_loop(hwnd
, hAccel
);
10551 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
10553 if (winetest_debug
> 1) trace("testing Ctrl+VK_N press/release\n");
10555 keybd_event(VK_CONTROL
, 0, 0, 0);
10556 keybd_event('N', 0, 0, 0);
10557 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10558 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10559 pump_msg_loop(hwnd
, hAccel
);
10560 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
10562 if (winetest_debug
> 1) trace("testing Alt+VK_N press/release\n");
10564 keybd_event(VK_MENU
, 0, 0, 0);
10565 keybd_event('N', 0, 0, 0);
10566 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10567 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10568 pump_msg_loop(hwnd
, hAccel
);
10569 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
10571 if (winetest_debug
> 1) trace("testing Ctrl+Alt+VK_N press/release 1\n");
10573 keybd_event(VK_CONTROL
, 0, 0, 0);
10574 keybd_event(VK_MENU
, 0, 0, 0);
10575 keybd_event('N', 0, 0, 0);
10576 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10577 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10578 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10579 pump_msg_loop(hwnd
, hAccel
);
10580 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
10582 ret
= DestroyAcceleratorTable(hAccel
);
10583 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
10585 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
10586 ok(!!hAccel
, "Failed to load accelerators, error %lu.\n", GetLastError());
10588 if (winetest_debug
> 1) trace("testing VK_N press/release\n");
10590 keybd_event('N', 0, 0, 0);
10591 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10592 pump_msg_loop(hwnd
, hAccel
);
10593 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
10595 if (winetest_debug
> 1) trace("testing Shift+VK_N press/release\n");
10597 keybd_event(VK_SHIFT
, 0, 0, 0);
10598 keybd_event('N', 0, 0, 0);
10599 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10600 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10601 pump_msg_loop(hwnd
, hAccel
);
10602 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
10604 if (winetest_debug
> 1) trace("testing Ctrl+VK_N press/release 2\n");
10606 keybd_event(VK_CONTROL
, 0, 0, 0);
10607 keybd_event('N', 0, 0, 0);
10608 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10609 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10610 pump_msg_loop(hwnd
, hAccel
);
10611 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
10613 if (winetest_debug
> 1) trace("testing Alt+VK_N press/release 2\n");
10615 keybd_event(VK_MENU
, 0, 0, 0);
10616 keybd_event('N', 0, 0, 0);
10617 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10618 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10619 pump_msg_loop(hwnd
, hAccel
);
10620 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
10622 if (winetest_debug
> 1) trace("testing Ctrl+Alt+VK_N press/release 2\n");
10624 keybd_event(VK_CONTROL
, 0, 0, 0);
10625 keybd_event(VK_MENU
, 0, 0, 0);
10626 keybd_event('N', 0, 0, 0);
10627 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10628 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10629 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10630 pump_msg_loop(hwnd
, hAccel
);
10631 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
10633 if (winetest_debug
> 1) trace("testing Ctrl+Shift+VK_N press/release\n");
10635 keybd_event(VK_CONTROL
, 0, 0, 0);
10636 keybd_event(VK_SHIFT
, 0, 0, 0);
10637 keybd_event('N', 0, 0, 0);
10638 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10639 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10640 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10641 pump_msg_loop(hwnd
, hAccel
);
10642 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
10644 if (winetest_debug
> 1) trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
10646 keybd_event(VK_CONTROL
, 0, 0, 0);
10647 keybd_event(VK_MENU
, 0, 0, 0);
10648 keybd_event(VK_SHIFT
, 0, 0, 0);
10649 keybd_event('N', 0, 0, 0);
10650 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10651 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10652 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10653 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10654 pump_msg_loop(hwnd
, hAccel
);
10655 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
10657 ret
= DestroyAcceleratorTable(hAccel
);
10658 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
10661 if (winetest_debug
> 1) trace("testing Alt press/release\n");
10663 keybd_event(VK_MENU
, 0, 0, 0);
10664 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10665 keybd_event(VK_MENU
, 0, 0, 0);
10666 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10667 pump_msg_loop(hwnd
, 0);
10668 /* this test doesn't pass in Wine for managed windows */
10669 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
10671 if (winetest_debug
> 1) trace("testing VK_F1 press/release\n");
10672 keybd_event(VK_F1
, 0, 0, 0);
10673 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
10674 pump_msg_loop(hwnd
, 0);
10675 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
10677 if (winetest_debug
> 1) trace("testing VK_APPS press/release\n");
10678 keybd_event(VK_APPS
, 0, 0, 0);
10679 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
10680 pump_msg_loop(hwnd
, 0);
10681 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
10683 if (winetest_debug
> 1) trace("testing VK_F10 press/release\n");
10684 keybd_event(VK_F10
, 0, 0, 0);
10685 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
10686 keybd_event(VK_F10
, 0, 0, 0);
10687 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
10688 pump_msg_loop(hwnd
, 0);
10689 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", TRUE
);
10691 if (winetest_debug
> 1) trace("testing SHIFT+F10 press/release\n");
10692 keybd_event(VK_SHIFT
, 0, 0, 0);
10693 keybd_event(VK_F10
, 0, 0, 0);
10694 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
10695 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10696 keybd_event(VK_ESCAPE
, 0, 0, 0);
10697 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
10698 pump_msg_loop(hwnd
, 0);
10699 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
10701 if (winetest_debug
> 1) trace("testing Shift+MouseButton press/release\n");
10702 /* first, move mouse pointer inside of the window client area */
10703 GetClientRect(hwnd
, &rc
);
10704 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
10705 rc
.left
+= (rc
.right
- rc
.left
)/2;
10706 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
10707 SetCursorPos(rc
.left
, rc
.top
);
10708 SetActiveWindow(hwnd
);
10713 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
10716 keybd_event(VK_SHIFT
, 0, 0, 0);
10717 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
10718 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
10719 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10720 pump_msg_loop(hwnd
, 0);
10721 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
10722 if (i
< sequence_cnt
)
10723 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
10725 skip( "Shift+MouseButton event didn't get to the window\n" );
10729 if (hAccel
) DestroyAcceleratorTable(hAccel
);
10730 DestroyWindow(hwnd
);
10733 /************* window procedures ********************/
10735 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
10736 WPARAM wParam
, LPARAM lParam
)
10738 static LONG defwndproc_counter
= 0;
10739 static LONG beginpaint_counter
= 0;
10741 struct recvd_message msg
;
10743 if (ignore_message( message
)) return 0;
10749 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
10750 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
10751 "wrong WS_DISABLED state: %Id != %d\n", wParam
, !(style
& WS_DISABLED
));
10755 case WM_CAPTURECHANGED
:
10756 if (test_DestroyWindow_flag
)
10758 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
10759 if (style
& WS_CHILD
)
10760 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
10761 else if (style
& WS_POPUP
)
10762 lParam
= WND_POPUP_ID
;
10764 lParam
= WND_PARENT_ID
;
10772 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
10773 capture
= GetCapture();
10776 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
10777 if (winetest_debug
> 1) trace("current capture %p, releasing...\n", capture
);
10783 ok(GetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
10784 if (test_DestroyWindow_flag
)
10786 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
10787 if (style
& WS_CHILD
)
10788 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
10789 else if (style
& WS_POPUP
)
10790 lParam
= WND_POPUP_ID
;
10792 lParam
= WND_PARENT_ID
;
10796 /* test_accelerators() depends on this */
10802 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo
;
10803 HANDLE handle
, event
= (HANDLE
)lParam
;
10806 handle
= (void*)0xdeadbeef;
10807 ret
= GetCurrentActCtx(&handle
);
10808 ok(ret
, "failed to get current context, %lu\n", GetLastError());
10809 ok(handle
== 0, "got active context %p\n", handle
);
10811 memset(&basicinfo
, 0xff, sizeof(basicinfo
));
10812 ret
= QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
, handle
, 0, ActivationContextBasicInformation
,
10813 &basicinfo
, sizeof(basicinfo
), NULL
);
10814 ok(ret
, "got %d, error %ld\n", ret
, GetLastError());
10815 ok(basicinfo
.hActCtx
== NULL
, "got %p\n", basicinfo
.hActCtx
);
10816 ok(basicinfo
.dwFlags
== 0, "got %lx\n", basicinfo
.dwFlags
);
10818 if (event
) SetEvent(event
);
10824 case WM_MOUSEACTIVATE
:
10825 case WM_NCMOUSEMOVE
:
10827 case WM_IME_SELECT
:
10832 msg
.message
= message
;
10833 msg
.flags
= sent
|wparam
|lparam
;
10834 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10835 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
10836 msg
.wParam
= wParam
;
10837 msg
.lParam
= lParam
;
10838 msg
.descr
= "MsgCheckProc";
10841 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
10843 HWND parent
= GetParent(hwnd
);
10845 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
10847 GetClientRect(parent
, &rc
);
10848 if (winetest_debug
> 1)
10850 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
10851 trace("Reserved=%ld,%ld MaxSize=%ld,%ld MaxPos=%ld,%ld MinTrack=%ld,%ld MaxTrack=%ld,%ld\n",
10852 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
10853 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
10854 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
10855 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
10856 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
10858 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
10859 minmax
->ptMaxSize
.x
, rc
.right
);
10860 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
10861 minmax
->ptMaxSize
.y
, rc
.bottom
);
10864 if (message
== WM_PAINT
)
10867 beginpaint_counter
++;
10868 BeginPaint( hwnd
, &ps
);
10869 beginpaint_counter
--;
10870 EndPaint( hwnd
, &ps
);
10874 if (!test_context_menu
&& message
== WM_CONTEXTMENU
)
10876 /* don't create context menu */
10880 defwndproc_counter
++;
10881 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
10882 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10883 defwndproc_counter
--;
10888 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10890 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
10893 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10895 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
10898 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10900 static LONG defwndproc_counter
= 0;
10902 struct recvd_message msg
;
10904 if (ignore_message( message
)) return 0;
10908 case WM_QUERYENDSESSION
:
10909 case WM_ENDSESSION
:
10910 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
10915 msg
.message
= message
;
10916 msg
.flags
= sent
|wparam
|lparam
;
10917 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10918 msg
.wParam
= wParam
;
10919 msg
.lParam
= lParam
;
10920 msg
.descr
= "popup";
10923 if (message
== WM_CREATE
)
10925 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
10926 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
10929 defwndproc_counter
++;
10930 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10931 defwndproc_counter
--;
10936 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10938 static LONG defwndproc_counter
= 0;
10939 static LONG beginpaint_counter
= 0;
10941 struct recvd_message msg
;
10943 if (ignore_message( message
)) return 0;
10945 if (log_all_parent_messages
||
10946 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
10947 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
10948 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
10949 message
== WM_DRAWITEM
|| message
== WM_MEASUREITEM
|| message
== WM_COMPAREITEM
||
10950 message
== WM_COMMAND
|| message
== WM_IME_SETCONTEXT
)
10959 case WM_NCMOUSEMOVE
:
10964 msg
.message
= message
;
10965 msg
.flags
= sent
|parent
|wparam
|lparam
;
10966 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10967 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
10968 msg
.wParam
= wParam
;
10969 msg
.lParam
= lParam
;
10970 msg
.descr
= "parent";
10974 if (message
== WM_PAINT
)
10977 beginpaint_counter
++;
10978 BeginPaint( hwnd
, &ps
);
10979 beginpaint_counter
--;
10980 EndPaint( hwnd
, &ps
);
10984 defwndproc_counter
++;
10985 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10986 defwndproc_counter
--;
10988 return message
== WM_COMPAREITEM
? -1 : ret
;
10991 static LRESULT CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
10993 if (message
== WM_CREATE
)
10994 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
10995 else if (message
== WM_CLOSE
)
10997 /* Only the first WM_QUIT will survive the window destruction */
10998 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
10999 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
11000 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
11003 return DefWindowProcA(hwnd
, message
, wp
, lp
);
11006 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11008 static LONG defwndproc_counter
= 0;
11010 struct recvd_message msg
;
11012 if (ignore_message( message
)) return 0;
11016 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
11017 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
11018 if (after_end_dialog
)
11019 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %Ix\n", ret
);
11021 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %Ix\n", ret
);
11025 msg
.message
= message
;
11026 msg
.flags
= sent
|wparam
|lparam
;
11027 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11028 msg
.wParam
= wParam
;
11029 msg
.lParam
= lParam
;
11030 msg
.descr
= "dialog";
11033 defwndproc_counter
++;
11034 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
11035 defwndproc_counter
--;
11040 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11042 static LONG defwndproc_counter
= 0;
11044 struct recvd_message msg
;
11046 /* log only specific messages we are interested in */
11049 #if 0 /* probably log these as well */
11054 case WM_SHOWWINDOW
:
11057 case WM_GETMINMAXINFO
:
11058 case WM_WINDOWPOSCHANGING
:
11059 case WM_WINDOWPOSCHANGED
:
11062 default: /* ignore */
11063 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
11064 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
11068 msg
.message
= message
;
11069 msg
.flags
= sent
|wparam
|lparam
;
11070 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11071 msg
.wParam
= wParam
;
11072 msg
.lParam
= lParam
;
11073 msg
.descr
= "show";
11076 defwndproc_counter
++;
11077 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
11078 defwndproc_counter
--;
11083 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
11087 case WM_CREATE
: return 0;
11096 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
11098 TranslateMessage(&msg2
);
11099 DispatchMessageA(&msg2
);
11103 else ok(broken(1), "infinite loop\n");
11105 paint_loop_done
= TRUE
;
11106 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
11109 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
11112 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11114 static LONG defwndproc_counter
= 0;
11116 struct recvd_message msg
;
11117 DWORD queue_status
;
11119 if (ignore_message( message
)) return 0;
11121 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
11122 message
== WM_HOTKEY
|| message
>= WM_APP
)
11125 msg
.message
= message
;
11126 msg
.flags
= sent
|wparam
|lparam
;
11127 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11128 msg
.wParam
= wParam
;
11129 msg
.lParam
= lParam
;
11130 msg
.descr
= "HotkeyMsgCheckProcA";
11134 defwndproc_counter
++;
11135 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
11136 defwndproc_counter
--;
11138 if (message
== WM_APP
)
11140 queue_status
= GetQueueStatus(QS_HOTKEY
);
11141 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
11142 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
11143 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %lx\n", queue_status
);
11144 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
11146 else if (message
== WM_APP
+1)
11148 queue_status
= GetQueueStatus(QS_HOTKEY
);
11149 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %lx\n", queue_status
);
11155 static void register_classes(void)
11161 cls
.lpfnWndProc
= MsgCheckProcA
;
11162 cls
.cbClsExtra
= 0;
11163 cls
.cbWndExtra
= 0;
11164 cls
.hInstance
= GetModuleHandleA(0);
11166 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
11167 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
11168 cls
.lpszMenuName
= NULL
;
11169 cls
.lpszClassName
= "TestWindowClass";
11170 register_class(&cls
);
11172 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
11173 cls
.lpszClassName
= "HotkeyWindowClass";
11174 register_class(&cls
);
11176 cls
.lpfnWndProc
= ShowWindowProcA
;
11177 cls
.lpszClassName
= "ShowWindowClass";
11178 register_class(&cls
);
11180 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
11181 cls
.lpszClassName
= "TestPopupClass";
11182 register_class(&cls
);
11184 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
11185 cls
.lpszClassName
= "TestParentClass";
11186 register_class(&cls
);
11188 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
11189 cls
.lpszClassName
= "StopQuitClass";
11190 register_class(&cls
);
11192 cls
.lpfnWndProc
= DefWindowProcA
;
11193 cls
.lpszClassName
= "SimpleWindowClass";
11194 register_class(&cls
);
11196 cls
.lpfnWndProc
= PaintLoopProcA
;
11197 cls
.lpszClassName
= "PaintLoopWindowClass";
11198 register_class(&cls
);
11200 cls
.style
= CS_NOCLOSE
;
11201 cls
.lpszClassName
= "NoCloseWindowClass";
11202 register_class(&cls
);
11204 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
11206 cls
.hInstance
= GetModuleHandleA(0);
11207 cls
.hbrBackground
= 0;
11208 cls
.lpfnWndProc
= TestDlgProcA
;
11209 cls
.lpszClassName
= "TestDialogClass";
11210 register_class(&cls
);
11212 cls
.lpfnWndProc
= DefWindowProcA
;
11213 cls
.style
= CS_PARENTDC
;
11214 cls
.lpszClassName
= "SimpleWindowClassWithParentDC";
11215 register_class(&cls
);
11218 clsW
.lpfnWndProc
= MsgCheckProcW
;
11219 clsW
.cbClsExtra
= 0;
11220 clsW
.cbWndExtra
= 0;
11221 clsW
.hInstance
= GetModuleHandleW(0);
11223 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
11224 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
11225 clsW
.lpszMenuName
= NULL
;
11226 clsW
.lpszClassName
= testWindowClassW
;
11227 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
11230 static BOOL
is_our_logged_class(HWND hwnd
)
11234 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
11236 if (!lstrcmpiA(buf
, "TestWindowClass") ||
11237 !lstrcmpiA(buf
, "ShowWindowClass") ||
11238 !lstrcmpiA(buf
, "TestParentClass") ||
11239 !lstrcmpiA(buf
, "TestPopupClass") ||
11240 !lstrcmpiA(buf
, "SimpleWindowClass") ||
11241 !lstrcmpiA(buf
, "TestDialogClass") ||
11242 !lstrcmpiA(buf
, "MDI_frame_class") ||
11243 !lstrcmpiA(buf
, "MDI_client_class") ||
11244 !lstrcmpiA(buf
, "MDI_child_class") ||
11245 !lstrcmpiA(buf
, "my_button_class") ||
11246 !lstrcmpiA(buf
, "my_edit_class") ||
11247 !lstrcmpiA(buf
, "static") ||
11248 !lstrcmpiA(buf
, "ListBox") ||
11249 !lstrcmpiA(buf
, "ComboBox") ||
11250 !lstrcmpiA(buf
, "MyDialogClass") ||
11251 !lstrcmpiA(buf
, "#32770") ||
11252 !lstrcmpiA(buf
, "#32768"))
11258 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
11262 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
11264 if (nCode
== HCBT_CLICKSKIPPED
)
11266 /* ignore this event, XP sends it a lot when switching focus between windows */
11267 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
11270 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
11272 struct recvd_message msg
;
11275 msg
.message
= nCode
;
11276 msg
.flags
= hook
|wparam
|lparam
;
11277 msg
.wParam
= wParam
;
11278 msg
.lParam
= lParam
;
11282 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
11285 if (nCode
== HCBT_DESTROYWND
)
11287 if (test_DestroyWindow_flag
)
11289 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
11290 if (style
& WS_CHILD
)
11291 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
11292 else if (style
& WS_POPUP
)
11293 lParam
= WND_POPUP_ID
;
11295 lParam
= WND_PARENT_ID
;
11299 /* Log also SetFocus(0) calls */
11300 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
11302 if (is_our_logged_class(hwnd
))
11304 struct recvd_message msg
;
11307 msg
.message
= nCode
;
11308 msg
.flags
= hook
|wparam
|lparam
;
11309 msg
.wParam
= wParam
;
11310 msg
.lParam
= lParam
;
11314 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
11317 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
11325 ok(thread_id
== winevent_hook_thread_id
, "we didn't ask for events from other threads\n");
11327 /* ignore mouse cursor events */
11328 if (object_id
== OBJID_CURSOR
) return;
11330 if (!hwnd
|| is_our_logged_class(hwnd
))
11332 struct recvd_message msg
;
11335 msg
.message
= event
;
11336 msg
.flags
= winevent_hook
|wparam
|lparam
;
11337 msg
.wParam
= object_id
;
11338 msg
.lParam
= child_id
;
11344 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
11345 static const WCHAR wszAnsi
[] = {'U',0};
11347 static const GUID iface_guid
= {0x66666666};
11349 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
11351 const DEV_BROADCAST_DEVICEINTERFACE_A
*ifaceA
= (const void *)lParam
;
11355 case CB_FINDSTRINGEXACT
:
11356 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
11358 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
11362 case WM_DEVICECHANGE
:
11363 if (wParam
== DBT_DEVICEARRIVAL
&& IsEqualGUID(&ifaceA
->dbcc_classguid
, &iface_guid
))
11365 DWORD expect_size
= offsetof(DEV_BROADCAST_DEVICEINTERFACE_A
, dbcc_name
[strlen(ifaceA
->dbcc_name
)]);
11367 ok(ifaceA
->dbcc_size
== expect_size
, "Expected %lu, got %lu.\n", expect_size
, ifaceA
->dbcc_size
);
11368 ok(ifaceA
->dbcc_devicetype
== DBT_DEVTYP_DEVICEINTERFACE
,
11369 "Got notification type %#lx.\n", ifaceA
->dbcc_devicetype
);
11370 ok(!ifaceA
->dbcc_reserved
, "Got reserved %#lx.\n", ifaceA
->dbcc_reserved
);
11371 ok(!strcmp(ifaceA
->dbcc_name
, "test name"), "Got name %s.\n", debugstr_a(ifaceA
->dbcc_name
));
11375 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
11378 static const struct message WmGetTextLengthAfromW
[] = {
11379 { WM_GETTEXTLENGTH
, sent
},
11380 { WM_GETTEXT
, sent
|optional
},
11384 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
11386 /* dummy window proc for WM_GETTEXTLENGTH test */
11387 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
11391 case WM_GETTEXTLENGTH
:
11392 return lstrlenW(dummy_window_text
) + 37; /* some random length */
11394 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
11395 return lstrlenW( (LPWSTR
)lp
);
11397 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
11401 static void test_message_conversion(void)
11403 static const WCHAR wszMsgConversionClass
[] =
11404 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
11406 DEV_BROADCAST_DEVICEINTERFACE_A
*dev_interface
= (void *)buffer
;
11410 WNDPROC wndproc
, newproc
;
11414 cls
.lpfnWndProc
= MsgConversionProcW
;
11415 cls
.cbClsExtra
= 0;
11416 cls
.cbWndExtra
= 0;
11417 cls
.hInstance
= GetModuleHandleW(NULL
);
11419 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
11420 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
11421 cls
.lpszMenuName
= NULL
;
11422 cls
.lpszClassName
= wszMsgConversionClass
;
11423 /* this call will fail on Win9x, but that doesn't matter as this test is
11424 * meaningless on those platforms */
11425 if(!RegisterClassW(&cls
)) return;
11427 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
11428 100, 100, 200, 200, 0, 0, 0, NULL
);
11429 ok(hwnd
!= NULL
, "Window creation failed\n");
11433 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
11434 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11435 ok(lRes
== 0, "String should have been converted\n");
11436 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11437 ok(lRes
== 1, "String shouldn't have been converted\n");
11441 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
11442 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11443 ok(lRes
== 1, "String shouldn't have been converted\n");
11444 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11445 ok(lRes
== 1, "String shouldn't have been converted\n");
11447 /* Synchronous messages */
11449 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11450 ok(lRes
== 0, "String should have been converted\n");
11451 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11452 ok(lRes
== 1, "String shouldn't have been converted\n");
11454 /* Asynchronous messages */
11457 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11458 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11459 "PostMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11461 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11462 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11463 "PostMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11465 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11466 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11467 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11469 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11470 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11471 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11473 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11474 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11475 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11477 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11478 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11479 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11481 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
11482 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11483 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11485 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
11486 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11487 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11489 /* Test WM_DEVICECHANGE. */
11491 dev_interface
->dbcc_devicetype
= DBT_DEVTYP_DEVICEINTERFACE
;
11492 dev_interface
->dbcc_reserved
= 0;
11493 dev_interface
->dbcc_classguid
= iface_guid
;
11494 strcpy(dev_interface
->dbcc_name
, "test name");
11495 dev_interface
->dbcc_size
= offsetof(DEV_BROADCAST_DEVICEINTERFACE_A
,
11496 dbcc_name
[strlen(dev_interface
->dbcc_name
)]);
11497 lRes
= SendMessageA(hwnd
, WM_DEVICECHANGE
, DBT_DEVICEARRIVAL
, (LPARAM
)dev_interface
);
11498 ok(lRes
== 2, "Got %Id, error %lu.\n", lRes
, GetLastError());
11500 DestroyWindow(hwnd
);
11502 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
11504 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
11505 WS_OVERLAPPEDWINDOW
,
11506 100, 100, 200, 200, 0, 0, 0, NULL
);
11507 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
11509 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
11510 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
11511 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
11512 "got bad length %Id\n", lRes
);
11515 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
11516 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
11517 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
11518 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
11519 "got bad length %Id\n", lRes
);
11521 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
11522 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
11523 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
11524 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
11525 NULL
, 0, NULL
, NULL
) ||
11526 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
11527 "got bad length %Id\n", lRes
);
11529 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
11530 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
11531 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
11532 NULL
, 0, NULL
, NULL
) ||
11533 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
11534 "got bad length %Id\n", lRes
);
11536 ret
= DestroyWindow(hwnd
);
11537 ok( ret
, "DestroyWindow() error %ld\n", GetLastError());
11547 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
11551 #define TIMER_ID 0x19
11552 #define TIMER_COUNT 500 /* 499 samples */
11553 #define TIMER_DURATION_EXPECTED 10000 /* 10 ms */
11554 #define TIMER_DURATION_ALT 15600 /* 15.6 ms */
11555 #define TIMER_DURATION_TOLERANCE 1000 /* 1 ms */
11557 static int count
= 0;
11558 static ULONGLONG timer_ticks
[TIMER_COUNT
];
11559 static int timer_duration
= 0;
11561 static int compare_ulonglong(const void *a
, const void *b
)
11564 la
= *(ULONGLONG
*)a
;
11565 lb
= *(ULONGLONG
*)b
;
11566 return (la
> lb
) - (la
< lb
);
11569 static void timer_fired(void)
11571 if (count
< TIMER_COUNT
)
11573 LARGE_INTEGER performance_counter
;
11576 ret
= QueryPerformanceCounter(&performance_counter
);
11577 ok(ret
, "QueryPerformanceCounter failed\n");
11579 timer_ticks
[count
] = performance_counter
.QuadPart
;
11584 if (count
== TIMER_COUNT
)
11586 LARGE_INTEGER performance_frequency
;
11589 /* calculate durations */
11590 for (int i
=0; i
< TIMER_COUNT
-1; i
++)
11591 timer_ticks
[i
] = timer_ticks
[i
+1] - timer_ticks
[i
];
11593 qsort(timer_ticks
, TIMER_COUNT
- 1, sizeof(timer_ticks
[0]), compare_ulonglong
);
11595 ret
= QueryPerformanceFrequency(&performance_frequency
);
11596 ok(ret
, "QueryPerformanceFrequency failed\n");
11598 /* median duration, converted to microseconds */
11599 timer_duration
= (int)(timer_ticks
[(TIMER_COUNT
- 1) / 2] * 1000000 / performance_frequency
.QuadPart
);
11603 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
11608 static DWORD exception
;
11609 static void CALLBACK
callback_exception(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
11612 RaiseException(exception
, 0, 0, NULL
);
11615 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
11617 struct timer_info
*info
= x
;
11620 r
= KillTimer(info
->hWnd
, 0x19);
11621 ok(r
,"KillTimer failed in thread\n");
11622 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
11623 ok(r
,"SetTimer failed in thread\n");
11624 ok(r
==TIMER_ID
,"SetTimer id different\n");
11625 r
= SetEvent(info
->handles
[0]);
11626 ok(r
,"SetEvent failed in thread\n");
11630 static void test_timers(void)
11632 struct timer_info info
;
11636 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
11637 WS_OVERLAPPEDWINDOW
,
11638 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
11641 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
11642 ok(info
.id
, "SetTimer failed\n");
11643 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
11644 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
11645 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
11647 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
11649 WaitForSingleObject(info
.handles
[1], INFINITE
);
11651 CloseHandle(info
.handles
[0]);
11652 CloseHandle(info
.handles
[1]);
11654 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
11656 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
11657 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
11661 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
11662 ok(id
!= 0, "did not get id from SetTimer.\n");
11663 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
11664 while (count
< TIMER_COUNT
&& GetMessageA(&msg
, info
.hWnd
, 0, 0))
11665 DispatchMessageA(&msg
);
11666 ok(abs(timer_duration
-TIMER_DURATION_EXPECTED
) < TIMER_DURATION_TOLERANCE
/* xp, win7 */
11667 || broken(abs(timer_duration
- TIMER_DURATION_ALT
) < TIMER_DURATION_TOLERANCE
) /* most common */,
11668 "did not get expected median timeout (%d != ~%d).\n",
11669 timer_duration
, TIMER_DURATION_EXPECTED
);
11670 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
11671 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
11672 if (pSetSystemTimer
)
11675 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
11676 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
11677 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
11678 while (count
< TIMER_COUNT
&& GetMessageA(&msg
, info
.hWnd
, 0, 0))
11680 if (msg
.message
== WM_SYSTIMER
)
11682 ok(msg
.message
!= WM_TIMER
, "unexpected WM_TIMER\n");
11683 DispatchMessageA(&msg
);
11685 ok(abs(timer_duration
-TIMER_DURATION_EXPECTED
) < TIMER_DURATION_TOLERANCE
11686 || broken(abs(timer_duration
- TIMER_DURATION_ALT
) < TIMER_DURATION_TOLERANCE
) /* most common */,
11687 "did not get expected median timeout (%d != ~%d).\n",
11688 timer_duration
, TIMER_DURATION_EXPECTED
);
11689 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
11692 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
11695 static void test_timers_no_wnd(void)
11697 static UINT_PTR ids
[0xffff];
11704 id
= SetTimer(NULL
, 0, 100, callback_count
);
11705 ok(id
!= 0, "did not get id from SetTimer.\n");
11706 id2
= SetTimer(NULL
, id
, 200, callback_count
);
11707 ok(id2
== id
, "did not get same id from SetTimer when replacing (%Ii expected %Ii).\n", id2
, id
);
11709 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11710 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
11712 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11713 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
11714 KillTimer(NULL
, id
);
11716 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11717 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
11719 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
11720 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
11724 id
= SetTimer(NULL
, 0, 0, callback_count
);
11725 ok(id
!= 0, "did not get id from SetTimer.\n");
11726 while (count
< TIMER_COUNT
&& GetMessageA(&msg
, NULL
, 0, 0))
11727 DispatchMessageA(&msg
);
11728 ok(abs(timer_duration
-TIMER_DURATION_EXPECTED
) < TIMER_DURATION_TOLERANCE
/* xp */
11729 || broken(abs(timer_duration
- TIMER_DURATION_ALT
) < TIMER_DURATION_TOLERANCE
) /* most common */,
11730 "did not get expected median timeout (%d != ~%d).\n",
11731 timer_duration
, TIMER_DURATION_EXPECTED
);
11732 KillTimer(NULL
, id
);
11733 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
11735 if (pSetCoalescableTimer
)
11738 id
= pSetCoalescableTimer(NULL
, 0, 0, callback_count
, 0);
11739 ok(id
!= 0, "SetCoalescableTimer failed with %lu.\n", GetLastError());
11740 start
= GetTickCount();
11741 while (GetTickCount()-start
< 100 && GetMessageA(&msg
, NULL
, 0, 0))
11742 DispatchMessageA(&msg
);
11743 ok(count
> 1, "expected count > 1, got %d.\n", count
);
11744 KillTimer(NULL
, id
);
11747 win_skip("SetCoalescableTimer not available.\n");
11749 /* Check what happens when we're running out of timers */
11750 for (i
= 0; i
< ARRAY_SIZE(ids
); i
++)
11752 SetLastError(0xdeadbeef);
11753 ids
[i
] = SetTimer(NULL
, 0, USER_TIMER_MAXIMUM
, tfunc
);
11754 if (!ids
[i
]) break;
11756 ok(i
!= ARRAY_SIZE(ids
), "all timers were created successfully\n");
11757 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES
|| broken(GetLastError()==0xdeadbeef),
11758 "GetLastError() = %ld\n", GetLastError());
11759 while (i
> 0) KillTimer(NULL
, ids
[--i
]);
11762 static void test_timers_exception(DWORD code
)
11768 id
= SetTimer(NULL
, 0, 1000, callback_exception
);
11769 ok(id
!= 0, "did not get id from SetTimer.\n");
11771 memset(&msg
, 0, sizeof(msg
));
11772 msg
.message
= WM_TIMER
;
11774 msg
.lParam
= (LPARAM
)callback_exception
;
11777 DispatchMessageA(&msg
);
11778 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
11780 KillTimer(NULL
, id
);
11783 static void test_timers_exceptions(void)
11785 test_timers_exception(EXCEPTION_ACCESS_VIOLATION
);
11786 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT
);
11787 test_timers_exception(EXCEPTION_BREAKPOINT
);
11788 test_timers_exception(EXCEPTION_SINGLE_STEP
);
11789 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED
);
11790 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND
);
11791 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO
);
11792 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT
);
11793 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION
);
11794 test_timers_exception(0xE000BEEF); /* customer exception */
11797 /* Various win events with arbitrary parameters */
11798 static const struct message WmWinEventsSeq
[] = {
11799 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
11800 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
11801 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
11802 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
11803 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
11804 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
11805 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
11806 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
11807 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
11808 /* our win event hook ignores OBJID_CURSOR events */
11809 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
11810 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
11811 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
11812 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
11813 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
11814 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
11815 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
11816 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
11817 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
11818 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
11819 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
11820 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
11821 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
11822 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
11825 static const struct message WmWinEventCaretSeq
[] = {
11826 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
11827 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
11828 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
11829 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
11832 static const struct message WmWinEventCaretSeq_2
[] = {
11833 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
11834 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
11835 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
11838 static const struct message WmWinEventAlertSeq
[] = {
11839 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
11842 static const struct message WmWinEventAlertSeq_2
[] = {
11843 /* create window in the thread proc */
11844 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
11845 /* our test event */
11846 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
11849 static const struct message WmGlobalHookSeq_1
[] = {
11850 /* create window in the thread proc */
11851 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
11852 /* our test events */
11853 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
11854 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
11857 static const struct message WmGlobalHookSeq_2
[] = {
11858 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
11859 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
11860 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
11861 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
11865 static const struct message WmMouseLLHookSeq
[] = {
11866 { WM_MOUSEMOVE
, hook
},
11867 { WM_LBUTTONUP
, hook
},
11868 { WM_MOUSEMOVE
, hook
},
11872 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
11882 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
11884 if (!lstrcmpiA(buf
, "TestWindowClass") ||
11885 !lstrcmpiA(buf
, "static"))
11887 struct recvd_message msg
;
11890 msg
.message
= event
;
11891 msg
.flags
= winevent_hook
|wparam
|lparam
;
11892 msg
.wParam
= object_id
;
11893 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
11894 msg
.descr
= "WEH_2";
11900 static HHOOK hCBT_global_hook
;
11901 static DWORD cbt_global_hook_thread_id
;
11903 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
11908 if (nCode
== HCBT_SYSCOMMAND
)
11910 struct recvd_message msg
;
11913 msg
.message
= nCode
;
11914 msg
.flags
= hook
|wparam
|lparam
;
11915 msg
.wParam
= wParam
;
11916 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
11917 msg
.descr
= "CBT_2";
11920 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11922 /* WH_MOUSE_LL hook */
11923 if (nCode
== HC_ACTION
)
11925 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
11927 /* we can't test for real mouse events */
11928 if (mhll
->flags
& LLMHF_INJECTED
)
11930 struct recvd_message msg
;
11932 memset (&msg
, 0, sizeof (msg
));
11933 msg
.message
= wParam
;
11935 msg
.descr
= "CBT_2";
11938 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11941 /* Log also SetFocus(0) calls */
11942 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
11944 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
11946 if (!lstrcmpiA(buf
, "TestWindowClass") ||
11947 !lstrcmpiA(buf
, "static"))
11949 struct recvd_message msg
;
11952 msg
.message
= nCode
;
11953 msg
.flags
= hook
|wparam
|lparam
;
11954 msg
.wParam
= wParam
;
11955 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
11956 msg
.descr
= "CBT_2";
11960 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11963 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
11967 HANDLE hevent
= *(HANDLE
*)param
;
11969 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
11970 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
11971 if (winetest_debug
> 1) trace("created thread window %p\n", hwnd
);
11973 *(HWND
*)param
= hwnd
;
11976 /* this event should be received only by our new hook proc,
11977 * an old one does not expect an event from another thread.
11979 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
11982 while (GetMessageA(&msg
, 0, 0, 0))
11984 TranslateMessage(&msg
);
11985 DispatchMessageA(&msg
);
11990 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
11994 HANDLE hevent
= *(HANDLE
*)param
;
11997 /* these events should be received only by our new hook proc,
11998 * an old one does not expect an event from another thread.
12001 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
12002 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
12003 if (winetest_debug
> 1) trace("created thread window %p\n", hwnd
);
12005 *(HWND
*)param
= hwnd
;
12007 /* Windows doesn't like when a thread plays games with the focus,
12008 that leads to all kinds of misbehaviours and failures to activate
12009 a window. So, better keep next lines commented out.
12013 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
12014 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
12018 while (GetMessageA(&msg
, 0, 0, 0))
12020 TranslateMessage(&msg
);
12021 DispatchMessageA(&msg
);
12026 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
12030 HANDLE hevent
= *(HANDLE
*)param
;
12032 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
12033 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
12034 if (winetest_debug
> 1) trace("created thread window %p\n", hwnd
);
12036 *(HWND
*)param
= hwnd
;
12040 /* Windows doesn't like when a thread plays games with the focus,
12041 * that leads to all kinds of misbehaviours and failures to activate
12042 * a window. So, better don't generate a mouse click message below.
12044 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12045 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
12046 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12049 while (GetMessageA(&msg
, 0, 0, 0))
12051 TranslateMessage(&msg
);
12052 DispatchMessageA(&msg
);
12057 static void test_winevents(void)
12063 HANDLE hthread
, hevent
;
12065 HWINEVENTHOOK hhook
;
12066 const struct message
*events
= WmWinEventsSeq
;
12068 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
12069 WS_OVERLAPPEDWINDOW
,
12070 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
12072 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
12074 /****** start of global hook test *************/
12075 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
12076 if (!hCBT_global_hook
)
12078 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12079 skip( "cannot set global hook\n" );
12083 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12084 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12087 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
12088 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12090 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12092 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
12095 /* this one should be received only by old hook proc */
12096 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
12097 /* this one should be received only by old hook proc */
12098 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
12100 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
12102 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
12103 ok( ret
, "UnhookWindowsHookEx error %ld\n", GetLastError());
12105 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12106 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12107 CloseHandle(hthread
);
12108 CloseHandle(hevent
);
12109 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12110 /****** end of global hook test *************/
12112 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
12114 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12122 /* this test doesn't pass under Win9x */
12123 /* win2k ignores events with hwnd == 0 */
12124 SetLastError(0xdeadbeef);
12125 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
12126 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
12127 GetLastError() == 0xdeadbeef, /* Win9x */
12128 "unexpected error %ld\n", GetLastError());
12129 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
12132 for (i
= 0; i
< ARRAY_SIZE(WmWinEventsSeq
); i
++)
12133 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
12135 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
12137 /****** start of event filtering test *************/
12138 hhook
= pSetWinEventHook(
12139 EVENT_OBJECT_SHOW
, /* 0x8002 */
12140 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
12141 GetModuleHandleA(0), win_event_global_hook_proc
,
12142 GetCurrentProcessId(), 0,
12143 WINEVENT_INCONTEXT
);
12144 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12146 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12147 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12150 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
12151 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12153 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12155 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
12158 /* this one should be received only by old hook proc */
12159 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
12160 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
12161 /* this one should be received only by old hook proc */
12162 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
12164 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
12166 ret
= pUnhookWinEvent(hhook
);
12167 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12169 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12170 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12171 CloseHandle(hthread
);
12172 CloseHandle(hevent
);
12173 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12174 /****** end of event filtering test *************/
12176 /****** start of out of context event test *************/
12177 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
12178 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
12179 WINEVENT_OUTOFCONTEXT
);
12180 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12182 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12183 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12188 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
12189 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12191 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12193 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
12194 /* process pending winevent messages */
12195 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
12196 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
12199 /* this one should be received only by old hook proc */
12200 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
12201 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
12202 /* this one should be received only by old hook proc */
12203 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
12205 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
12206 /* process pending winevent messages */
12207 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
12208 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
12210 ret
= pUnhookWinEvent(hhook
);
12211 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12213 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12214 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12215 CloseHandle(hthread
);
12216 CloseHandle(hevent
);
12217 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12218 /****** end of out of context event test *************/
12220 /****** start of MOUSE_LL hook test *************/
12221 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
12222 /* WH_MOUSE_LL is not supported on Win9x platforms */
12223 if (!hCBT_global_hook
)
12225 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
12226 goto skip_mouse_ll_hook_test
;
12229 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12230 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12233 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
12234 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12236 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
12237 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
12239 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
12242 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12243 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
12244 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12246 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
12248 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
12249 ok( ret
, "UnhookWindowsHookEx error %ld\n", GetLastError());
12251 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12252 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12253 CloseHandle(hthread
);
12254 CloseHandle(hevent
);
12255 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12256 /****** end of MOUSE_LL hook test *************/
12257 skip_mouse_ll_hook_test
:
12259 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12262 static char *get_test_dll_path(void)
12264 static const char *dll_name
= "testdll.dll";
12265 static char path
[MAX_PATH
];
12271 GetTempPathA(ARRAY_SIZE(path
), path
);
12272 strcat(path
, dll_name
);
12274 file
= CreateFileA(path
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
12275 ok(file
!= INVALID_HANDLE_VALUE
, "Failed to create file %s: %lu.\n", debugstr_a(path
), GetLastError());
12277 res
= FindResourceA(NULL
, dll_name
, "TESTDLL");
12278 ok(!!res
, "Failed to load resource: %lu\n", GetLastError());
12279 ptr
= LockResource(LoadResource(GetModuleHandleA(NULL
), res
));
12280 WriteFile(file
, ptr
, SizeofResource(GetModuleHandleA(NULL
), res
), &written
, NULL
);
12281 ok(written
== SizeofResource(GetModuleHandleA(NULL
), res
), "Failed to write resource\n");
12287 static void test_set_hook(void)
12289 LRESULT (CALLBACK
*p_dummy_hook_proc
)(int code
, WPARAM wp
, LPARAM lp
);
12290 HMODULE test_dll_module
;
12291 char *test_dll_path
;
12295 HWINEVENTHOOK hwinevent_hook
;
12298 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
12299 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
12300 UnhookWindowsHookEx(hhook
);
12302 SetLastError(0xdeadbeef);
12303 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
12304 ok(!hhook
, "global hook requires hModule != 0\n");
12305 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
12307 SetLastError(0xdeadbeef);
12308 hhook
= SetWindowsHookExA(WH_JOURNALRECORD
, cbt_hook_proc
, 0, 0);
12309 ok(!hhook
, "global hook requires hModule != 0\n");
12310 ok(GetLastError() == ERROR_ACCESS_DENIED
, "unexpected error %ld\n", GetLastError());
12312 SetLastError(0xdeadbeef);
12313 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
12314 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
12315 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
, "unexpected error %ld\n", GetLastError());
12317 SetLastError(0xdeadbeef);
12318 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
12319 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
, "unexpected error %ld\n", GetLastError());
12321 test_dll_path
= get_test_dll_path();
12322 test_dll_module
= LoadLibraryA(test_dll_path
);
12323 p_dummy_hook_proc
= (void *)GetProcAddress(test_dll_module
, "dummy_hook_proc");
12324 for (i
= WH_MIN
; i
<= WH_MAX
; i
++)
12326 winetest_push_context("ID %d", i
);
12328 /* Test that setting hooks should succeed for hook procs in a library. But for WH_JOURNALRECORD
12329 * and WH_JOURNALPLAYBACK, ERROR_ACCESS_DENIED is returned, even with administrator rights */
12330 SetLastError(0xdeadbeef);
12331 hhook
= SetWindowsHookExA(i
, p_dummy_hook_proc
, test_dll_module
, 0);
12332 error
= GetLastError();
12333 if (i
== WH_JOURNALRECORD
|| i
== WH_JOURNALPLAYBACK
)
12335 ok(!hhook
, "SetWinEventHook succeeded.\n");
12336 ok(error
== ERROR_ACCESS_DENIED
, "Got unexpected error %ld.\n", GetLastError());
12340 ok(!!hhook
, "SetWinEventHook failed.\n");
12341 ok(error
== NO_ERROR
, "Got unexpected error %ld.\n", GetLastError());
12344 UnhookWindowsHookEx(hhook
);
12346 /* Test settings global hooks with a thread ID */
12347 SetLastError(0xdeadbeef);
12348 hhook
= SetWindowsHookExA(i
, p_dummy_hook_proc
, test_dll_module
, GetCurrentThreadId());
12349 error
= GetLastError();
12350 if (i
== WH_JOURNALRECORD
|| i
== WH_JOURNALPLAYBACK
|| i
== WH_SYSMSGFILTER
12351 || i
== WH_KEYBOARD_LL
|| i
== WH_MOUSE_LL
)
12353 ok(!hhook
, "SetWinEventHook succeeded.\n");
12354 ok(error
== ERROR_GLOBAL_ONLY_HOOK
, "Got unexpected error %ld.\n", GetLastError());
12358 ok(!!hhook
, "SetWinEventHook failed.\n");
12359 ok(error
== NO_ERROR
, "Got unexpected error %ld.\n", GetLastError());
12362 UnhookWindowsHookEx(hhook
);
12364 winetest_pop_context();
12366 FreeLibrary(test_dll_module
);
12367 ret
= DeleteFileA(test_dll_path
);
12368 ok(ret
, "Failed to remove the test dll, error %ld.\n", GetLastError());
12370 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
12372 /* even process local incontext hooks require hmodule */
12373 SetLastError(0xdeadbeef);
12374 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12375 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
12376 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
12377 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
12379 /* even thread local incontext hooks require hmodule */
12380 SetLastError(0xdeadbeef);
12381 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12382 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
12383 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
12384 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
12386 SetLastError(0xdeadbeef);
12387 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
12388 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
12389 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
12390 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
12392 SetLastError(0xdeadbeef);
12393 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
12394 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
12395 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
12396 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
12398 SetLastError(0xdeadbeef);
12399 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12400 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
12401 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
12403 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %ld\n", GetLastError());
12405 SetLastError(0xdeadbeef);
12406 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
12407 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
12408 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12409 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
12410 ret
= pUnhookWinEvent(hwinevent_hook
);
12411 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12414 /* This call succeeds under win2k SP4, but fails under Wine.
12415 Does win2k test/use passed process id? */
12416 SetLastError(0xdeadbeef);
12417 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12418 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
12419 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12420 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
12421 ret
= pUnhookWinEvent(hwinevent_hook
);
12422 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12425 SetLastError(0xdeadbeef);
12426 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
12427 ok(GetLastError() == ERROR_INVALID_HANDLE
, "unexpected error %ld\n", GetLastError());
12430 static HWND hook_hwnd
;
12431 static HHOOK recursive_hook
;
12432 static int hook_depth
, max_hook_depth
;
12434 static LRESULT WINAPI
rec_get_message_hook(int code
, WPARAM w
, LPARAM l
)
12441 if(hook_depth
> max_hook_depth
)
12442 max_hook_depth
= hook_depth
;
12444 b
= PeekMessageW(&msg
, hook_hwnd
, 0, 0, PM_NOREMOVE
);
12445 ok(b
, "PeekMessage failed\n");
12447 res
= CallNextHookEx(recursive_hook
, code
, w
, l
);
12453 static void test_recursive_hook(void)
12458 hook_hwnd
= CreateWindowA("Static", NULL
, WS_POPUP
, 0, 0, 200, 60, NULL
, NULL
, NULL
, NULL
);
12459 ok(hook_hwnd
!= NULL
, "CreateWindow failed\n");
12461 recursive_hook
= SetWindowsHookExW(WH_GETMESSAGE
, rec_get_message_hook
, NULL
, GetCurrentThreadId());
12462 ok(recursive_hook
!= NULL
, "SetWindowsHookEx failed\n");
12464 PostMessageW(hook_hwnd
, WM_USER
, 0, 0);
12465 PostMessageW(hook_hwnd
, WM_USER
+1, 0, 0);
12468 GetMessageW(&msg
, hook_hwnd
, 0, 0);
12469 ok(15 <= max_hook_depth
&& max_hook_depth
< 45, "max_hook_depth = %d\n", max_hook_depth
);
12470 if (winetest_debug
> 1) trace("max_hook_depth = %d\n", max_hook_depth
);
12472 b
= UnhookWindowsHookEx(recursive_hook
);
12473 ok(b
, "UnhokWindowsHookEx failed\n");
12475 DestroyWindow(hook_hwnd
);
12478 static const struct message ScrollWindowPaint1
[] = {
12479 { WM_PAINT
, sent
},
12480 { WM_ERASEBKGND
, sent
|beginpaint
},
12481 { WM_GETTEXTLENGTH
, sent
|optional
},
12482 { WM_PAINT
, sent
|optional
},
12483 { WM_NCPAINT
, sent
|beginpaint
|optional
},
12484 { WM_GETTEXT
, sent
|beginpaint
|optional
},
12485 { WM_GETTEXT
, sent
|beginpaint
|optional
},
12486 { WM_GETTEXT
, sent
|beginpaint
|optional
},
12487 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
12488 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
12492 static const struct message ScrollWindowPaint2
[] = {
12493 { WM_PAINT
, sent
},
12497 static void test_scrollwindowex(void)
12500 RECT rect
={0,0,130,130};
12502 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
12503 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
12504 100, 100, 200, 200, 0, 0, 0, NULL
);
12505 ok (hwnd
!= 0, "Failed to create overlapped window\n");
12506 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
12507 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
12508 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
12509 ok (hchild
!= 0, "Failed to create child\n");
12510 UpdateWindow(hwnd
);
12514 /* scroll without the child window */
12515 if (winetest_debug
> 1) trace("start scroll\n");
12516 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
12517 SW_ERASE
|SW_INVALIDATE
);
12518 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
12519 if (winetest_debug
> 1) trace("end scroll\n");
12522 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
12526 /* Now without the SW_ERASE flag */
12527 if (winetest_debug
> 1) trace("start scroll\n");
12528 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
12529 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
12530 if (winetest_debug
> 1) trace("end scroll\n");
12533 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
12537 /* now scroll the child window as well */
12538 if (winetest_debug
> 1) trace("start scroll\n");
12539 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
12540 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
12541 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
12542 /* windows sometimes a WM_MOVE */
12543 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
12544 if (winetest_debug
> 1) trace("end scroll\n");
12547 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
12551 /* now scroll with ScrollWindow() */
12552 if (winetest_debug
> 1) trace("start scroll with ScrollWindow\n");
12553 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
12554 if (winetest_debug
> 1) trace("end scroll\n");
12557 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
12559 ok(DestroyWindow(hchild
), "failed to destroy window\n");
12560 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12564 static const struct message destroy_window_with_children
[] = {
12565 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* popup */
12566 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
12567 { 0x0090, sent
|optional
},
12568 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12569 { 0x0090, sent
|optional
},
12570 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* popup */
12571 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12572 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12573 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12574 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* parent */
12575 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
12576 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
12577 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
12578 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
12579 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
12580 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
12581 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
12582 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
12586 static void test_DestroyWindow(void)
12589 HWND parent
, child1
, child2
, child3
, child4
, test
;
12590 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
12592 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12593 100, 100, 200, 200, 0, 0, 0, NULL
);
12594 ok(!!parent
, "Failed to create window, error %lu.\n", GetLastError());
12595 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
12596 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
12597 ok(!!child1
, "Failed to create window, error %lu.\n", GetLastError());
12598 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
12599 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
12600 ok(!!child2
, "Failed to create window, error %lu.\n", GetLastError());
12601 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
12602 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
12603 ok(!!child3
, "Failed to create window, error %lu.\n", GetLastError());
12604 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
12605 0, 0, 50, 50, parent
, 0, 0, NULL
);
12606 ok(!!child4
, "Failed to create window, error %lu.\n", GetLastError());
12608 /* test owner/parent of child2 */
12609 test
= GetParent(child2
);
12610 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12611 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
12612 test
= GetAncestor(child2
, GA_PARENT
);
12613 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12614 test
= GetWindow(child2
, GW_OWNER
);
12615 ok(!test
, "wrong owner %p\n", test
);
12617 test
= SetParent(child2
, parent
);
12618 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
12620 /* test owner/parent of the parent */
12621 test
= GetParent(parent
);
12622 ok(!test
, "wrong parent %p\n", test
);
12623 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
12624 test
= GetAncestor(parent
, GA_PARENT
);
12625 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12626 test
= GetWindow(parent
, GW_OWNER
);
12627 ok(!test
, "wrong owner %p\n", test
);
12629 /* test owner/parent of child1 */
12630 test
= GetParent(child1
);
12631 ok(test
== parent
, "wrong parent %p\n", test
);
12632 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
12633 test
= GetAncestor(child1
, GA_PARENT
);
12634 ok(test
== parent
, "wrong parent %p\n", test
);
12635 test
= GetWindow(child1
, GW_OWNER
);
12636 ok(!test
, "wrong owner %p\n", test
);
12638 /* test owner/parent of child2 */
12639 test
= GetParent(child2
);
12640 ok(test
== parent
, "wrong parent %p\n", test
);
12641 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
12642 test
= GetAncestor(child2
, GA_PARENT
);
12643 ok(test
== parent
, "wrong parent %p\n", test
);
12644 test
= GetWindow(child2
, GW_OWNER
);
12645 ok(!test
, "wrong owner %p\n", test
);
12647 /* test owner/parent of child3 */
12648 test
= GetParent(child3
);
12649 ok(test
== child1
, "wrong parent %p\n", test
);
12650 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
12651 test
= GetAncestor(child3
, GA_PARENT
);
12652 ok(test
== child1
, "wrong parent %p\n", test
);
12653 test
= GetWindow(child3
, GW_OWNER
);
12654 ok(!test
, "wrong owner %p\n", test
);
12656 /* test owner/parent of child4 */
12657 test
= GetParent(child4
);
12658 ok(test
== parent
, "wrong parent %p\n", test
);
12659 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
12660 test
= GetAncestor(child4
, GA_PARENT
);
12661 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12662 test
= GetWindow(child4
, GW_OWNER
);
12663 ok(test
== parent
, "wrong owner %p\n", test
);
12667 if (winetest_debug
> 1) trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
12668 parent
, child1
, child2
, child3
, child4
);
12670 SetCapture(child4
);
12671 test
= GetCapture();
12672 ok(test
== child4
, "wrong capture window %p\n", test
);
12674 test_DestroyWindow_flag
= TRUE
;
12675 ret
= DestroyWindow(parent
);
12676 ok( ret
, "DestroyWindow() error %ld\n", GetLastError());
12677 test_DestroyWindow_flag
= FALSE
;
12678 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
12680 ok(!IsWindow(parent
), "parent still exists\n");
12681 ok(!IsWindow(child1
), "child1 still exists\n");
12682 ok(!IsWindow(child2
), "child2 still exists\n");
12683 ok(!IsWindow(child3
), "child3 still exists\n");
12684 ok(!IsWindow(child4
), "child4 still exists\n");
12686 test
= GetCapture();
12687 ok(!test
, "wrong capture window %p\n", test
);
12691 static const struct message WmDispatchPaint
[] = {
12692 { WM_NCPAINT
, sent
},
12693 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12694 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12695 { WM_ERASEBKGND
, sent
},
12699 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12701 if (message
== WM_PAINT
) return 0;
12702 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
12705 static void test_DispatchMessage(void)
12710 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12711 100, 100, 200, 200, 0, 0, 0, NULL
);
12712 ShowWindow( hwnd
, SW_SHOW
);
12713 UpdateWindow( hwnd
);
12716 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
12718 SetRect( &rect
, -5, -5, 5, 5 );
12719 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
12721 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
12723 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
12727 DispatchMessageA( &msg
);
12728 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
12729 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
12730 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
12731 if (++count
> 10) break;
12734 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
12736 if (winetest_debug
> 1) trace("now without DispatchMessage\n");
12738 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
12740 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
12742 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
12745 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
12747 /* this will send WM_NCCPAINT just like DispatchMessage does */
12748 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
12749 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
12750 DeleteObject( hrgn
);
12751 GetClientRect( hwnd
, &rect
);
12752 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
12753 ok( !count
, "Got multiple WM_PAINTs\n" );
12754 if (++count
> 10) break;
12759 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
12761 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
12763 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
12769 hdc
= BeginPaint( hwnd
, NULL
);
12770 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
12771 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
12772 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
12773 ok( !count
, "Got multiple WM_PAINTs\n" );
12774 if (++count
> 10) break;
12777 DestroyWindow(hwnd
);
12781 static const struct message WmUser
[] = {
12786 struct sendmsg_info
12794 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
12796 struct sendmsg_info
*info
= arg
;
12797 SetLastError( 0xdeadbeef );
12798 SetEvent( info
->ready
);
12799 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
12800 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
12801 broken(GetLastError() == 0), /* win9x */
12802 "unexpected error %ld\n", GetLastError());
12806 static void wait_for_thread( HANDLE thread
)
12808 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
12811 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
12815 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12817 if (message
== WM_USER
) Sleep(200);
12818 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
12821 static void test_SendMessageTimeout(void)
12824 struct sendmsg_info info
;
12828 info
.ready
= CreateEventA( NULL
, 0, 0, NULL
);
12829 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12830 100, 100, 200, 200, 0, 0, 0, NULL
);
12834 info
.timeout
= 1000;
12835 info
.ret
= 0xdeadbeef;
12836 ResetEvent( info
.ready
);
12837 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
12838 WaitForSingleObject( info
.ready
, INFINITE
);
12839 wait_for_thread( thread
);
12840 CloseHandle( thread
);
12841 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
12842 ok_sequence( WmUser
, "WmUser", FALSE
);
12845 info
.ret
= 0xdeadbeef;
12846 ResetEvent( info
.ready
);
12847 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
12848 WaitForSingleObject( info
.ready
, INFINITE
);
12849 Sleep(100); /* SendMessageTimeout should time out here */
12850 wait_for_thread( thread
);
12851 CloseHandle( thread
);
12852 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
12853 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
12855 /* 0 means infinite timeout (but not on win9x) */
12857 info
.ret
= 0xdeadbeef;
12858 ResetEvent( info
.ready
);
12859 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
12860 WaitForSingleObject( info
.ready
, INFINITE
);
12862 wait_for_thread( thread
);
12863 CloseHandle( thread
);
12864 is_win9x
= !info
.ret
;
12865 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
12866 else ok_sequence( WmUser
, "WmUser", FALSE
);
12868 /* timeout is treated as signed despite the prototype (but not on win9x) */
12869 info
.timeout
= 0x7fffffff;
12870 info
.ret
= 0xdeadbeef;
12871 ResetEvent( info
.ready
);
12872 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
12873 WaitForSingleObject( info
.ready
, INFINITE
);
12875 wait_for_thread( thread
);
12876 CloseHandle( thread
);
12877 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
12878 ok_sequence( WmUser
, "WmUser", FALSE
);
12880 info
.timeout
= 0x80000000;
12881 info
.ret
= 0xdeadbeef;
12882 ResetEvent( info
.ready
);
12883 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
12884 WaitForSingleObject( info
.ready
, INFINITE
);
12886 wait_for_thread( thread
);
12887 CloseHandle( thread
);
12890 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
12891 ok_sequence( WmUser
, "WmUser", FALSE
);
12895 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
12896 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
12899 /* now check for timeout during message processing */
12900 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
12901 info
.timeout
= 100;
12902 info
.ret
= 0xdeadbeef;
12903 ResetEvent( info
.ready
);
12904 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
12905 WaitForSingleObject( info
.ready
, INFINITE
);
12906 wait_for_thread( thread
);
12907 CloseHandle( thread
);
12908 /* we should time out but still get the message */
12909 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
12910 ok_sequence( WmUser
, "WmUser", FALSE
);
12912 DestroyWindow( info
.hwnd
);
12913 CloseHandle( info
.ready
);
12917 /****************** edit message test *************************/
12918 #define ID_EDIT 0x1234
12919 static const struct message sl_edit_setfocus
[] =
12921 { HCBT_SETFOCUS
, hook
},
12922 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
12923 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
12924 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
12925 { WM_SETFOCUS
, sent
|wparam
, 0 },
12926 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
12927 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
12928 { WM_CTLCOLOREDIT
, sent
|parent
},
12929 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12930 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12931 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12932 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
12935 static const struct message sl_edit_invisible
[] =
12937 { HCBT_SETFOCUS
, hook
},
12938 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
12939 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
12940 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Sent for IME. */
12941 { WM_KILLFOCUS
, sent
|parent
},
12942 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12943 { WM_SETFOCUS
, sent
},
12944 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12945 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12946 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
12949 static const struct message ml_edit_setfocus
[] =
12951 { HCBT_SETFOCUS
, hook
},
12952 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
12953 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
12954 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
12955 { WM_SETFOCUS
, sent
|wparam
, 0 },
12956 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
12957 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12958 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12959 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12960 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
12961 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
12964 static const struct message sl_edit_killfocus
[] =
12966 { HCBT_SETFOCUS
, hook
},
12967 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
12968 { WM_KILLFOCUS
, sent
|wparam
, 0 },
12969 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12970 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12971 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
12972 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
12973 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
12976 static const struct message sl_edit_lbutton_dblclk
[] =
12978 { WM_LBUTTONDBLCLK
, sent
},
12979 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
12982 static const struct message sl_edit_lbutton_down
[] =
12984 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
12985 { HCBT_SETFOCUS
, hook
},
12986 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
12987 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
12988 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
12989 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
12990 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
12991 { WM_CTLCOLOREDIT
, sent
|parent
},
12992 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12993 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12994 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
12995 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12996 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
12997 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
12998 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12999 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
13000 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13001 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
13002 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
13005 static const struct message ml_edit_lbutton_down
[] =
13007 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
13008 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13009 { HCBT_SETFOCUS
, hook
},
13010 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13011 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13012 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
13013 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
13014 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
13015 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13016 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
13017 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
13018 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
13021 static const struct message sl_edit_lbutton_up
[] =
13023 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
13024 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
13025 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13026 { WM_CAPTURECHANGED
, sent
|defwinproc
},
13027 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
13030 static const struct message ml_edit_lbutton_up
[] =
13032 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
13033 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13034 { WM_CAPTURECHANGED
, sent
|defwinproc
},
13038 static WNDPROC old_edit_proc
;
13040 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13042 static LONG defwndproc_counter
= 0;
13044 struct recvd_message msg
;
13046 if (ignore_message( message
)) return 0;
13049 msg
.message
= message
;
13050 msg
.flags
= sent
|wparam
|lparam
;
13051 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
13052 msg
.wParam
= wParam
;
13053 msg
.lParam
= lParam
;
13054 msg
.descr
= "edit";
13057 defwndproc_counter
++;
13058 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
13059 defwndproc_counter
--;
13064 static const struct message edit_wm_ime_composition_seq
[] =
13066 {WM_IME_STARTCOMPOSITION
, sent
},
13067 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13068 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'W'},
13069 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'i'},
13070 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'n'},
13071 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'e'},
13072 {WM_IME_ENDCOMPOSITION
, sent
},
13073 {WM_CHAR
, sent
| wparam
, 'W'},
13074 {WM_CHAR
, sent
| wparam
, 'i'},
13075 {WM_CHAR
, sent
| wparam
, 'n'},
13076 {WM_CHAR
, sent
| wparam
, 'e'},
13080 static const struct message edit_wm_ime_composition_korean_seq
[] =
13082 {WM_IME_ENDCOMPOSITION
, sent
},
13083 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13084 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'W'},
13085 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'i'},
13086 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'n'},
13087 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'e'},
13088 {WM_CHAR
, sent
| wparam
, 'W'},
13089 {WM_CHAR
, sent
| wparam
, 'i'},
13090 {WM_CHAR
, sent
| wparam
, 'n'},
13091 {WM_CHAR
, sent
| wparam
, 'e'},
13095 static const struct message edit_wm_ime_char_seq
[] =
13097 {WM_IME_CHAR
, sent
| wparam
, '0'},
13098 {WM_CHAR
, sent
| wparam
, '0'},
13102 static const struct message edit_eimes_getcompstratonce_seq
[] =
13104 {WM_IME_STARTCOMPOSITION
, sent
},
13105 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13106 {WM_IME_ENDCOMPOSITION
, sent
},
13110 static const struct message edit_eimes_getcompstratonce_korean_seq
[] =
13112 {WM_IME_ENDCOMPOSITION
, sent
},
13113 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13117 static LRESULT CALLBACK
edit_ime_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13119 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
13120 static LONG defwndproc_counter
= 0;
13121 struct recvd_message msg
= {0};
13124 msg
.message
= message
;
13125 msg
.flags
= sent
| wparam
;
13126 if (defwndproc_counter
)
13127 msg
.flags
|= defwinproc
;
13128 msg
.wParam
= wParam
;
13130 if (message
< 0xc000 &&
13131 message
!= WM_GETTEXTLENGTH
&&
13132 message
!= WM_GETTEXT
&&
13133 message
!= WM_GETFONT
&&
13134 message
!= WM_GETICON
&&
13135 message
!= WM_IME_SETCONTEXT
&&
13136 message
!= WM_IME_NOTIFY
&&
13137 message
!= WM_CTLCOLOREDIT
&&
13138 message
!= WM_PAINT
&&
13139 message
!= WM_ERASEBKGND
&&
13140 message
!= WM_NCHITTEST
&&
13141 message
!= WM_SETCURSOR
&&
13142 message
!= WM_MOUSEMOVE
&&
13143 message
!= WM_MOUSEACTIVATE
&&
13144 message
!= WM_KEYUP
&&
13145 (message
< EM_GETSEL
|| message
> EM_GETIMESTATUS
))
13150 defwndproc_counter
++;
13151 if (IsWindowUnicode(hwnd
))
13152 ret
= CallWindowProcW(oldproc
, hwnd
, message
, wParam
, lParam
);
13154 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
13155 defwndproc_counter
--;
13160 static DWORD WINAPI
test_edit_ime_messages(void *unused_arg
)
13162 static const HKL korean_hkl
= (HKL
)0x04120412;
13171 hkl
= GetKeyboardLayout(0);
13173 hwnd
= CreateWindowA(WC_EDITA
, "Test", WS_POPUP
| WS_VISIBLE
, 10, 10, 300, 300, NULL
, NULL
,
13175 ok(hwnd
!= NULL
, "CreateWindowA failed.\n");
13177 /* Test EM_{GET|SET}IMESTATUS */
13178 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13179 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13181 /* Note that EM_SETIMESTATUS always return 1, which is contrary to what MSDN says about
13182 * returning the previous LPARAM value */
13183 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
13184 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13185 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13186 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
13188 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_CANCELCOMPSTRINFOCUS
);
13189 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13190 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13191 ok(lr
== EIMES_CANCELCOMPSTRINFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
13193 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_COMPLETECOMPSTRKILLFOCUS
);
13194 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13195 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13196 ok(lr
== EIMES_COMPLETECOMPSTRKILLFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
13198 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
13199 | EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
);
13200 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13201 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13202 ok(lr
== (EIMES_GETCOMPSTRATONCE
| EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
),
13203 "Got unexpected lr %#Ix.\n", lr
);
13205 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13206 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13207 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13208 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13210 /* Invalid EM_{GET|SET}IMESTATUS status types and flags */
13211 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, 0, 0);
13212 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13214 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, 0);
13215 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13217 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, 0, EIMES_GETCOMPSTRATONCE
);
13218 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13219 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13220 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13222 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, EIMES_GETCOMPSTRATONCE
);
13223 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13224 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13225 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13227 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0xFFFFFFFF);
13228 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13229 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13230 ok(lr
== 0xFFFF, "Got unexpected lr %#Ix.\n", lr
);
13232 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13233 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13234 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13235 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13237 /* Test IME messages when EIMES_GETCOMPSTRATONCE is not set */
13238 old_proc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)edit_ime_subclass_proc
);
13239 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)old_proc
);
13241 himc
= ImmGetContext(hwnd
);
13242 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
13243 ok(ret
, "ImmSetCompositionStringA failed.\n");
13245 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
13246 ok(ret
, "ImmNotifyIME failed.\n");
13247 /* Note that the following message loop is necessary to get the WM_CHAR messages because they
13248 * are posted. Same for the later message loops in this function. */
13249 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13250 if (hkl
== korean_hkl
)
13251 ok_sequence(edit_wm_ime_composition_korean_seq
,
13252 "korean WM_IME_COMPOSITION", TRUE
);
13254 ok_sequence(edit_wm_ime_composition_seq
, "WM_IME_COMPOSITION", TRUE
);
13256 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR */
13258 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
13259 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13260 ok_sequence(edit_wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
13262 /* Test IME messages when EIMES_GETCOMPSTRATONCE is set */
13263 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
13264 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13265 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13266 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
13268 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
13269 ok(ret
, "ImmSetCompositionStringA failed.\n");
13271 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
13272 ok(ret
, "ImmNotifyIME failed.\n");
13273 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13274 if (hkl
== korean_hkl
)
13275 ok_sequence(edit_eimes_getcompstratonce_korean_seq
,
13276 "korean WM_IME_COMPOSITION with EIMES_GETCOMPSTRATONCE", TRUE
);
13278 ok_sequence(edit_eimes_getcompstratonce_seq
,
13279 "WM_IME_COMPOSITION with EIMES_GETCOMPSTRATONCE", TRUE
);
13281 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR with EIMES_GETCOMPSTRATONCE */
13283 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
13284 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13285 ok_sequence(edit_wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
13287 ImmReleaseContext(hwnd
, himc
);
13288 DestroyWindow(hwnd
);
13292 static void subclass_edit(void)
13297 ret
= GetClassInfoA(0, "edit", &cls
);
13298 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
13300 old_edit_proc
= cls
.lpfnWndProc
;
13302 cls
.hInstance
= GetModuleHandleA(NULL
);
13303 cls
.lpfnWndProc
= edit_hook_proc
;
13304 cls
.lpszClassName
= "my_edit_class";
13305 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
13306 register_class(&cls
);
13309 static void test_edit_messages(void)
13316 log_all_parent_messages
++;
13318 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13319 100, 100, 200, 200, 0, 0, 0, NULL
);
13320 ok (parent
!= 0, "Failed to create parent window\n");
13322 /* test single line edit */
13323 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
13324 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
13325 ok(hwnd
!= 0, "Failed to create edit window\n");
13327 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
13328 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", dlg_code
);
13332 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
13334 ShowWindow(hwnd
, SW_SHOW
);
13335 UpdateWindow(hwnd
);
13340 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
13343 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
13349 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
13350 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
13356 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
13357 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
13359 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
13360 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
13362 DestroyWindow(hwnd
);
13364 /* test multiline edit */
13365 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
13366 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
13367 ok(hwnd
!= 0, "Failed to create edit window\n");
13369 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
13370 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
13371 "wrong dlg_code %08lx\n", dlg_code
);
13373 ShowWindow(hwnd
, SW_SHOW
);
13374 UpdateWindow(hwnd
);
13379 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
13382 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
13388 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
13389 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
13395 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
13396 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
13398 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
13399 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
13401 DestroyWindow(hwnd
);
13402 DestroyWindow(parent
);
13404 log_all_parent_messages
--;
13406 /* Test IME messages in another thread because IME is disabled in the current thread */
13407 thread
= CreateThread(NULL
, 0, test_edit_ime_messages
, NULL
, 0, NULL
);
13408 WaitForSingleObject(thread
, INFINITE
);
13409 CloseHandle(thread
);
13412 /**************************** End of Edit test ******************************/
13414 static const struct message WmKeyDownSkippedSeq
[] =
13416 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
13419 static const struct message WmKeyDownWasDownSkippedSeq
[] =
13421 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
13424 static const struct message WmKeyUpSkippedSeq
[] =
13426 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
13429 static const struct message WmUserKeyUpSkippedSeq
[] =
13432 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
13437 #define EV_SENDMSG 1
13440 struct peekmsg_info
13443 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
13446 static DWORD CALLBACK
send_msg_thread_2(void *param
)
13449 struct peekmsg_info
*info
= param
;
13451 if (winetest_debug
> 1) trace("thread: looping\n");
13452 SetEvent(info
->hevent
[EV_ACK
]);
13456 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
13460 case WAIT_OBJECT_0
+ EV_STOP
:
13461 if (winetest_debug
> 1) trace("thread: exiting\n");
13464 case WAIT_OBJECT_0
+ EV_SENDMSG
:
13465 if (winetest_debug
> 1) trace("thread: sending message\n");
13466 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
13467 ok(ret
, "SendNotifyMessageA failed error %lu\n", GetLastError());
13468 SetEvent(info
->hevent
[EV_ACK
]);
13472 ok(0, "Unexpected return %#lx.\n", ret
);
13479 static void test_PeekMessage(void)
13483 DWORD tid
, qstatus
;
13484 UINT qs_all_input
= QS_ALLINPUT
;
13485 UINT qs_input
= QS_INPUT
;
13486 BOOL ret
, broken_flags
= FALSE
;
13487 struct peekmsg_info info
;
13489 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
13490 100, 100, 200, 200, 0, 0, 0, NULL
);
13491 ok(!!info
.hwnd
, "Failed to create window, error %lu.\n", GetLastError());
13492 ShowWindow(info
.hwnd
, SW_SHOW
);
13493 UpdateWindow(info
.hwnd
);
13494 SetFocus(info
.hwnd
);
13496 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
13497 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
13498 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
13500 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
13501 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
13506 SetLastError(0xdeadbeef);
13507 qstatus
= GetQueueStatus(qs_all_input
);
13508 if (GetLastError() == ERROR_INVALID_FLAGS
)
13510 trace("QS_RAWINPUT not supported on this platform\n");
13511 qs_all_input
&= ~QS_RAWINPUT
;
13512 qs_input
&= ~QS_RAWINPUT
;
13514 SetLastError(0xdeadbeef);
13515 qstatus
= GetQueueStatus(qs_all_input
);
13516 if (GetLastError() == ERROR_INVALID_FLAGS
)
13517 broken_flags
= TRUE
;
13518 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_INVALID_FLAGS
) /* win7 */,
13519 "wrong error %ld\n", GetLastError());
13521 if (qstatus
& QS_POSTMESSAGE
)
13523 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
13524 qstatus
= GetQueueStatus(qs_all_input
);
13526 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
13528 if (winetest_debug
> 1) trace("signalling to send message\n");
13529 SetEvent(info
.hevent
[EV_SENDMSG
]);
13530 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13532 /* pass invalid QS_xxxx flags */
13533 SetLastError(0xdeadbeef);
13534 qstatus
= GetQueueStatus(0xffffffff);
13535 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08lx\n", qstatus
);
13538 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %ld\n", GetLastError());
13539 SetLastError(0xdeadbeef);
13540 qstatus
= GetQueueStatus(qs_all_input
);
13541 ok(GetLastError() == 0xdeadbeef || broken(broken_flags
&& GetLastError() == ERROR_INVALID_FLAGS
),
13542 "wrong error %ld\n", GetLastError());
13544 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
13545 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
) ||
13546 broken(broken_flags
&& qstatus
== 0),
13547 "wrong qstatus %08lx\n", qstatus
);
13550 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
13552 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13554 ok_sequence(WmUser
, "WmUser", FALSE
);
13556 qstatus
= GetQueueStatus(qs_all_input
);
13557 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
13559 keybd_event('N', 0, 0, 0);
13560 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
13561 qstatus
= GetQueueStatus(qs_all_input
);
13562 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
13564 skip( "queuing key events not supported\n" );
13567 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
13568 /* keybd_event seems to trigger a sent message on NT4 */
13569 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
13570 "wrong qstatus %08lx\n", qstatus
);
13572 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13573 qstatus
= GetQueueStatus(qs_all_input
);
13574 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
13575 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
13576 "wrong qstatus %08lx\n", qstatus
);
13578 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
13579 qstatus
= GetQueueStatus(qs_all_input
);
13580 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
13581 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
13582 "wrong qstatus %08lx\n", qstatus
);
13584 if (winetest_debug
> 1) trace("signalling to send message\n");
13585 SetEvent(info
.hevent
[EV_SENDMSG
]);
13586 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13588 qstatus
= GetQueueStatus(qs_all_input
);
13589 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13590 "wrong qstatus %08lx\n", qstatus
);
13593 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
13594 if (ret
&& msg
.message
== WM_CHAR
)
13596 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
13600 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13602 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
13604 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
13607 ok_sequence(WmUser
, "WmUser", FALSE
);
13609 qstatus
= GetQueueStatus(qs_all_input
);
13610 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13611 "wrong qstatus %08lx\n", qstatus
);
13613 if (winetest_debug
> 1) trace("signalling to send message\n");
13614 SetEvent(info
.hevent
[EV_SENDMSG
]);
13615 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13617 qstatus
= GetQueueStatus(qs_all_input
);
13618 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13619 "wrong qstatus %08lx\n", qstatus
);
13622 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
13624 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13626 ok_sequence(WmUser
, "WmUser", FALSE
);
13628 qstatus
= GetQueueStatus(qs_all_input
);
13629 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13630 "wrong qstatus %08lx\n", qstatus
);
13633 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
13634 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13635 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13636 ret
, msg
.message
, msg
.wParam
);
13637 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13639 qstatus
= GetQueueStatus(qs_all_input
);
13640 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
13641 "wrong qstatus %08lx\n", qstatus
);
13644 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
13646 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13648 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13650 qstatus
= GetQueueStatus(qs_all_input
);
13651 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
13652 "wrong qstatus %08lx\n", qstatus
);
13655 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
13656 ok(ret
&& msg
.message
== WM_PAINT
,
13657 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
13658 DispatchMessageA(&msg
);
13659 ok_sequence(WmPaint
, "WmPaint", FALSE
);
13661 qstatus
= GetQueueStatus(qs_all_input
);
13662 ok(qstatus
== MAKELONG(0, QS_KEY
),
13663 "wrong qstatus %08lx\n", qstatus
);
13666 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
13668 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13670 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13672 qstatus
= GetQueueStatus(qs_all_input
);
13673 ok(qstatus
== MAKELONG(0, QS_KEY
),
13674 "wrong qstatus %08lx\n", qstatus
);
13676 if (winetest_debug
> 1) trace("signalling to send message\n");
13677 SetEvent(info
.hevent
[EV_SENDMSG
]);
13678 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13680 qstatus
= GetQueueStatus(qs_all_input
);
13681 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
13682 "wrong qstatus %08lx\n", qstatus
);
13684 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13686 qstatus
= GetQueueStatus(qs_all_input
);
13687 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
13688 "wrong qstatus %08lx\n", qstatus
);
13691 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
13692 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13693 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13694 ret
, msg
.message
, msg
.wParam
);
13695 ok_sequence(WmUser
, "WmUser", FALSE
);
13697 qstatus
= GetQueueStatus(qs_all_input
);
13698 ok(qstatus
== MAKELONG(0, QS_KEY
),
13699 "wrong qstatus %08lx\n", qstatus
);
13702 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
13704 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13706 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13708 qstatus
= GetQueueStatus(qs_all_input
);
13709 ok(qstatus
== MAKELONG(0, QS_KEY
),
13710 "wrong qstatus %08lx\n", qstatus
);
13712 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13714 qstatus
= GetQueueStatus(qs_all_input
);
13715 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
13716 "wrong qstatus %08lx\n", qstatus
);
13718 if (winetest_debug
> 1) trace("signalling to send message\n");
13719 SetEvent(info
.hevent
[EV_SENDMSG
]);
13720 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13722 qstatus
= GetQueueStatus(qs_all_input
);
13723 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
13724 "wrong qstatus %08lx\n", qstatus
);
13727 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
13729 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13731 ok_sequence(WmUser
, "WmUser", FALSE
);
13733 qstatus
= GetQueueStatus(qs_all_input
);
13734 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
13735 "wrong qstatus %08lx\n", qstatus
);
13738 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
13739 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
13740 else /* workaround for a missing QS_RAWINPUT support */
13741 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
13742 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
13743 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
13744 ret
, msg
.message
, msg
.wParam
);
13745 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
13747 qstatus
= GetQueueStatus(qs_all_input
);
13748 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
13749 "wrong qstatus %08lx\n", qstatus
);
13752 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
13753 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
13754 else /* workaround for a missing QS_RAWINPUT support */
13755 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
13756 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
13757 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYUP wParam 'N'\n",
13758 ret
, msg
.message
, msg
.wParam
);
13759 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
13761 qstatus
= GetQueueStatus(qs_all_input
);
13762 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
13763 "wrong qstatus %08lx\n", qstatus
);
13766 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
13768 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13770 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13772 qstatus
= GetQueueStatus(qs_all_input
);
13773 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
13774 "wrong qstatus %08lx\n", qstatus
);
13777 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
13778 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13779 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13780 ret
, msg
.message
, msg
.wParam
);
13781 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13783 qstatus
= GetQueueStatus(qs_all_input
);
13785 "wrong qstatus %08lx\n", qstatus
);
13788 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
13790 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13792 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13794 qstatus
= GetQueueStatus(qs_all_input
);
13796 "wrong qstatus %08lx\n", qstatus
);
13798 /* test whether presence of the quit flag in the queue affects
13801 PostQuitMessage(0x1234abcd);
13803 qstatus
= GetQueueStatus(qs_all_input
);
13804 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
13805 "wrong qstatus %08lx\n", qstatus
);
13807 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
13809 qstatus
= GetQueueStatus(qs_all_input
);
13810 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
13811 "wrong qstatus %08lx\n", qstatus
);
13814 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
13815 ok(ret
&& msg
.message
== WM_USER
,
13816 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
13817 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13819 qstatus
= GetQueueStatus(qs_all_input
);
13820 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
13821 "wrong qstatus %08lx\n", qstatus
);
13824 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
13825 ok(ret
&& msg
.message
== WM_QUIT
,
13826 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
13827 ok(msg
.wParam
== 0x1234abcd, "got wParam %08Ix instead of 0x1234abcd\n", msg
.wParam
);
13828 ok(msg
.lParam
== 0, "got lParam %08Ix instead of 0\n", msg
.lParam
);
13829 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13831 qstatus
= GetQueueStatus(qs_all_input
);
13833 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
13834 "wrong qstatus %08lx\n", qstatus
);
13838 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
13840 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13842 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13844 qstatus
= GetQueueStatus(qs_all_input
);
13846 "wrong qstatus %08lx\n", qstatus
);
13848 /* some GetMessage tests */
13850 keybd_event('N', 0, 0, 0);
13851 qstatus
= GetQueueStatus(qs_all_input
);
13852 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
13854 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13855 qstatus
= GetQueueStatus(qs_all_input
);
13856 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
13860 ret
= GetMessageA( &msg
, 0, 0, 0 );
13861 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13862 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13863 ret
, msg
.message
, msg
.wParam
);
13864 qstatus
= GetQueueStatus(qs_all_input
);
13865 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
13870 ret
= GetMessageA( &msg
, 0, 0, 0 );
13871 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
13872 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
13873 ret
, msg
.message
, msg
.wParam
);
13874 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
13875 qstatus
= GetQueueStatus(qs_all_input
);
13876 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
13879 keybd_event('N', 0, 0, 0);
13880 qstatus
= GetQueueStatus(qs_all_input
);
13881 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
13883 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13884 qstatus
= GetQueueStatus(qs_all_input
);
13885 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
13887 if (qstatus
& (QS_KEY
<< 16))
13889 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
13890 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
13891 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
13892 ret
, msg
.message
, msg
.wParam
);
13893 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
13894 qstatus
= GetQueueStatus(qs_all_input
);
13895 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08lx\n", qstatus
);
13900 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
13901 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13902 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13903 ret
, msg
.message
, msg
.wParam
);
13904 qstatus
= GetQueueStatus(qs_all_input
);
13905 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
13908 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
13909 qstatus
= GetQueueStatus(qs_all_input
);
13910 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
13912 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13913 qstatus
= GetQueueStatus(qs_all_input
);
13914 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "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
);
13919 qstatus
= GetQueueStatus(qs_all_input
);
13920 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
13921 "wrong qstatus %08lx\n", qstatus
);
13923 if (qstatus
& (QS_KEY
<< 16))
13925 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
13926 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
13927 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
13928 ret
, msg
.message
, msg
.wParam
);
13929 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
13930 qstatus
= GetQueueStatus(qs_all_input
);
13931 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08lx\n", qstatus
);
13936 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
13937 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13938 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13939 ret
, msg
.message
, msg
.wParam
);
13940 qstatus
= GetQueueStatus(qs_all_input
);
13941 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
13944 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
13945 ret
= PeekMessageA(&msg
, (HWND
)-1, 0, 0, PM_NOREMOVE
);
13946 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
13947 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
13948 ret
= GetMessageA(&msg
, (HWND
)-1, 0, 0);
13949 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
13950 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
13952 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
13953 ret
= PeekMessageA(&msg
, (HWND
)1, 0, 0, PM_NOREMOVE
);
13954 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
13955 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
13956 ret
= GetMessageA(&msg
, (HWND
)1, 0, 0);
13957 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
13958 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
13960 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
13961 ret
= PeekMessageA(&msg
, (HWND
)0xffff, 0, 0, PM_NOREMOVE
);
13962 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
13963 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
13964 ret
= GetMessageA(&msg
, (HWND
)0xffff, 0, 0);
13965 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
13966 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
13969 if (winetest_debug
> 1) trace("signalling to exit\n");
13970 SetEvent(info
.hevent
[EV_STOP
]);
13972 WaitForSingleObject(hthread
, INFINITE
);
13974 CloseHandle(hthread
);
13975 CloseHandle(info
.hevent
[0]);
13976 CloseHandle(info
.hevent
[1]);
13977 CloseHandle(info
.hevent
[2]);
13979 DestroyWindow(info
.hwnd
);
13982 static void wait_move_event(HWND hwnd
, int x
, int y
)
13985 DWORD timeout
= GetTickCount() + 500;
13989 while ((delay
= timeout
- GetTickCount()) > 0)
13991 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
13992 if (ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
) break;
13993 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, delay
, QS_ALLINPUT
);
13994 else Sleep( delay
);
13999 static void test_PeekMessage2(void)
14005 DWORD time1
, time2
, time3
;
14006 int x1
, y1
, x2
, y2
, x3
, y3
;
14009 time1
= time2
= time3
= 0;
14010 x1
= y1
= x2
= y2
= x3
= y3
= 0;
14012 /* Initialise window and make sure it is ready for events */
14013 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
14014 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
14015 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
14016 if (winetest_debug
> 1) trace("Window for test_PeekMessage2 %p\n", hwnd
);
14017 ShowWindow(hwnd
, SW_SHOW
);
14018 UpdateWindow(hwnd
);
14020 GetCursorPos(&pos
);
14021 SetCursorPos(100, 100);
14022 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
14025 /* Do initial mousemove, wait until we can see it
14026 and then do our test peek with PM_NOREMOVE. */
14027 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
14028 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
14030 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
14033 skip( "queuing mouse events not supported\n" );
14038 if (winetest_debug
> 1) trace("1st move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
14039 message
= msg
.message
;
14043 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
14046 /* Allow time to advance a bit, and then simulate the user moving their
14047 * mouse around. After that we peek again with PM_NOREMOVE.
14048 * Although the previous mousemove message was never removed, the
14049 * mousemove we now peek should reflect the recent mouse movements
14050 * because the input queue will merge the move events. */
14052 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
14053 wait_move_event(hwnd
, x1
, y1
);
14055 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
14056 ok(ret
, "no message available\n");
14058 if (winetest_debug
> 1) trace("2nd move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
14059 message
= msg
.message
;
14063 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
14064 ok(time2
> time1
, "message time not advanced: %lx %lx\n", time1
, time2
);
14065 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
14068 /* Have another go, to drive the point home */
14070 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
14071 wait_move_event(hwnd
, x2
, y2
);
14073 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
14074 ok(ret
, "no message available\n");
14076 if (winetest_debug
> 1) trace("3rd move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
14077 message
= msg
.message
;
14081 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
14082 ok(time3
> time2
, "message time not advanced: %lx %lx\n", time2
, time3
);
14083 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
14087 DestroyWindow(hwnd
);
14088 SetCursorPos(pos
.x
, pos
.y
);
14092 static void test_PeekMessage3(void)
14094 HWND parent_hwnd
, hwnd
;
14098 parent_hwnd
= CreateWindowA("SimpleWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW
,
14099 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
14100 ok(parent_hwnd
!= NULL
, "expected parent_hwnd != NULL\n");
14102 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage3", WS_CHILD
, 0, 0, 1, 1,
14103 parent_hwnd
, NULL
, NULL
, NULL
);
14104 ok(hwnd
!= NULL
, "expected hwnd != NULL\n");
14108 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
14109 * were already seen. */
14111 SetTimer(hwnd
, 1, 100, NULL
);
14112 while (!PeekMessageA(&msg
, hwnd
, 0, 0, PM_NOREMOVE
));
14113 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14114 PostMessageA(hwnd
, WM_USER
, 0, 0);
14115 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, PM_NOREMOVE
);
14117 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14118 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14120 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14121 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14123 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14124 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14125 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14127 SetTimer(hwnd
, 1, 100, NULL
);
14128 while (!PeekMessageA(&msg
, hwnd
, 0, 0, PM_NOREMOVE
));
14129 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14130 PostMessageA(hwnd
, WM_USER
, 0, 0);
14131 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, PM_REMOVE
);
14133 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14134 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, PM_REMOVE
);
14136 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14137 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14138 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14140 /* It doesn't matter if a message range is specified or not. */
14142 SetTimer(hwnd
, 1, 100, NULL
);
14143 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14144 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14145 PostMessageA(hwnd
, WM_USER
, 0, 0);
14146 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14148 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14149 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14151 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14152 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14153 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14155 /* But not if the post messages were added before the PeekMessage() call. */
14157 PostMessageA(hwnd
, WM_USER
, 0, 0);
14158 SetTimer(hwnd
, 1, 100, NULL
);
14159 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14160 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14161 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14162 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14163 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14164 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14165 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14166 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14168 /* More complicated test with multiple messages. */
14170 PostMessageA(hwnd
, WM_USER
, 0, 0);
14171 SetTimer(hwnd
, 1, 100, NULL
);
14172 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14173 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14174 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
14175 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14176 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14177 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14179 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14180 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14182 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
14183 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14184 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14186 /* Also works for posted messages, but the situation is a bit different,
14187 * because both messages are in the same queue. */
14189 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
14190 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14191 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14192 PostMessageA(hwnd
, WM_USER
, 0, 0);
14193 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14194 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14195 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14196 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14197 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14198 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14200 PostMessageA(hwnd
, WM_USER
, 0, 0);
14201 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
14202 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14203 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14204 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14205 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14206 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14207 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14208 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14209 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14211 DestroyWindow(parent_hwnd
);
14215 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14217 struct recvd_message msg
;
14219 if (ignore_message( message
)) return 0;
14222 msg
.message
= message
;
14223 msg
.flags
= sent
|wparam
|lparam
;
14226 msg
.descr
= "dialog";
14231 case WM_INITDIALOG
:
14232 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
14233 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
14236 case WM_GETDLGCODE
:
14240 EndDialog(hwnd
, 0);
14247 static const struct message WmQuitDialogSeq
[] = {
14248 { HCBT_CREATEWND
, hook
},
14249 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14250 { WM_SETFONT
, sent
},
14251 { WM_INITDIALOG
, sent
},
14252 { WM_CHANGEUISTATE
, sent
|optional
},
14253 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14254 { HCBT_DESTROYWND
, hook
},
14255 { 0x0090, sent
|optional
}, /* Vista */
14256 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14257 { WM_DESTROY
, sent
},
14258 { WM_NCDESTROY
, sent
},
14262 static const struct message WmStopQuitSeq
[] = {
14263 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
14264 { WM_CLOSE
, posted
},
14265 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
14269 static void test_quit_message(void)
14274 /* test using PostQuitMessage */
14276 PostQuitMessage(0xbeef);
14279 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_QS_SENDMESSAGE
);
14280 ok(!ret
, "got %x message\n", msg
.message
);
14282 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
14283 ok(ret
, "PeekMessage failed with error %ld\n", GetLastError());
14284 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14285 ok(msg
.wParam
== 0xbeef, "wParam was 0x%Ix instead of 0xbeef\n", msg
.wParam
);
14287 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
14288 ok(ret
, "PostMessage failed with error %ld\n", GetLastError());
14290 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14291 ok(ret
> 0, "GetMessage failed with error %ld\n", GetLastError());
14292 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
14294 /* note: WM_QUIT message received after WM_USER message */
14295 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14296 ok(!ret
, "GetMessage return %d with error %ld instead of FALSE\n", ret
, GetLastError());
14297 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14298 ok(msg
.wParam
== 0xbeef, "wParam was 0x%Ix instead of 0xbeef\n", msg
.wParam
);
14300 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
14301 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
14303 /* now test with PostThreadMessage - different behaviour! */
14304 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
14306 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
14307 ok(ret
, "PeekMessage failed with error %ld\n", GetLastError());
14308 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14309 ok(msg
.wParam
== 0xdead, "wParam was 0x%Ix instead of 0xdead\n", msg
.wParam
);
14311 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
14312 ok(ret
, "PostMessage failed with error %ld\n", GetLastError());
14314 /* note: we receive the WM_QUIT message first this time */
14315 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14316 ok(!ret
, "GetMessage return %d with error %ld instead of FALSE\n", ret
, GetLastError());
14317 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14318 ok(msg
.wParam
== 0xdead, "wParam was 0x%Ix instead of 0xdead\n", msg
.wParam
);
14320 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14321 ok(ret
> 0, "GetMessage failed with error %ld\n", GetLastError());
14322 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
14326 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
14327 ok(ret
== 1, "expected 1, got %d\n", ret
);
14328 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
14329 memset(&msg
, 0xab, sizeof(msg
));
14330 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
14331 ok(ret
, "PeekMessage failed\n");
14332 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14333 ok(msg
.wParam
== 0x1234, "wParam was 0x%Ix instead of 0x1234\n", msg
.wParam
);
14334 ok(msg
.lParam
== 0, "lParam was 0x%Ix instead of 0\n", msg
.lParam
);
14336 /* Check what happens to a WM_QUIT message posted to a window that gets
14339 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
14340 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
14342 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14344 struct recvd_message rmsg
;
14345 rmsg
.hwnd
= msg
.hwnd
;
14346 rmsg
.message
= msg
.message
;
14347 rmsg
.flags
= posted
|wparam
|lparam
;
14348 rmsg
.wParam
= msg
.wParam
;
14349 rmsg
.lParam
= msg
.lParam
;
14350 rmsg
.descr
= "stop/quit";
14351 if (msg
.message
== WM_QUIT
)
14352 /* The hwnd can only be checked here */
14353 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
14354 add_message(&rmsg
);
14355 DispatchMessageA(&msg
);
14357 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
14360 static const struct message WmNotifySeq
[] = {
14361 { WM_NOTIFY
, sent
|wparam
|lparam
, 0x1234, 0xdeadbeef },
14365 static void test_notify_message(void)
14371 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
14372 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0, NULL
, NULL
, 0);
14373 ok(hwnd
!= 0, "Failed to create window\n");
14377 ret
= SendNotifyMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14378 ok(ret
== TRUE
, "SendNotifyMessageA failed with error %lu\n", GetLastError());
14379 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14381 ret
= SendNotifyMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14382 ok(ret
== TRUE
, "SendNotifyMessageW failed with error %lu\n", GetLastError());
14383 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14385 ret
= SendMessageCallbackA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
14386 ok(ret
== TRUE
, "SendMessageCallbackA failed with error %lu\n", GetLastError());
14387 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14389 ret
= SendMessageCallbackW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
14390 ok(ret
== TRUE
, "SendMessageCallbackW failed with error %lu\n", GetLastError());
14391 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14393 ret
= PostMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14394 ok(ret
== TRUE
, "PostMessageA failed with error %lu\n", GetLastError());
14396 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14398 ret
= PostMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14399 ok(ret
== TRUE
, "PostMessageW failed with error %lu\n", GetLastError());
14401 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14403 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
14404 ok(ret
== TRUE
, "PostThreadMessageA failed with error %lu\n", GetLastError());
14405 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14408 DispatchMessageA(&msg
);
14410 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14412 ret
= PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
14413 ok(ret
== TRUE
, "PostThreadMessageW failed with error %lu\n", GetLastError());
14414 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14417 DispatchMessageA(&msg
);
14419 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14421 DestroyWindow(hwnd
);
14424 static const struct message WmMouseHoverSeq
[] = {
14425 { WM_GETMINMAXINFO
, sent
|optional
}, /* sometimes seen on w1064v1809 */
14426 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
14427 { WM_MOUSEACTIVATE
, sent
|optional
},
14428 { WM_TIMER
, sent
|optional
}, /* XP sends it */
14429 { WM_SYSTIMER
, sent
},
14430 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
14434 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
14437 DWORD start_ticks
, end_ticks
;
14439 start_ticks
= GetTickCount();
14440 /* add some deviation (50%) to cover not expected delays */
14441 start_ticks
+= timeout
/ 2;
14445 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14447 /* Timer proc messages are not dispatched to the window proc,
14448 * and therefore not logged.
14450 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
14452 struct recvd_message s_msg
;
14454 s_msg
.hwnd
= msg
.hwnd
;
14455 s_msg
.message
= msg
.message
;
14456 s_msg
.flags
= sent
|wparam
|lparam
;
14457 s_msg
.wParam
= msg
.wParam
;
14458 s_msg
.lParam
= msg
.lParam
;
14459 s_msg
.descr
= "msg_loop";
14460 add_message(&s_msg
);
14462 DispatchMessageA(&msg
);
14465 end_ticks
= GetTickCount();
14467 /* inject WM_MOUSEMOVE to see how it changes tracking */
14468 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
14470 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
14471 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
14473 inject_mouse_move
= FALSE
;
14475 } while (start_ticks
+ timeout
>= end_ticks
);
14478 static void test_TrackMouseEvent(void)
14480 TRACKMOUSEEVENT tme
;
14483 RECT rc_parent
, rc_child
;
14484 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
14486 #define track_hover(track_hwnd, track_hover_time) \
14487 tme.cbSize = sizeof(tme); \
14488 tme.dwFlags = TME_HOVER; \
14489 tme.hwndTrack = track_hwnd; \
14490 tme.dwHoverTime = track_hover_time; \
14491 SetLastError(0xdeadbeef); \
14492 ret = pTrackMouseEvent(&tme); \
14493 ok(ret, "TrackMouseEvent(TME_HOVER) error %ld\n", GetLastError())
14495 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
14496 tme.cbSize = sizeof(tme); \
14497 tme.dwFlags = TME_QUERY; \
14498 tme.hwndTrack = (HWND)0xdeadbeef; \
14499 tme.dwHoverTime = 0xdeadbeef; \
14500 SetLastError(0xdeadbeef); \
14501 ret = pTrackMouseEvent(&tme); \
14502 ok(ret, "TrackMouseEvent(TME_QUERY) error %ld\n", GetLastError());\
14503 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %lu\n", tme.cbSize); \
14504 ok(tme.dwFlags == (expected_track_flags), \
14505 "wrong tme.dwFlags %08lx, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
14506 ok(tme.hwndTrack == (expected_track_hwnd), \
14507 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
14508 ok(tme.dwHoverTime == (expected_hover_time), \
14509 "wrong tme.dwHoverTime %lu, expected %u\n", tme.dwHoverTime, (expected_hover_time))
14511 #define track_hover_cancel(track_hwnd) \
14512 tme.cbSize = sizeof(tme); \
14513 tme.dwFlags = TME_HOVER | TME_CANCEL; \
14514 tme.hwndTrack = track_hwnd; \
14515 tme.dwHoverTime = 0xdeadbeef; \
14516 SetLastError(0xdeadbeef); \
14517 ret = pTrackMouseEvent(&tme); \
14518 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %ld\n", GetLastError())
14520 default_hover_time
= 0xdeadbeef;
14521 SetLastError(0xdeadbeef);
14522 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
14523 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
14524 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %lu\n", GetLastError());
14525 if (!ret
) default_hover_time
= 400;
14526 if (winetest_debug
> 1) trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
14528 SetLastError(0xdeadbeef);
14529 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
14530 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
14531 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %lu\n", GetLastError());
14532 if (!ret
) hover_width
= 4;
14533 SetLastError(0xdeadbeef);
14534 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
14535 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
14536 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %lu\n", GetLastError());
14537 if (!ret
) hover_height
= 4;
14538 if (winetest_debug
> 1) trace("hover rect is %u x %d\n", hover_width
, hover_height
);
14540 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
14541 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14542 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
14544 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
14546 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
14547 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
14548 50, 50, 200, 200, hwnd
,
14550 ok(!!hchild
, "Failed to create window, error %lu.\n", GetLastError());
14552 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
14557 tme
.dwFlags
= TME_QUERY
;
14558 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14559 tme
.dwHoverTime
= 0xdeadbeef;
14560 SetLastError(0xdeadbeef);
14561 ret
= pTrackMouseEvent(&tme
);
14562 ok(!ret
, "TrackMouseEvent should fail\n");
14563 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
14564 "not expected error %lu\n", GetLastError());
14566 tme
.cbSize
= sizeof(tme
);
14567 tme
.dwFlags
= TME_HOVER
;
14568 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14569 tme
.dwHoverTime
= 0xdeadbeef;
14570 SetLastError(0xdeadbeef);
14571 ret
= pTrackMouseEvent(&tme
);
14572 ok(!ret
, "TrackMouseEvent should fail\n");
14573 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14574 "not expected error %lu\n", GetLastError());
14576 tme
.cbSize
= sizeof(tme
);
14577 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
14578 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14579 tme
.dwHoverTime
= 0xdeadbeef;
14580 SetLastError(0xdeadbeef);
14581 ret
= pTrackMouseEvent(&tme
);
14582 ok(!ret
, "TrackMouseEvent should fail\n");
14583 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14584 "not expected error %lu\n", GetLastError());
14586 GetWindowRect(hwnd
, &rc_parent
);
14587 GetWindowRect(hchild
, &rc_child
);
14588 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
14590 /* Process messages so that the system updates its internal current
14591 * window and hittest, otherwise TrackMouseEvent calls don't have any
14597 track_query(0, NULL
, 0);
14598 track_hover(hchild
, 0);
14599 track_query(0, NULL
, 0);
14604 track_hover(hwnd
, 0);
14605 tme
.cbSize
= sizeof(tme
);
14606 tme
.dwFlags
= TME_QUERY
;
14607 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14608 tme
.dwHoverTime
= 0xdeadbeef;
14609 SetLastError(0xdeadbeef);
14610 ret
= pTrackMouseEvent(&tme
);
14611 ok(ret
, "TrackMouseEvent(TME_QUERY) error %ld\n", GetLastError());
14612 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %lu\n", tme
.cbSize
);
14615 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
14616 DestroyWindow( hwnd
);
14619 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08lx, expected TME_HOVER\n", tme
.dwFlags
);
14620 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
14621 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %lu, expected %u\n",
14622 tme
.dwHoverTime
, default_hover_time
);
14624 pump_msg_loop_timeout(default_hover_time
, FALSE
);
14625 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
14627 track_query(0, NULL
, 0);
14629 track_hover(hwnd
, HOVER_DEFAULT
);
14630 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14632 Sleep(default_hover_time
/ 2);
14633 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
14634 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
14636 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14638 pump_msg_loop_timeout(default_hover_time
, FALSE
);
14639 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
14641 track_query(0, NULL
, 0);
14643 track_hover(hwnd
, HOVER_DEFAULT
);
14644 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14646 pump_msg_loop_timeout(default_hover_time
, TRUE
);
14647 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
14649 track_query(0, NULL
, 0);
14651 track_hover(hwnd
, HOVER_DEFAULT
);
14652 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14653 track_hover_cancel(hwnd
);
14655 DestroyWindow(hwnd
);
14659 #undef track_hover_cancel
14663 static const struct message WmSetWindowRgn
[] = {
14664 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
14665 |SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
, 0 },
14666 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
14667 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
14668 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14669 { WM_ERASEBKGND
, sent
|optional
},
14670 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
14671 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14675 static const struct message WmSetWindowRgn_no_redraw
[] = {
14676 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
14677 |SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
, 0 },
14678 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
14679 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
14680 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14684 static const struct message WmSetWindowRgn_clear
[] = {
14685 { WM_WINDOWPOSCHANGING
, sent
/*|wparam|lparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
14686 |SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */
14687 /* Some newer Windows versions set window coordinates instead of zeros in WINDOWPOS structure */},
14688 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
14689 { WM_NCPAINT
, sent
|optional
},
14690 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14691 { WM_ERASEBKGND
, sent
|optional
}, /* FIXME: remove optional once Wine is fixed */
14692 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
14693 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
14694 { WM_NCPAINT
, sent
|optional
},
14695 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14696 { WM_ERASEBKGND
, sent
|optional
},
14697 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14698 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14699 { WM_WINDOWPOSCHANGING
, sent
|optional
},
14700 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
14701 { WM_NCPAINT
, sent
|optional
},
14702 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14703 { WM_ERASEBKGND
, sent
|optional
},
14704 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
14705 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
14706 { WM_NCPAINT
, sent
|optional
},
14707 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14708 { WM_ERASEBKGND
, sent
|optional
},
14709 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14710 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not always sent. */
14714 static void test_SetWindowRgn(void)
14717 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
14718 100, 100, 200, 200, 0, 0, 0, NULL
);
14719 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
14721 ShowWindow( hwnd
, SW_SHOW
);
14722 UpdateWindow( hwnd
);
14726 if (winetest_debug
> 1) trace("testing SetWindowRgn\n");
14727 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
14728 SetWindowRgn( hwnd
, hrgn
, TRUE
);
14729 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
14731 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
14732 SetWindowRgn( hwnd
, hrgn
, FALSE
);
14733 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
14735 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
14736 SetWindowRgn( hwnd
, hrgn
, TRUE
);
14737 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
14739 SetWindowRgn( hwnd
, 0, TRUE
);
14740 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
14742 DestroyWindow( hwnd
);
14745 /*************************** ShowWindow() test ******************************/
14746 static const struct message WmShowNormal
[] = {
14747 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
14748 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
14749 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14750 { HCBT_ACTIVATE
, hook
},
14751 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14752 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
14753 { HCBT_SETFOCUS
, hook
},
14754 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
14755 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14756 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
14759 static const struct message WmShow
[] = {
14760 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
14761 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
14762 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14763 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
14764 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
14765 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
14766 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14769 static const struct message WmShowNoActivate_1
[] = {
14770 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
14771 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14772 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14773 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14774 { WM_MOVE
, sent
|defwinproc
|optional
},
14775 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
14776 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14777 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14780 static const struct message WmShowNoActivate_2
[] = {
14781 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
14782 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
14783 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14784 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14785 { HCBT_ACTIVATE
, hook
|optional
},
14786 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
14787 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14788 { WM_WINDOWPOSCHANGED
, sent
|optional
}, /* Sometimes sent on Win8+. */
14789 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
14790 { HCBT_SETFOCUS
, hook
|optional
},
14791 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Win7 sends this. */
14792 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
14793 { WM_MOVE
, sent
|defwinproc
},
14794 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
14795 { HCBT_SETFOCUS
, hook
|optional
},
14796 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
14797 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
14798 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14799 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
14800 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14801 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14802 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14805 static const struct message WmShowNA_1
[] = {
14806 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
14807 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14808 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14809 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14812 static const struct message WmShowNA_2
[] = {
14813 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
14814 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14815 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14818 static const struct message WmRestore_1
[] = {
14819 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
14820 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14821 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14822 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14823 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
14824 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
14825 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
14826 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14827 { WM_MOVE
, sent
|defwinproc
},
14828 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
14829 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14830 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14831 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14832 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
14833 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
14836 static const struct message WmRestore_2
[] = {
14837 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
14838 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
14839 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14840 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
14841 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
14842 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
14843 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14846 static const struct message WmRestore_3
[] = {
14847 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
14848 { WM_GETMINMAXINFO
, sent
},
14849 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14850 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14851 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
14852 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14853 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
14854 { WM_WINDOWPOSCHANGED
, sent
|optional
}, /* Win8+ sometimes sends this. */
14855 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
14856 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
14857 { WM_WINDOWPOSCHANGED
, sent
|optional
},
14858 { WM_MOVE
, sent
|defwinproc
},
14859 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
14860 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
14861 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14862 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14863 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14866 static const struct message WmRestore_4
[] = {
14867 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
14868 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14869 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14870 { WM_MOVE
, sent
|defwinproc
|optional
},
14871 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
14872 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14873 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14876 static const struct message WmRestore_5
[] = {
14877 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
14878 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14879 { HCBT_ACTIVATE
, hook
|optional
},
14880 { HCBT_SETFOCUS
, hook
|optional
},
14881 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14882 { WM_MOVE
, sent
|defwinproc
|optional
},
14883 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
14884 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
14885 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14888 static const struct message WmHide_1
[] = {
14889 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
14890 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
14891 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14892 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
14893 { HCBT_ACTIVATE
, hook
|optional
},
14894 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
14895 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
14898 static const struct message WmHide_2
[] = {
14899 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
14900 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
14901 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14902 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
14903 { HCBT_ACTIVATE
, hook
|optional
},
14906 static const struct message WmHide_3
[] = {
14907 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
14908 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
14909 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14910 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14911 { HCBT_SETFOCUS
, hook
|optional
},
14912 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
14915 static const struct message WmShowMinimized_1
[] = {
14916 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
14917 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14918 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14919 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14920 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
14921 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
14922 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14923 { WM_MOVE
, sent
|defwinproc
},
14924 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
14925 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14926 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14927 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14930 static const struct message WmMinimize_1
[] = {
14931 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
14932 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
14933 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
14934 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14935 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14936 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14937 { WM_MOVE
, sent
|defwinproc
},
14938 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
14939 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14940 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14941 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14944 static const struct message WmMinimize_2
[] = {
14945 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
14946 { HCBT_SETFOCUS
, hook
|optional
},
14947 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
14948 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14949 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
14950 { WM_MOVE
, sent
|defwinproc
},
14951 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
14952 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14953 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14954 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14957 static const struct message WmMinimize_3
[] = {
14958 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
14959 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
14960 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14961 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14962 { HCBT_ACTIVATE
, hook
|optional
},
14963 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sometimes sent on Win8/10. */
14964 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14965 { WM_WINDOWPOSCHANGED
, sent
|optional
},
14966 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sometimes sent on Win7. */
14967 { WM_WINDOWPOSCHANGED
, sent
|optional
},
14968 { WM_MOVE
, sent
|defwinproc
},
14969 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
14970 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14971 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14972 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14975 static const struct message WmShowMinNoActivate
[] = {
14976 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
14977 { WM_WINDOWPOSCHANGING
, sent
},
14978 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14979 { WM_WINDOWPOSCHANGED
, sent
},
14980 { WM_MOVE
, sent
|defwinproc
|optional
},
14981 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
14984 static const struct message WmMinMax_1
[] = {
14985 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
14988 static const struct message WmMinMax_2
[] = {
14989 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
14990 { WM_GETMINMAXINFO
, sent
|optional
},
14991 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
14992 { HCBT_ACTIVATE
, hook
|optional
},
14993 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14994 { HCBT_SETFOCUS
, hook
|optional
},
14995 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14996 { WM_MOVE
, sent
|defwinproc
|optional
},
14997 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
14998 { HCBT_SETFOCUS
, hook
|optional
},
15001 static const struct message WmMinMax_3
[] = {
15002 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
15003 { HCBT_SETFOCUS
, hook
|optional
},
15004 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15005 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15006 { WM_MOVE
, sent
|defwinproc
|optional
},
15007 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
15010 static const struct message WmMinMax_4
[] = {
15011 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
15014 static const struct message WmShowMaximized_1
[] = {
15015 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
15016 { WM_GETMINMAXINFO
, sent
},
15017 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15018 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15019 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15020 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15021 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15022 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15023 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15024 { WM_MOVE
, sent
|defwinproc
},
15025 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
15026 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15027 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15028 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15029 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
15030 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15033 static const struct message WmShowMaximized_2
[] = {
15034 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
15035 { WM_GETMINMAXINFO
, sent
},
15036 { WM_WINDOWPOSCHANGING
, sent
|optional
},
15037 { HCBT_ACTIVATE
, hook
|optional
},
15038 { WM_WINDOWPOSCHANGED
, sent
|optional
},
15039 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15040 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
15041 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
15042 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
15043 { WM_WINDOWPOSCHANGING
, sent
|optional
},
15044 { HCBT_SETFOCUS
, hook
|optional
},
15045 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15046 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15047 { WM_MOVE
, sent
|defwinproc
},
15048 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
15049 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15050 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15051 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15052 { HCBT_SETFOCUS
, hook
|optional
},
15053 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15056 static const struct message WmShowMaximized_3
[] = {
15057 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
15058 { WM_GETMINMAXINFO
, sent
|optional
},
15059 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15060 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15061 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15062 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15063 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15064 { WM_MOVE
, sent
|defwinproc
|optional
},
15065 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
15066 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15067 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15071 static void test_ShowWindow(void)
15073 /* ShowWindow commands in random order */
15074 static const struct
15076 INT cmd
; /* ShowWindow command */
15077 LPARAM ret
; /* ShowWindow return value */
15078 DWORD style
; /* window style after the command */
15079 const struct message
*msg
; /* message sequence the command produces */
15080 INT wp_cmd
, wp_flags
; /* window placement after the command */
15081 POINT wp_min
, wp_max
; /* window placement after the command */
15082 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
15085 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
15086 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15087 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15088 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15089 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
15090 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15091 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15092 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15093 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
15094 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15095 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
15096 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15097 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
15098 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15099 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
15100 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15101 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
15102 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15103 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
15104 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15105 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
15106 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15107 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
15108 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15109 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
15110 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15111 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15112 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15113 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
15114 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15115 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15116 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15117 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
15118 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15119 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15120 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15121 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
15122 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15123 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
15124 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15125 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15126 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15127 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
15128 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
15129 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
15130 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15131 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15132 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15133 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
15134 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15135 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
15136 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15137 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
15138 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15139 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15140 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15141 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
15142 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15143 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
15144 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15145 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15146 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15147 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
15148 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15149 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15150 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15151 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
15152 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15153 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
15154 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15155 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15156 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15157 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
15158 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15159 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15160 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15161 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15162 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15163 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
15164 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15165 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
15166 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15167 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
15168 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15169 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
15170 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15171 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
15172 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15173 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
15174 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15175 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
15176 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15177 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
15178 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15179 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
15180 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15181 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
15182 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15183 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
15184 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15185 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
15186 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15187 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
15188 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15189 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15190 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15191 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
15192 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15193 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15194 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15195 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
15196 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15197 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15198 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
15204 WINDOWPLACEMENT wp
;
15205 RECT win_rc
, work_rc
= {0, 0, 0, 0};
15210 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
15211 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
15214 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
15216 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
15217 ok(style
== 0, "expected style 0, got %08lx\n", style
);
15222 SetLastError(0xdeadbeef);
15223 hmon
= MonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
15224 ok(hmon
!= 0, "MonitorFromPoint error %lu\n", GetLastError());
15226 mi
.cbSize
= sizeof(mi
);
15227 SetLastError(0xdeadbeef);
15228 ret
= GetMonitorInfoA(hmon
, &mi
);
15229 ok(ret
, "GetMonitorInfo error %lu\n", GetLastError());
15230 if (winetest_debug
> 1) trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi
.rcMonitor
),
15231 wine_dbgstr_rect(&mi
.rcWork
));
15232 work_rc
= mi
.rcWork
;
15234 GetWindowRect(hwnd
, &win_rc
);
15235 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
15237 wp
.length
= sizeof(wp
);
15238 SetLastError(0xdeadbeaf);
15239 ret
= GetWindowPlacement(hwnd
, &wp
);
15240 ok(ret
, "GetWindowPlacement error %lu\n", GetLastError());
15241 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
15242 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
15243 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
15244 "expected -1,-1 got %ld,%ld\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
15245 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
15246 "expected -1,-1 got %ld,%ld\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
15247 todo_wine_if (work_rc
.left
|| work_rc
.top
) /* FIXME: remove once Wine is fixed */
15248 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n", wine_dbgstr_rect(&win_rc
),
15249 wine_dbgstr_rect(&wp
.rcNormalPosition
));
15251 for (i
= 0; i
< ARRAY_SIZE(sw
); i
++)
15253 static const char * const sw_cmd_name
[13] =
15255 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
15256 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
15257 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
15258 "SW_NORMALNA" /* 0xCC */
15261 INT idx
; /* index into the above array of names */
15263 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
15265 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
15266 if (winetest_debug
> 1) trace("%d: sending %s, current window style %08lx\n", i
+1, sw_cmd_name
[idx
], style
);
15267 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
15268 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %Iu, got %Iu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
15269 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
15270 ok(style
== sw
[i
].style
, "%d: expected style %08lx, got %08lx\n", i
+1, sw
[i
].style
, style
);
15272 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
15273 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
15275 wp
.length
= sizeof(wp
);
15276 SetLastError(0xdeadbeaf);
15277 ret
= GetWindowPlacement(hwnd
, &wp
);
15278 ok(ret
, "GetWindowPlacement error %lu\n", GetLastError());
15279 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
15280 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
15282 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
15283 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
15284 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
15286 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
15287 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
15288 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
15292 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
15293 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
15296 todo_wine_if(wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
15297 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
15298 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
15300 if (0) /* FIXME: Wine behaves completely different here */
15301 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n",
15302 wine_dbgstr_rect(&win_rc
), wine_dbgstr_rect(&wp
.rcNormalPosition
));
15304 DestroyWindow(hwnd
);
15308 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15310 struct recvd_message msg
;
15312 if (ignore_message( message
)) return 0;
15315 msg
.message
= message
;
15316 msg
.flags
= sent
|wparam
|lparam
;
15317 msg
.wParam
= wParam
;
15318 msg
.lParam
= lParam
;
15319 msg
.descr
= "dialog";
15322 /* calling DefDlgProc leads to a recursion under XP */
15326 case WM_INITDIALOG
:
15329 case WM_GETDLGCODE
:
15335 static WNDPROC orig_edit_proc
;
15336 static LRESULT WINAPI
dlg_creation_edit_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
15338 struct recvd_message msg
;
15340 if (ignore_message( message
)) return 0;
15343 msg
.message
= message
;
15344 msg
.flags
= sent
|wparam
|lparam
;
15347 msg
.descr
= "edit";
15350 return CallWindowProcW(orig_edit_proc
, hwnd
, message
, wp
, lp
);
15353 static INT_PTR WINAPI
test_dlg_proc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15355 struct recvd_message msg
;
15357 if (ignore_message( message
)) return 0;
15360 msg
.message
= message
;
15361 msg
.flags
= sent
|wparam
|lparam
|parent
;
15362 msg
.wParam
= wParam
;
15363 msg
.lParam
= lParam
;
15364 msg
.descr
= "dialog";
15367 if (message
== WM_INITDIALOG
)
15369 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
15370 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
15376 static INT_PTR WINAPI
test_dlg_proc3(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15378 ok( 0, "should not be called since DefDlgProc is not used\n" );
15382 static LRESULT WINAPI
test_dlg_proc4(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15384 struct recvd_message msg
;
15386 if (!ignore_message( message
))
15389 msg
.message
= message
;
15390 msg
.flags
= sent
|wparam
|lparam
|parent
;
15391 msg
.wParam
= wParam
;
15392 msg
.lParam
= lParam
;
15393 msg
.descr
= "dialog";
15396 if (message
== WM_INITDIALOG
)
15398 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
15399 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
15402 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
15405 static const struct message WmDefDlgSetFocus_1
[] = {
15406 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15407 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
15408 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
15409 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
15410 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
15411 { HCBT_SETFOCUS
, hook
},
15412 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
15413 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
15414 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15415 { WM_SETFOCUS
, sent
|wparam
, 0 },
15416 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
15417 { WM_CTLCOLOREDIT
, sent
},
15418 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
15419 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
15420 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
15421 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
15422 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
15425 static const struct message WmDefDlgSetFocus_2
[] = {
15426 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15427 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
15428 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
15429 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
15430 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
15431 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
15432 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
15433 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
15436 /* Creation of a dialog */
15437 static const struct message WmCreateDialogParamSeq_0
[] = {
15438 { HCBT_CREATEWND
, hook
},
15439 { WM_NCCREATE
, sent
},
15440 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
15441 { WM_CREATE
, sent
},
15442 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15443 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
15445 { WM_SETFONT
, sent
},
15446 { WM_INITDIALOG
, sent
},
15447 { WM_CHANGEUISTATE
, sent
|optional
},
15450 /* Creation of a dialog */
15451 static const struct message WmCreateDialogParamSeq_1
[] = {
15452 { HCBT_CREATEWND
, hook
},
15453 { WM_NCCREATE
, sent
},
15454 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
15455 { WM_CREATE
, sent
},
15456 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15457 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
15459 { WM_SETFONT
, sent
},
15460 { WM_INITDIALOG
, sent
},
15461 { WM_GETDLGCODE
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
15462 { HCBT_SETFOCUS
, hook
},
15463 { HCBT_ACTIVATE
, hook
},
15464 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15465 { WM_QUERYNEWPALETTE
, sent
|optional
},
15466 { WM_PALETTEISCHANGING
, sent
|optional
},
15467 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15468 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOREDRAW
},
15469 { WM_GETTEXT
, sent
|optional
}, /* win7 */
15470 { WM_NCCALCSIZE
, sent
|optional
}, /* win7 */
15471 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win7 */
15472 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
15473 { WM_NCACTIVATE
, sent
},
15474 { WM_ACTIVATE
, sent
|wparam
, 1 },
15475 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15476 { WM_SETFOCUS
, sent
},
15477 { WM_CHANGEUISTATE
, sent
|optional
},
15480 /* Creation of a dialog */
15481 static const struct message WmCreateDialogParamSeq_2
[] = {
15482 { HCBT_CREATEWND
, hook
},
15483 { WM_NCCREATE
, sent
},
15484 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
15485 { WM_CREATE
, sent
},
15486 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15487 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
15489 { WM_CHANGEUISTATE
, sent
|optional
},
15493 static const struct message WmCreateDialogParamSeq_3
[] = {
15494 { HCBT_CREATEWND
, hook
},
15495 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15496 { WM_SETFONT
, sent
|parent
},
15497 { WM_INITDIALOG
, sent
|parent
},
15498 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15499 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
15500 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15501 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15502 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15503 { HCBT_ACTIVATE
, hook
},
15504 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15505 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
15506 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15507 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15508 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15509 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15510 { WM_NCCALCSIZE
, sent
|parent
|optional
, 0 },
15511 { WM_MOVE
, sent
|parent
|optional
},
15512 { WM_SIZE
, sent
|parent
|optional
},
15513 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15514 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
15515 { WM_NCACTIVATE
, sent
|parent
},
15516 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
15517 { WM_SETFOCUS
, sent
},
15518 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
15519 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15520 { WM_USER
, sent
|parent
},
15521 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
15525 static const struct message WmCreateDialogParamSeq_4
[] = {
15526 { HCBT_CREATEWND
, hook
},
15527 { WM_NCCREATE
, sent
|parent
},
15528 { WM_NCCALCSIZE
, sent
|parent
|wparam
, 0 },
15529 { WM_CREATE
, sent
|parent
},
15530 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15531 { WM_SIZE
, sent
|parent
|wparam
, SIZE_RESTORED
},
15532 { WM_MOVE
, sent
|parent
},
15533 { WM_SETFONT
, sent
|parent
},
15534 { WM_INITDIALOG
, sent
|parent
},
15535 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15536 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
15537 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15538 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15539 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15540 { HCBT_ACTIVATE
, hook
},
15541 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15542 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
15543 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15544 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15545 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15546 { WM_NCCALCSIZE
, sent
|parent
|optional
, 0 },
15547 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15548 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
15549 { WM_NCACTIVATE
, sent
|parent
},
15550 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
15551 { HCBT_SETFOCUS
, hook
},
15552 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15553 { WM_SETFOCUS
, sent
|parent
},
15554 { WM_KILLFOCUS
, sent
|parent
},
15555 { WM_SETFOCUS
, sent
},
15556 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
15557 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15558 { WM_USER
, sent
|parent
},
15559 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
15560 { WM_UPDATEUISTATE
, sent
|parent
|optional
},
15561 { WM_UPDATEUISTATE
, sent
|optional
},
15565 static void test_dialog_messages(void)
15568 HWND hdlg
, hedit1
, hedit2
, hfocus
, parent
, child
, child2
;
15571 #define set_selection(hctl, start, end) \
15572 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
15573 ok(ret == 1, "EM_SETSEL returned %Id\n", ret);
15575 #define check_selection(hctl, start, end) \
15576 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
15577 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
15581 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
15582 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
15583 0, 0, 100, 100, 0, 0, 0, NULL
);
15584 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
15586 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
15587 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
15588 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
15589 ok(hedit1
!= 0, "Failed to create edit control\n");
15590 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
15591 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
15592 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
15593 ok(hedit2
!= 0, "Failed to create edit control\n");
15595 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
15596 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
15598 hfocus
= GetFocus();
15599 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
15602 hfocus
= GetFocus();
15603 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
15605 check_selection(hedit1
, 0, 0);
15606 check_selection(hedit2
, 0, 0);
15608 set_selection(hedit2
, 0, -1);
15609 check_selection(hedit2
, 0, 3);
15612 hfocus
= GetFocus();
15613 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
15616 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
15617 ok(ret
== 0, "WM_SETFOCUS returned %Id\n", ret
);
15618 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
15620 hfocus
= GetFocus();
15621 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
15623 check_selection(hedit1
, 0, 5);
15624 check_selection(hedit2
, 0, 3);
15627 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
15628 ok(ret
== 0, "WM_SETFOCUS returned %Id\n", ret
);
15629 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
15631 hfocus
= GetFocus();
15632 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
15634 check_selection(hedit1
, 0, 5);
15635 check_selection(hedit2
, 0, 3);
15637 EndDialog(hdlg
, 0);
15638 DestroyWindow(hedit1
);
15639 DestroyWindow(hedit2
);
15640 DestroyWindow(hdlg
);
15643 #undef set_selection
15644 #undef check_selection
15646 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
15647 cls
.lpszClassName
= "MyDialogClass";
15648 cls
.hInstance
= GetModuleHandleA(NULL
);
15649 /* need a cast since a dlgproc is used as a wndproc */
15650 cls
.lpfnWndProc
= (WNDPROC
)test_dlg_proc
;
15651 register_class(&cls
);
15655 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
15656 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15657 ok_sequence(WmCreateDialogParamSeq_0
, "CreateDialogParam_0", FALSE
);
15658 hfocus
= GetFocus();
15659 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
15660 EndDialog(hdlg
, 0);
15661 DestroyWindow(hdlg
);
15666 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 1);
15667 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15668 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
15669 hfocus
= GetFocus();
15670 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
15671 EndDialog(hdlg
, 0);
15672 DestroyWindow(hdlg
);
15675 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
15676 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15677 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
15678 EndDialog(hdlg
, 0);
15679 DestroyWindow(hdlg
);
15682 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2
, 0);
15683 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15684 ok_sequence(WmCreateDialogParamSeq_3
, "CreateDialogParam_3", TRUE
);
15685 EndDialog(hdlg
, 0);
15686 DestroyWindow(hdlg
);
15689 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
15690 cls
.lpfnWndProc
= test_dlg_proc4
;
15691 register_class(&cls
);
15692 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3
, 0);
15693 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15694 ok_sequence(WmCreateDialogParamSeq_4
, "CreateDialogParam_4", TRUE
);
15695 EndDialog(hdlg
, 0);
15696 DestroyWindow(hdlg
);
15699 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
15701 parent
= CreateWindowExA(0, "TestParentClass", "Test parent",
15702 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15703 100, 100, 200, 200, 0, 0, 0, NULL
);
15704 ok (parent
!= 0, "Failed to create parent window\n");
15706 /* This child has no parent set. We will later call SetParent on it,
15707 * so that it will have a parent set, but no WS_CHILD style. */
15708 child
= CreateWindowExA(0, "TestWindowClass", "Test child",
15709 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15710 100, 100, 200, 200, 0, 0, 0, NULL
);
15711 ok (child
!= 0, "Failed to create child window\n");
15713 /* This is a regular child window. When used as an owner, the other
15714 * child window will be used. */
15715 child2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2",
15716 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CHILD
,
15717 100, 100, 200, 200, child
, 0, 0, NULL
);
15718 ok (child2
!= 0, "Failed to create child window\n");
15720 SetParent(child
, parent
);
15724 DialogBoxA( 0, "TEST_DIALOG", child2
, TestModalDlgProc2
);
15725 ok_sequence(WmModalDialogSeq_2
, "ModalDialog2", TRUE
);
15727 DestroyWindow(child2
);
15728 DestroyWindow(child
);
15729 DestroyWindow(parent
);
15733 static void test_enddialog_seq(HWND dialog
, HWND owner
)
15735 const struct message seq
[] = {
15736 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15737 { WM_ENABLE
, sent
},
15738 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15739 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
15740 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
15741 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
15742 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15743 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */
15744 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15745 { WM_QUERYNEWPALETTE
, sent
|optional
},
15746 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
15747 { WM_GETTEXT
, sent
|optional
|defwinproc
},
15748 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
15749 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
15750 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
15751 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15752 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, (WPARAM
)dialog
},
15757 EndDialog(dialog
, 0);
15758 ok_sequence(seq
, "EndDialog", FALSE
);
15761 static void test_enddialog_seq2(HWND dialog
, HWND owner
)
15763 const struct message seq
[] = {
15764 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15765 { WM_ENABLE
, parent
|sent
},
15766 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15767 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
15768 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
15769 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
15770 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15771 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15772 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15773 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
15774 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
15775 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15776 { WM_SETFOCUS
, sent
|parent
|defwinproc
|wparam
, (WPARAM
)dialog
},
15781 EndDialog(dialog
, 0);
15782 ok_sequence(seq
, "EndDialog2", FALSE
);
15785 static void test_EndDialog(void)
15787 HWND hparent
, hother
, hactive
, hdlg
, hchild
;
15790 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
15791 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
15792 100, 100, 200, 200, 0, 0, 0, NULL
);
15793 ok (hparent
!= 0, "Failed to create parent window\n");
15795 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
15796 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15797 200, 100, 200, 200, 0, 0, 0, NULL
);
15798 ok (hother
!= 0, "Failed to create parent window\n");
15800 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
15801 cls
.lpszClassName
= "MyDialogClass";
15802 cls
.hInstance
= GetModuleHandleA(NULL
);
15803 cls
.lpfnWndProc
= (WNDPROC
)test_dlg_proc
;
15804 register_class(&cls
);
15807 SetForegroundWindow(hother
);
15808 hactive
= GetForegroundWindow();
15809 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
15811 /* create a dialog where the parent is disabled, this parent should be
15812 * enabled and receive focus when dialog exits */
15813 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
15814 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15815 SetForegroundWindow(hdlg
);
15816 hactive
= GetForegroundWindow();
15817 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
15818 EndDialog(hdlg
, 0);
15819 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
15820 hactive
= GetForegroundWindow();
15821 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
15822 DestroyWindow(hdlg
);
15825 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */
15826 EnableWindow(hparent
, FALSE
);
15827 hdlg
= CreateWindowExA(0, "TestDialogClass", NULL
,
15828 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
15829 0, 0, 100, 100, hparent
, 0, 0, NULL
);
15830 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15832 SetForegroundWindow(hother
);
15834 hactive
= GetForegroundWindow();
15835 ok(hactive
== hother
, "Wrong foreground (%p != %p)\n", hactive
, hother
);
15836 hactive
= GetActiveWindow();
15837 ok(hactive
== hother
, "Wrong active window (%p != %p)\n", hactive
, hother
);
15838 EndDialog(hdlg
, 0);
15839 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
15840 hactive
= GetForegroundWindow();
15841 ok(hother
== hactive
, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
15842 DestroyWindow(hdlg
);
15845 DestroyWindow( hparent
);
15847 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
15848 WS_POPUP
| WS_VISIBLE
| WS_DISABLED
,
15849 100, 100, 200, 200, 0, 0, 0, NULL
);
15850 ok (hparent
!= 0, "Failed to create parent window\n");
15852 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
15853 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
15854 0, 0, 0, 0, 0, 0, 0, NULL
);
15855 ok (hchild
!= 0, "Failed to create child window\n");
15857 SetParent(hchild
, hparent
);
15860 SetForegroundWindow(hother
);
15861 hactive
= GetForegroundWindow();
15862 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
15864 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
15865 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15867 SetForegroundWindow(hdlg
);
15868 test_enddialog_seq(hdlg
, hchild
);
15870 hactive
= GetForegroundWindow();
15871 ok(hactive
== hchild
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
15873 DestroyWindow(hdlg
);
15875 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */
15876 SetWindowLongW(hchild
, GWL_STYLE
, GetWindowLongW(hchild
, GWL_STYLE
) | WS_CHILD
);
15878 SetForegroundWindow(hother
);
15879 hactive
= GetForegroundWindow();
15880 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
15882 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
15883 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15885 SetForegroundWindow(hdlg
);
15886 test_enddialog_seq2(hdlg
, hparent
);
15888 hactive
= GetForegroundWindow();
15889 ok(hactive
== hparent
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
15890 DestroyWindow(hdlg
);
15891 DestroyWindow(hchild
);
15892 DestroyWindow(hparent
);
15893 DestroyWindow(hother
);
15896 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
15899 static void test_nullCallback(void)
15903 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
15904 100, 100, 200, 200, 0, 0, 0, NULL
);
15905 ok (hwnd
!= 0, "Failed to create overlapped window\n");
15907 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
15909 DestroyWindow(hwnd
);
15912 /* SetActiveWindow( 0 ) hwnd visible */
15913 static const struct message SetActiveWindowSeq0
[] =
15915 { HCBT_ACTIVATE
, hook
|optional
},
15916 { WM_NCACTIVATE
, sent
|wparam
, 0 },
15917 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15918 { WM_ACTIVATE
, sent
|wparam
, 0 },
15919 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15920 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
15921 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
15922 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
15923 { WM_KILLFOCUS
, sent
|optional
},
15924 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
15925 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15926 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
15927 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15928 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
15929 { HCBT_SETFOCUS
, hook
|optional
},
15930 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
15931 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
15932 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
15933 { WM_IME_SETCONTEXT
, sent
|optional
},
15934 { WM_IME_SETCONTEXT
, sent
|optional
},
15935 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
15936 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
15937 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15938 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
15939 { WM_GETTEXT
, sent
|optional
},
15942 /* SetActiveWindow( hwnd ) hwnd visible */
15943 static const struct message SetActiveWindowSeq1
[] =
15945 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
15948 /* SetActiveWindow( popup ) hwnd visible, popup visible */
15949 static const struct message SetActiveWindowSeq2
[] =
15951 { HCBT_ACTIVATE
, hook
},
15952 { WM_NCACTIVATE
, sent
|wparam
, 0 },
15953 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15954 { WM_ACTIVATE
, sent
|wparam
, 0 },
15955 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15956 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
15957 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15958 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
15959 { WM_NCPAINT
, sent
|optional
},
15960 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15961 { WM_ERASEBKGND
, sent
|optional
},
15962 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15963 { WM_NCACTIVATE
, sent
|wparam
, 1 },
15964 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15965 { WM_ACTIVATE
, sent
|wparam
, 1 },
15966 { HCBT_SETFOCUS
, hook
},
15967 { WM_KILLFOCUS
, sent
|defwinproc
},
15968 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
15969 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
15970 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
15971 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
15972 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15973 { WM_SETFOCUS
, sent
|defwinproc
},
15974 { WM_GETTEXT
, sent
|optional
},
15978 /* SetActiveWindow( hwnd ) hwnd not visible */
15979 static const struct message SetActiveWindowSeq3
[] =
15981 { HCBT_ACTIVATE
, hook
},
15982 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15983 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
15984 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
15985 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
15986 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15987 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15988 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
15989 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
15990 { WM_NCACTIVATE
, sent
|wparam
, 1 },
15991 { WM_ACTIVATE
, sent
|wparam
, 1 },
15992 { HCBT_SETFOCUS
, hook
},
15993 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
15994 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
15995 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15996 { WM_SETFOCUS
, sent
|defwinproc
},
15999 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
16000 static const struct message SetActiveWindowSeq4
[] =
16002 { HCBT_ACTIVATE
, hook
},
16003 { WM_NCACTIVATE
, sent
|wparam
, 0 },
16004 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16005 { WM_ACTIVATE
, sent
|wparam
, 0 },
16006 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16007 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
16008 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
16009 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
16010 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16011 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16012 { WM_NCACTIVATE
, sent
|wparam
, 1 },
16013 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16014 { WM_ACTIVATE
, sent
|wparam
, 1 },
16015 { HCBT_SETFOCUS
, hook
},
16016 { WM_KILLFOCUS
, sent
|defwinproc
},
16017 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
16018 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
16019 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
16020 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
16021 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16022 { WM_SETFOCUS
, sent
|defwinproc
},
16027 static void test_SetActiveWindow(void)
16029 HWND hwnd
, popup
, ret
;
16031 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
16032 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16033 100, 100, 200, 200, 0, 0, 0, NULL
);
16035 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
16036 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
16037 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
16039 ok(hwnd
!= 0, "Failed to create overlapped window\n");
16040 ok(popup
!= 0, "Failed to create popup window\n");
16041 SetForegroundWindow( popup
);
16044 if (winetest_debug
> 1) trace("SetActiveWindow(0)\n");
16045 ret
= SetActiveWindow(0);
16046 ok( ret
== popup
|| broken(ret
== 0) /* w1064v1809 */, "Failed to SetActiveWindow(0), ret:%p\n", ret
);
16047 if (ret
== popup
) ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
16050 if (winetest_debug
> 1) trace("SetActiveWindow(hwnd), hwnd visible\n");
16051 ret
= SetActiveWindow(hwnd
);
16052 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
16055 if (winetest_debug
> 1) trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
16056 ret
= SetActiveWindow(popup
);
16057 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
16058 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
16061 ShowWindow(hwnd
, SW_HIDE
);
16062 ShowWindow(popup
, SW_HIDE
);
16065 if (winetest_debug
> 1) trace("SetActiveWindow(hwnd), hwnd not visible\n");
16066 ret
= SetActiveWindow(hwnd
);
16067 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
16068 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
16071 if (winetest_debug
> 1) trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
16072 ret
= SetActiveWindow(popup
);
16073 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
16074 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
16077 if (winetest_debug
> 1) trace("done\n");
16079 DestroyWindow(hwnd
);
16082 static const struct message SetForegroundWindowSeq
[] =
16084 { WM_NCACTIVATE
, sent
|wparam
, 0 },
16085 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16086 { WM_ACTIVATE
, sent
|wparam
, 0 },
16087 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
16088 { WM_KILLFOCUS
, sent
},
16089 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
16090 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
16094 static void test_SetForegroundWindow(void)
16098 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
16099 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16100 100, 100, 200, 200, 0, 0, 0, NULL
);
16101 ok (hwnd
!= 0, "Failed to create overlapped window\n");
16102 SetForegroundWindow( hwnd
);
16105 if (winetest_debug
> 1) trace("SetForegroundWindow( 0 )\n");
16106 SetForegroundWindow( 0 );
16107 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
16108 if (winetest_debug
> 1) trace("SetForegroundWindow( GetDesktopWindow() )\n");
16109 SetForegroundWindow( GetDesktopWindow() );
16110 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
16111 "foreground top level window", FALSE
);
16112 if (winetest_debug
> 1) trace("done\n");
16114 DestroyWindow(hwnd
);
16117 static DWORD
get_input_codepage( void )
16121 HKL hkl
= GetKeyboardLayout( 0 );
16123 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
,
16124 (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
16125 if (!ret
) cp
= CP_ACP
;
16129 static void test_dbcs_wm_char(void)
16132 WCHAR wch
, bad_wch
;
16140 struct message wmCharSeq
[2];
16142 DWORD cp
= get_input_codepage();
16144 if (!pGetCPInfoExA
)
16146 win_skip("GetCPInfoExA is not available\n");
16150 pGetCPInfoExA( cp
, 0, &cpinfo
);
16151 if (cpinfo
.MaxCharSize
!= 2)
16153 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
16157 dbch
[0] = dbch
[1] = 0;
16159 bad_wch
= cpinfo
.UnicodeDefaultChar
;
16160 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
16161 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
16162 for (k
= 128; k
<= 255; k
++)
16168 if (MultiByteToWideChar( cp
, 0, str
, 2, wstr
, 2 ) == 1 &&
16169 WideCharToMultiByte( cp
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
16170 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
16171 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
16182 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
16185 if (winetest_debug
> 1) trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
16186 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
16188 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
16189 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
16190 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
16191 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
16192 ok (hwnd
!= 0, "Failed to create overlapped window\n");
16193 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
16197 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
16198 wmCharSeq
[0].message
= WM_CHAR
;
16199 wmCharSeq
[0].flags
= sent
|wparam
;
16200 wmCharSeq
[0].wParam
= wch
;
16202 /* posted message */
16203 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16204 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16205 ok( !ret
, "got message %x\n", msg
.message
);
16206 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16207 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16208 ok( ret
, "no message\n" );
16209 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16210 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
16211 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16212 ok( !ret
, "got message %x\n", msg
.message
);
16214 /* posted thread message */
16215 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
16216 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16217 ok( !ret
, "got message %x\n", msg
.message
);
16218 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16219 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16220 ok( ret
, "no message\n" );
16221 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16222 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
16223 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16224 ok( !ret
, "got message %x\n", msg
.message
);
16228 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16229 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16230 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16231 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16232 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16233 ok( !ret
, "got message %x\n", msg
.message
);
16235 /* sent message with timeout */
16237 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
16238 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16239 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
16240 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16241 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16242 ok( !ret
, "got message %x\n", msg
.message
);
16244 /* sent message with timeout and callback */
16246 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
16247 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16248 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
16249 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16250 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16251 ok( !ret
, "got message %x\n", msg
.message
);
16253 /* sent message with callback */
16255 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16256 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16257 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
16258 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16259 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16260 ok( !ret
, "got message %x\n", msg
.message
);
16262 /* direct window proc call */
16264 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
16265 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16266 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
16267 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16269 /* dispatch message */
16271 msg
.message
= WM_CHAR
;
16272 msg
.wParam
= dbch
[0];
16274 DispatchMessageA( &msg
);
16275 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16276 msg
.wParam
= dbch
[1];
16277 DispatchMessageA( &msg
);
16278 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16280 /* window handle is irrelevant */
16282 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
16283 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16284 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16285 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16286 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16287 ok( !ret
, "got message %x\n", msg
.message
);
16289 /* interleaved post and send */
16291 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
16292 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
16293 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16294 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16295 ok( !ret
, "got message %x\n", msg
.message
);
16296 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16297 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16298 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16299 ok( ret
, "no message\n" );
16300 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16301 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
16302 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16303 ok( !ret
, "got message %x\n", msg
.message
);
16304 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16305 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16306 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16307 ok( !ret
, "got message %x\n", msg
.message
);
16309 /* interleaved sent message and winproc */
16311 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16312 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
16313 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16314 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16315 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16316 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
16317 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16319 /* interleaved winproc and dispatch */
16321 msg
.message
= WM_CHAR
;
16322 msg
.wParam
= dbch
[0];
16324 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
16325 DispatchMessageA( &msg
);
16326 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16327 msg
.wParam
= dbch
[1];
16328 DispatchMessageA( &msg
);
16329 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16330 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
16331 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16333 /* interleaved sends */
16335 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16336 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
16337 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16338 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
16339 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16340 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16341 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16345 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
16346 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16347 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16348 ok( !ret
, "got message %x\n", msg
.message
);
16350 /* other char messages are not magic */
16351 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
16352 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16353 ok( ret
, "no message\n" );
16354 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
16355 ok( msg
.wParam
== bad_wch
, "bad wparam %Ix/%x\n", msg
.wParam
, bad_wch
);
16356 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16357 ok( !ret
, "got message %x\n", msg
.message
);
16358 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
16359 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16360 ok( ret
, "no message\n" );
16361 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
16362 ok( msg
.wParam
== bad_wch
, "bad wparam %Ix/%x\n", msg
.wParam
, bad_wch
);
16363 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16364 ok( !ret
, "got message %x\n", msg
.message
);
16366 /* test retrieving messages */
16368 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
16369 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16370 ok( ret
, "no message\n" );
16371 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16372 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16373 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16374 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16375 ok( ret
, "no message\n" );
16376 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16377 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16378 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16379 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16380 ok( !ret
, "got message %x\n", msg
.message
);
16382 /* message filters */
16383 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
16384 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16385 ok( ret
, "no message\n" );
16386 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16387 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16388 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16389 /* message id is filtered, hwnd is not */
16390 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
16391 ok( !ret
, "no message\n" );
16392 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
16393 ok( ret
, "no message\n" );
16394 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16395 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16396 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16397 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16398 ok( !ret
, "got message %x\n", msg
.message
);
16400 /* mixing GetMessage and PostMessage */
16401 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
16402 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
16403 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16404 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16405 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16406 ok( msg
.lParam
== 0xbeef, "bad lparam %Ix\n", msg
.lParam
);
16409 ok( time
- GetTickCount() <= 100, "bad time %lx\n", msg
.time
);
16410 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
16411 ok( ret
, "no message\n" );
16412 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16413 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16414 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16415 ok( msg
.lParam
== 0xbeef, "bad lparam %Ix\n", msg
.lParam
);
16416 ok( msg
.time
== time
, "bad time %lx/%lx\n", msg
.time
, time
);
16417 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
);
16418 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16419 ok( !ret
, "got message %x\n", msg
.message
);
16421 /* without PM_REMOVE */
16422 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
16423 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
16424 ok( ret
, "no message\n" );
16425 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16426 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16427 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16428 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
16429 ok( ret
, "no message\n" );
16430 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16431 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16432 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16433 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
16434 ok( ret
, "no message\n" );
16435 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16436 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16437 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16438 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
16439 ok( ret
, "no message\n" );
16440 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16441 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16442 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16443 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16444 ok( !ret
, "got message %x\n", msg
.message
);
16446 DestroyWindow(hwnd
);
16447 DestroyWindow(hwnd2
);
16450 static void test_unicode_wm_char(void)
16454 struct message seq
[2];
16455 HKL hkl_orig
, hkl_greek
;
16457 LCID thread_locale
;
16459 hkl_orig
= GetKeyboardLayout( 0 );
16460 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
16463 skip( "Default codepage %ld\n", cp
);
16467 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
16468 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
16470 skip( "Unable to load Greek keyboard layout\n" );
16474 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
16475 100, 100, 200, 200, 0, 0, 0, NULL
);
16478 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
16480 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
16482 if (!ignore_message( msg
.message
)) break;
16485 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16486 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16487 ok( msg
.wParam
== 0x3b1, "bad wparam %Ix\n", msg
.wParam
);
16488 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
16490 DispatchMessageW( &msg
);
16492 memset( seq
, 0, sizeof(seq
) );
16493 seq
[0].message
= WM_CHAR
;
16494 seq
[0].flags
= sent
|wparam
;
16495 seq
[0].wParam
= 0x3b1;
16497 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
16501 /* greek alpha -> 'a' in cp1252 */
16502 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
16504 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
16505 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16506 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16507 ok( msg
.wParam
== 0x61, "bad wparam %Ix\n", msg
.wParam
);
16508 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
16510 DispatchMessageA( &msg
);
16512 seq
[0].wParam
= 0x61;
16513 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
16515 thread_locale
= GetThreadLocale();
16516 ActivateKeyboardLayout( hkl_greek
, 0 );
16517 ok( GetThreadLocale() == thread_locale
, "locale changed from %08lx to %08lx\n",
16518 thread_locale
, GetThreadLocale() );
16522 /* greek alpha -> 0xe1 in cp1253 */
16523 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
16525 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
16526 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16527 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16528 ok( msg
.wParam
== 0xe1, "bad wparam %Ix\n", msg
.wParam
);
16529 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
16531 DispatchMessageA( &msg
);
16533 seq
[0].wParam
= 0x3b1;
16534 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
16536 DestroyWindow( hwnd
);
16537 ActivateKeyboardLayout( hkl_orig
, 0 );
16538 UnloadKeyboardLayout( hkl_greek
);
16541 #define ID_LISTBOX 0x000f
16543 static const struct message wm_lb_setcursel_0
[] =
16545 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
16546 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16547 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
16548 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16549 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16552 static const struct message wm_lb_setcursel_1
[] =
16554 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
16555 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16556 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
16557 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16558 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
16559 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
16560 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
16563 static const struct message wm_lb_setcursel_2
[] =
16565 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
16566 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16567 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
16568 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16569 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
16570 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
16571 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
16574 static const struct message wm_lb_click_0
[] =
16576 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
16577 { HCBT_SETFOCUS
, hook
},
16578 { WM_KILLFOCUS
, sent
|parent
},
16579 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
16580 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
16581 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16582 { WM_SETFOCUS
, sent
|defwinproc
},
16584 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
16585 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
16586 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
16587 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
16588 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16590 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
16591 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16592 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
16593 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16594 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
16595 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
16597 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16598 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16600 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
16601 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16602 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
16603 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
16606 static const struct message wm_lb_deletestring
[] =
16608 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
16609 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16610 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
16611 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16612 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16615 static const struct message wm_lb_deletestring_reset
[] =
16617 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
16618 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16619 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
16620 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
16621 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16622 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16625 static const struct message wm_lb_addstring
[] =
16627 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
16628 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16629 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
16630 /* Child ID changes each test, don't test lparam. */
16631 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
16632 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
16633 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
16636 static const struct message wm_lb_addstring_ownerdraw
[] =
16638 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
16639 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
16640 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16641 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
16642 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
16643 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
16644 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
16645 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
16646 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
16649 static const struct message wm_lb_addstring_sort_ownerdraw
[] =
16651 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
16652 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
16653 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16654 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
16655 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ee },
16656 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
16657 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
16658 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
16659 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ef },
16660 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ee, 0xf30604ef },
16661 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
16662 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
16665 static const struct message wm_lb_dblclick_0
[] =
16667 { WM_LBUTTONDBLCLK
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
16668 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
16672 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
16674 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
16676 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
16678 static LONG defwndproc_counter
= 0;
16680 struct recvd_message msg
;
16682 /* do not log painting messages */
16683 if (message
!= WM_PAINT
&&
16684 message
!= WM_NCPAINT
&&
16685 message
!= WM_SYNCPAINT
&&
16686 message
!= WM_ERASEBKGND
&&
16687 message
!= WM_NCHITTEST
&&
16688 message
!= WM_GETTEXT
&&
16689 !ignore_message( message
))
16692 msg
.message
= message
;
16693 msg
.flags
= sent
|wparam
|lparam
;
16694 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
16696 if (message
== LB_ADDSTRING
)
16697 msg
.lParam
= lp
? hash_Ly((const char *)lp
) : 0;
16700 msg
.descr
= "listbox";
16704 defwndproc_counter
++;
16705 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
16706 defwndproc_counter
--;
16711 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
16712 int caret_index
, int top_index
, int line
)
16716 /* calling an orig proc helps to avoid unnecessary message logging */
16717 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
16718 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %Id\n", count
, ret
);
16719 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
16720 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %Id\n", cur_sel
, ret
);
16721 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
16722 ok_(__FILE__
, line
)(ret
== caret_index
||
16723 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
16724 "expected caret index %d, got %Id\n", caret_index
, ret
);
16725 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
16726 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %Id\n", top_index
, ret
);
16729 static void test_listbox_messages(void)
16731 HWND parent
, listbox
;
16734 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16735 100, 100, 200, 200, 0, 0, 0, NULL
);
16736 /* with LBS_HASSTRINGS */
16737 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
16738 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
16739 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
16740 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
16742 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16746 log_all_parent_messages
++;
16748 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
16749 ok(ret
== 0, "expected 0, got %Id\n", ret
);
16750 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
16751 ok(ret
== 1, "expected 1, got %Id\n", ret
);
16752 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
16753 ok(ret
== 2, "expected 2, got %Id\n", ret
);
16755 ok_sequence(wm_lb_addstring_ownerdraw
, "LB_ADDSTRING", FALSE
);
16756 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
16760 if (winetest_debug
> 1) trace("selecting item 0\n");
16761 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
16762 ok(ret
== 0, "expected 0, got %Id\n", ret
);
16763 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
16764 check_lb_state(listbox
, 3, 0, 0, 0);
16767 if (winetest_debug
> 1) trace("selecting item 1\n");
16768 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
16769 ok(ret
== 1, "expected 1, got %Id\n", ret
);
16770 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
16771 check_lb_state(listbox
, 3, 1, 1, 0);
16773 if (winetest_debug
> 1) trace("selecting item 2\n");
16774 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
16775 ok(ret
== 2, "expected 2, got %Id\n", ret
);
16776 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
16777 check_lb_state(listbox
, 3, 2, 2, 0);
16779 if (winetest_debug
> 1) trace("clicking on item 0\n");
16780 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
16781 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16782 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
16783 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16784 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
16785 check_lb_state(listbox
, 3, 0, 0, 0);
16788 if (winetest_debug
> 1) trace("deleting item 0\n");
16789 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
16790 ok(ret
== 2, "expected 2, got %Id\n", ret
);
16791 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
16792 check_lb_state(listbox
, 2, -1, 0, 0);
16795 if (winetest_debug
> 1) trace("deleting item 0\n");
16796 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
16797 ok(ret
== 1, "expected 1, got %Id\n", ret
);
16798 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
16799 check_lb_state(listbox
, 1, -1, 0, 0);
16802 if (winetest_debug
> 1) trace("deleting item 0\n");
16803 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
16804 ok(ret
== 0, "expected 0, got %Id\n", ret
);
16805 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
16806 check_lb_state(listbox
, 0, -1, 0, 0);
16809 if (winetest_debug
> 1) trace("deleting item 0\n");
16810 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
16811 ok(ret
== LB_ERR
, "expected LB_ERR, got %Id\n", ret
);
16812 check_lb_state(listbox
, 0, -1, 0, 0);
16815 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
16816 ok(ret
== LB_ERR
, "expected LB_ERR, got %Id\n", ret
);
16817 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16820 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
16821 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16822 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16825 if (winetest_debug
> 1) trace("clicking on item 0\n");
16826 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
16827 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16828 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
16829 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16830 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
16831 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16834 log_all_parent_messages
--;
16836 DestroyWindow(listbox
);
16838 /* with LBS_SORT and without LBS_HASSTRINGS */
16839 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
16840 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_SORT
| WS_VISIBLE
,
16841 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
16842 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
16844 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16848 log_all_parent_messages
++;
16850 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
16851 ok(ret
== 0, "expected 0, got %Id\n", ret
);
16852 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
16853 ok(ret
== 1, "expected 1, got %Id\n", ret
);
16854 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
16855 ok(ret
== 2, "expected 2, got %Id\n", ret
);
16857 ok_sequence(wm_lb_addstring_sort_ownerdraw
, "LB_ADDSTRING", FALSE
);
16858 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
16860 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
16861 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16862 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16863 SetFocus(listbox
); /* avoid focus messages */
16866 if (winetest_debug
> 1) trace("clicking on item 0\n");
16867 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
16868 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16869 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
16870 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16871 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
16872 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16875 log_all_parent_messages
--;
16877 DestroyWindow(listbox
);
16879 /* with LBS_HASSTRINGS */
16880 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
16881 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| WS_VISIBLE
,
16882 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
16883 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
16885 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16889 log_all_parent_messages
++;
16891 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
16892 ok(ret
== 0, "expected 0, got %Id\n", ret
);
16893 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
16894 ok(ret
== 1, "expected 1, got %Id\n", ret
);
16895 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
16896 ok(ret
== 2, "expected 2, got %Id\n", ret
);
16898 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
16899 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
16901 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
16902 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16903 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16904 SetFocus(listbox
); /* avoid focus messages */
16907 if (winetest_debug
> 1) trace("clicking on item 0\n");
16908 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
16909 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16910 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
16911 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16912 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
16913 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16916 log_all_parent_messages
--;
16918 DestroyWindow(listbox
);
16920 /* with LBS_HASSTRINGS and LBS_SORT */
16921 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
16922 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| LBS_SORT
| WS_VISIBLE
,
16923 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
16924 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
16926 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16930 log_all_parent_messages
++;
16932 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
16933 ok(ret
== 0, "expected 0, got %Id\n", ret
);
16934 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
16935 ok(ret
== 0, "expected 0, got %Id\n", ret
);
16936 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
16937 ok(ret
== 1, "expected 1, got %Id\n", ret
);
16939 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
16940 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
16942 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
16943 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16944 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16945 SetFocus(listbox
); /* avoid focus messages */
16948 if (winetest_debug
> 1) trace("clicking on item 0\n");
16949 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
16950 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16951 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
16952 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
16953 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
16954 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
16957 log_all_parent_messages
--;
16959 DestroyWindow(listbox
);
16960 DestroyWindow(parent
);
16963 /*************************** Menu test ******************************/
16964 static const struct message wm_popup_menu_1
[] =
16966 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
16967 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
16968 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
16969 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
16970 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
16971 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
16972 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
16973 { WM_INITMENU
, sent
|lparam
, 0, 0 },
16974 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
16975 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
16976 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
16977 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
16978 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16979 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
16980 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16981 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
16982 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
16983 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16984 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
16985 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
16986 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
16987 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_MENU
, 0 },
16988 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
16989 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
16990 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
16991 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16992 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
16993 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
16994 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
16995 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
16996 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
16997 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
17000 static const struct message wm_popup_menu_2
[] =
17002 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17003 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17004 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
17005 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
17006 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
17007 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
17008 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17009 { WM_INITMENU
, sent
|lparam
, 0, 0 },
17010 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
17011 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
17012 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
17013 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
17014 { HCBT_CREATEWND
, hook
},
17015 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17016 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17017 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17018 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17019 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17020 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
17021 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
17022 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
17023 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
17024 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
17025 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
17026 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
17027 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
17028 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17029 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17030 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17031 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17032 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17033 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
17034 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
17035 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
17036 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
17037 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_MENU
, 0 },
17038 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17039 { HCBT_DESTROYWND
, hook
},
17040 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17041 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17042 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17043 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17044 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
17045 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17046 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17047 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17048 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
17049 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17050 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
17051 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
17052 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
17055 static const struct message wm_popup_menu_3
[] =
17057 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17058 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17059 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
17060 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
17061 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
17062 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
17063 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17064 { WM_INITMENU
, sent
|lparam
, 0, 0 },
17065 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
17066 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
17067 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
17068 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
17069 { HCBT_CREATEWND
, hook
},
17070 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17071 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17072 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17073 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17074 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17075 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
17076 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
17077 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
17078 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
17079 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
17080 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
17081 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
17082 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
17083 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17084 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17085 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17086 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17087 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17088 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
17089 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
17090 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
17091 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
17092 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_MENU
, 100 },
17093 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17094 { HCBT_DESTROYWND
, hook
},
17095 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17096 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17097 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17098 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
17099 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
17100 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17101 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17102 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17103 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
17104 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17105 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
17106 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
17107 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
17111 static const struct message wm_single_menu_item
[] =
17113 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17114 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17115 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
17116 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
17117 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
17118 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
17119 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17120 { WM_INITMENU
, sent
|lparam
, 0, 0 },
17121 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
17122 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
17123 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17124 { WM_MENUCOMMAND
, sent
},
17125 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
17126 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
17127 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
17128 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
17130 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
17131 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
17132 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
17133 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
17134 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
17138 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
17140 if (message
== WM_ENTERIDLE
||
17141 message
== WM_INITMENU
||
17142 message
== WM_INITMENUPOPUP
||
17143 message
== WM_MENUSELECT
||
17144 message
== WM_PARENTNOTIFY
||
17145 message
== WM_ENTERMENULOOP
||
17146 message
== WM_EXITMENULOOP
||
17147 message
== WM_UNINITMENUPOPUP
||
17148 message
== WM_KEYDOWN
||
17149 message
== WM_KEYUP
||
17150 message
== WM_CHAR
||
17151 message
== WM_SYSKEYDOWN
||
17152 message
== WM_SYSKEYUP
||
17153 message
== WM_SYSCHAR
||
17154 message
== WM_COMMAND
||
17155 message
== WM_MENUCOMMAND
)
17157 struct recvd_message msg
;
17160 msg
.message
= message
;
17161 msg
.flags
= sent
|wparam
|lparam
;
17164 msg
.descr
= "parent_menu_proc";
17168 return DefWindowProcA(hwnd
, message
, wp
, lp
);
17171 static void set_menu_style(HMENU hmenu
, DWORD style
)
17176 mi
.cbSize
= sizeof(mi
);
17177 mi
.fMask
= MIM_STYLE
;
17178 mi
.dwStyle
= style
;
17179 SetLastError(0xdeadbeef);
17180 ret
= SetMenuInfo(hmenu
, &mi
);
17181 ok(ret
, "SetMenuInfo error %lu\n", GetLastError());
17184 static DWORD
get_menu_style(HMENU hmenu
)
17189 mi
.cbSize
= sizeof(mi
);
17190 mi
.fMask
= MIM_STYLE
;
17192 SetLastError(0xdeadbeef);
17193 ret
= GetMenuInfo(hmenu
, &mi
);
17194 ok(ret
, "GetMenuInfo error %lu\n", GetLastError());
17199 static void test_menu_messages(void)
17203 HMENU hmenu
, hmenu_popup
;
17206 BOOL us_kbd
= (GetKeyboardLayout(0) == (HKL
)(ULONG_PTR
)0x04090409);
17209 cls
.lpfnWndProc
= parent_menu_proc
;
17210 cls
.cbClsExtra
= 0;
17211 cls
.cbWndExtra
= 0;
17212 cls
.hInstance
= GetModuleHandleA(0);
17214 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
17215 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
17216 cls
.lpszMenuName
= NULL
;
17217 cls
.lpszClassName
= "TestMenuClass";
17218 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
17219 register_class(&cls
);
17221 SetLastError(0xdeadbeef);
17222 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
17223 100, 100, 200, 200, 0, 0, 0, NULL
);
17224 ok(hwnd
!= 0, "LoadMenuA error %lu\n", GetLastError());
17226 SetLastError(0xdeadbeef);
17227 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
17228 ok(hmenu
!= 0, "LoadMenuA error %lu\n", GetLastError());
17230 SetMenu(hwnd
, hmenu
);
17231 SetForegroundWindow( hwnd
);
17234 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
17235 style
= get_menu_style(hmenu
);
17236 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %lu\n", style
);
17238 hmenu_popup
= GetSubMenu(hmenu
, 0);
17239 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17240 style
= get_menu_style(hmenu_popup
);
17241 ok(style
== 0, "expected 0, got %lu\n", style
);
17243 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
17244 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17245 style
= get_menu_style(hmenu_popup
);
17246 ok(style
== 0, "expected 0, got %lu\n", style
);
17250 skip("skipping ascii VK events on non-us keyboard\n");
17255 if (winetest_debug
> 1) trace("testing a popup menu command\n");
17257 keybd_event(VK_MENU
, 0, 0, 0);
17258 keybd_event('E', 0, 0, 0);
17259 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
17260 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17261 keybd_event(VK_RETURN
, 0, 0, 0);
17262 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
17263 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17265 TranslateMessage(&msg
);
17266 DispatchMessageA(&msg
);
17268 if (!sequence_cnt
) /* we didn't get any message */
17270 skip( "queuing key events not supported\n" );
17273 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
17274 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
17276 win_skip( "menu tracking through VK_MENU not supported\n" );
17279 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
17281 /* Alt+F, Right, Enter */
17282 if (winetest_debug
> 1) trace("testing submenu of a popup menu command\n");
17284 keybd_event(VK_MENU
, 0, 0, 0);
17285 keybd_event('F', 0, 0, 0);
17286 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
17287 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17288 keybd_event(VK_RIGHT
, 0, 0, 0);
17289 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
17290 keybd_event(VK_RETURN
, 0, 0, 0);
17291 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
17292 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17294 TranslateMessage(&msg
);
17295 DispatchMessageA(&msg
);
17297 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
17299 if (winetest_debug
> 1) trace("testing single menu item command\n");
17301 keybd_event(VK_MENU
, 0, 0, 0);
17302 keybd_event('Q', 0, 0, 0);
17303 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
17304 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17305 keybd_event(VK_ESCAPE
, 0, 0, 0);
17306 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
17307 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17309 TranslateMessage(&msg
);
17310 DispatchMessageA(&msg
);
17312 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
17314 set_menu_style(hmenu
, 0);
17315 style
= get_menu_style(hmenu
);
17316 ok(style
== 0, "expected 0, got %lu\n", style
);
17318 hmenu_popup
= GetSubMenu(hmenu
, 0);
17319 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17320 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
17321 style
= get_menu_style(hmenu_popup
);
17322 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %lu\n", style
);
17324 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
17325 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17326 style
= get_menu_style(hmenu_popup
);
17327 ok(style
== 0, "expected 0, got %lu\n", style
);
17329 /* Alt+F, Right, Enter */
17330 if (winetest_debug
> 1) trace("testing submenu of a popup menu command\n");
17332 keybd_event(VK_MENU
, 0, 0, 0);
17333 keybd_event('F', 0, 0, 0);
17334 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
17335 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17336 keybd_event(VK_RIGHT
, 0, 0, 0);
17337 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
17338 keybd_event(VK_RETURN
, 0, 0, 0);
17339 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
17340 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17342 TranslateMessage(&msg
);
17343 DispatchMessageA(&msg
);
17345 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
17348 DestroyWindow(hwnd
);
17349 DestroyMenu(hmenu
);
17353 static void test_paintingloop(void)
17357 paint_loop_done
= FALSE
;
17358 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
17359 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
17360 100, 100, 100, 100, 0, 0, 0, NULL
);
17361 ok(hwnd
!= 0, "PaintLoop window error %lu\n", GetLastError());
17362 ShowWindow(hwnd
,SW_NORMAL
);
17365 while (!paint_loop_done
)
17368 if (PeekMessageA(&msg
, 0, 0, 0, 1))
17370 TranslateMessage(&msg
);
17371 DispatchMessageA(&msg
);
17374 DestroyWindow(hwnd
);
17377 static const struct message NCRBUTTONDOWNSeq
[] =
17379 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17380 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17381 { WM_CAPTURECHANGED
, sent
},
17382 { WM_CONTEXTMENU
, sent
, /*hwnd*/0, -1 },
17386 static const struct message NCXBUTTONUPSeq1
[] =
17388 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_BACKWARD
) },
17392 static const struct message NCXBUTTONUPSeq2
[] =
17394 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_FORWARD
) },
17398 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to minimized visible window */
17399 static const struct message WmRestoreMinimizedOverlappedSeq
[] =
17401 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_RESTORE
, 0 },
17402 { HCBT_MINMAX
, hook
},
17403 { WM_QUERYOPEN
, sent
},
17404 { WM_GETTEXT
, sent
|optional
},
17405 { WM_NCACTIVATE
, sent
|optional
},
17406 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
17407 { WM_WINDOWPOSCHANGED
, sent
|optional
},
17408 { WM_WINDOWPOSCHANGING
, sent
|optional
},
17409 { WM_GETMINMAXINFO
, sent
|defwinproc
},
17410 { WM_NCCALCSIZE
, sent
|optional
},
17411 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17412 { WM_NCPAINT
, sent
|optional
},
17413 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17414 { WM_ERASEBKGND
, sent
|optional
},
17415 { WM_WINDOWPOSCHANGED
, sent
|optional
},
17416 { HCBT_ACTIVATE
, hook
},
17417 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17418 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
17419 { WM_ACTIVATEAPP
, sent
|wparam
, TRUE
},
17420 { WM_NCACTIVATE
, sent
|wparam
, TRUE
},
17421 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17422 { WM_ACTIVATE
, sent
|wparam
, TRUE
},
17423 { HCBT_SETFOCUS
, hook
},
17424 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
17425 { WM_SETFOCUS
, sent
|defwinproc
},
17426 { WM_NCPAINT
, sent
},
17427 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17428 { WM_ERASEBKGND
, sent
},
17429 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
17430 { WM_MOVE
, sent
|defwinproc
},
17431 { WM_SIZE
, sent
|defwinproc
},
17432 { WM_NCCALCSIZE
, sent
|optional
},
17433 { WM_NCPAINT
, sent
|optional
},
17434 { WM_ERASEBKGND
, sent
|optional
},
17435 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17436 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
17437 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17438 { WM_ACTIVATE
, sent
|wparam
, TRUE
},
17439 { WM_SYNCPAINT
, sent
|optional
},
17440 { WM_PAINT
, sent
},
17444 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to an active minimized window */
17445 static const struct message WmRestoreActiveMinimizedOverlappedSeq
[] =
17447 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_RESTORE
, 0 },
17448 { HCBT_MINMAX
, hook
},
17449 { WM_QUERYOPEN
, sent
},
17450 { WM_GETTEXT
, sent
|optional
},
17451 { WM_NCACTIVATE
, sent
},
17452 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
17453 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
17454 { WM_NCCALCSIZE
, sent
|optional
},
17455 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
17456 { WM_MOVE
, sent
|optional
},
17457 { WM_SIZE
, sent
|optional
},
17458 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
17459 { WM_GETTEXT
, sent
|optional
},
17460 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
17461 { WM_GETMINMAXINFO
, sent
|defwinproc
},
17462 { WM_NCCALCSIZE
, sent
},
17463 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win8+. */
17464 { WM_NCPAINT
, sent
},
17465 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17466 { WM_ERASEBKGND
, sent
},
17467 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
17468 { WM_MOVE
, sent
|defwinproc
},
17469 { WM_SIZE
, sent
|defwinproc
},
17470 { WM_NCCALCSIZE
, sent
|optional
},
17471 { WM_NCPAINT
, sent
|optional
},
17472 { WM_ERASEBKGND
, sent
|optional
},
17473 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17474 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
17475 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17476 { HCBT_SETFOCUS
, hook
},
17477 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
17478 { WM_SETFOCUS
, sent
},
17479 /* Note this WM_ACTIVATE messages even if the window is already active */
17480 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
17481 { WM_SYNCPAINT
, sent
|optional
},
17482 { WM_PAINT
, sent
},
17483 { WM_GETMINMAXINFO
, sent
|optional
},
17487 static struct message WmContextMenuSeq
[] = {
17488 { WM_CONTEXTMENU
, sent
|wparam
, 0 }, /* wparams set in the code */
17489 { WM_CONTEXTMENU
, sent
|wparam
|defwinproc
, 0 },
17490 { WM_CONTEXTMENU
, sent
|wparam
|defwinproc
, 0 },
17494 struct rbuttonup_thread_data
17497 HANDLE wndproc_finished
;
17500 static DWORD CALLBACK
post_rbuttonup_msg( void *arg
)
17502 struct rbuttonup_thread_data
*data
= arg
;
17505 ret
= WaitForSingleObject( data
->wndproc_finished
, 500 );
17506 todo_wine
ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lx\n", ret
);
17507 if( ret
== WAIT_OBJECT_0
) return 0;
17509 PostMessageA( data
->hwnd
, WM_RBUTTONUP
, 0, 0 );
17513 static void test_defwinproc(void)
17515 HWND hwnd
, child
[3];
17517 BOOL gotwmquit
= FALSE
;
17522 struct rbuttonup_thread_data data
;
17526 hwnd
= CreateWindowExA(0, "TestWindowClass", "test_defwndproc",
17527 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0,0,500,100,0,0,0, NULL
);
17528 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
17532 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
17533 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
17535 /* Zero high word of the lParam */
17536 res
= DefWindowProcA(hwnd
, WM_SETTEXT
, 0, 0x1234);
17537 ok(res
== 0, "WM_SETTEXT was expected to fail, %Id\n", res
);
17539 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
17540 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
17542 res
= DefWindowProcW(hwnd
, WM_SETTEXT
, 0, 0x1234);
17543 ok(res
== 0, "WM_SETTEXT was expected to fail, %Id\n", res
);
17545 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
17546 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
17548 ShowWindow(hwnd
, SW_MINIMIZE
);
17552 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
17554 ok_sequence(WmRestoreMinimizedOverlappedSeq
, "DefWindowProcA(SC_RESTORE):overlapped", TRUE
);
17556 ShowWindow(hwnd
, SW_MINIMIZE
);
17557 SetActiveWindow(hwnd
);
17558 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
17561 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
17563 ok_sequence(WmRestoreActiveMinimizedOverlappedSeq
, "DefWindowProcA(SC_RESTORE):active minimized overlapped", TRUE
);
17565 child
[0] = CreateWindowExA(0, "TestWindowClass", "1st child",
17566 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, hwnd
, 0, 0, NULL
);
17567 child
[1] = CreateWindowExA(0, "TestWindowClass", "2nd child",
17568 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, child
[0], 0, 0, NULL
);
17569 child
[2] = CreateWindowExA(0, "TestWindowClass", "3rd child",
17570 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, child
[1], 0, 0, NULL
);
17573 test_context_menu
= TRUE
;
17574 DefWindowProcA(child
[2], WM_CONTEXTMENU
, 0xcafe, 0);
17575 test_context_menu
= FALSE
;
17576 WmContextMenuSeq
[0].wParam
= (WPARAM
)child
[2];
17577 WmContextMenuSeq
[1].wParam
= (WPARAM
)child
[1];
17578 WmContextMenuSeq
[2].wParam
= (WPARAM
)child
[0];
17579 ok_sequence(WmContextMenuSeq
, "DefWindowProcA(WM_CONTEXTMENU)", FALSE
);
17580 DestroyWindow(child
[0]);
17582 GetCursorPos(&pos
);
17583 GetWindowRect(hwnd
, &rect
);
17584 x
= (rect
.left
+rect
.right
) / 2;
17585 y
= rect
.top
+ GetSystemMetrics(SM_CYFRAME
) + 1;
17586 SetCursorPos(x
, y
);
17588 res
= DefWindowProcA( hwnd
, WM_NCHITTEST
, 0, MAKELPARAM(x
, y
));
17589 ok(res
== HTCAPTION
, "WM_NCHITTEST returned %Id\n", res
);
17591 mouse_event( MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0 );
17592 mouse_event( MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0 );
17596 mouse_event( MOUSEEVENTF_RIGHTUP
, 0, 0, 0, 0 );
17597 /* workaround for missing support for clicking on window frame */
17599 data
.wndproc_finished
= CreateEventA( NULL
, FALSE
, FALSE
, NULL
);
17600 thread
= CreateThread( NULL
, 0, post_rbuttonup_msg
, (void*)&data
, 0, NULL
);
17602 DefWindowProcA( hwnd
, WM_NCRBUTTONDOWN
, HTCAPTION
, MAKELPARAM(x
, y
));
17603 ok_sequence(NCRBUTTONDOWNSeq
, "WM_NCRBUTTONDOWN on caption", FALSE
);
17605 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, 0, MAKELPARAM(x
, y
));
17606 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17607 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP without button", FALSE
);
17609 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON1
), MAKELPARAM(x
, y
));
17610 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17611 ok_sequence(NCXBUTTONUPSeq1
, "WM_NCXBUTTONUP with XBUTTON1", FALSE
);
17613 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON2
), MAKELPARAM(x
, y
));
17614 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17615 ok_sequence(NCXBUTTONUPSeq2
, "WM_NCXBUTTONUP with XBUTTON2", FALSE
);
17617 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, 3), MAKELPARAM(x
, y
));
17618 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17619 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP with invalid button", FALSE
);
17621 /* Test WM_MOUSEACTIVATE */
17622 #define TEST_MOUSEACTIVATE(A,B,C) \
17623 res = DefWindowProcA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0)); \
17624 ok(res == B, "WM_MOUSEACTIVATE for %s returned %Id\n", #A, res); \
17625 res = DefWindowProcA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,WM_LBUTTONDOWN)); \
17626 ok(res == C, "WM_MOUSEACTIVATE for %s returned %Id\n", #A, res);
17628 TEST_MOUSEACTIVATE(HTERROR
, MA_ACTIVATE
, MA_ACTIVATE
);
17629 TEST_MOUSEACTIVATE(HTTRANSPARENT
, MA_ACTIVATE
, MA_ACTIVATE
);
17630 TEST_MOUSEACTIVATE(HTNOWHERE
, MA_ACTIVATE
, MA_ACTIVATE
);
17631 TEST_MOUSEACTIVATE(HTCLIENT
, MA_ACTIVATE
, MA_ACTIVATE
);
17632 TEST_MOUSEACTIVATE(HTCAPTION
, MA_ACTIVATE
, MA_NOACTIVATE
);
17633 TEST_MOUSEACTIVATE(HTSYSMENU
, MA_ACTIVATE
, MA_ACTIVATE
);
17634 TEST_MOUSEACTIVATE(HTSIZE
, MA_ACTIVATE
, MA_ACTIVATE
);
17635 TEST_MOUSEACTIVATE(HTMENU
, MA_ACTIVATE
, MA_ACTIVATE
);
17636 TEST_MOUSEACTIVATE(HTHSCROLL
, MA_ACTIVATE
, MA_ACTIVATE
);
17637 TEST_MOUSEACTIVATE(HTVSCROLL
, MA_ACTIVATE
, MA_ACTIVATE
);
17638 TEST_MOUSEACTIVATE(HTMINBUTTON
, MA_ACTIVATE
, MA_ACTIVATE
);
17639 TEST_MOUSEACTIVATE(HTMAXBUTTON
, MA_ACTIVATE
, MA_ACTIVATE
);
17640 TEST_MOUSEACTIVATE(HTLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
17641 TEST_MOUSEACTIVATE(HTRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
17642 TEST_MOUSEACTIVATE(HTTOP
, MA_ACTIVATE
, MA_ACTIVATE
);
17643 TEST_MOUSEACTIVATE(HTTOPLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
17644 TEST_MOUSEACTIVATE(HTTOPRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
17645 TEST_MOUSEACTIVATE(HTBOTTOM
, MA_ACTIVATE
, MA_ACTIVATE
);
17646 TEST_MOUSEACTIVATE(HTBOTTOMLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
17647 TEST_MOUSEACTIVATE(HTBOTTOMRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
17648 TEST_MOUSEACTIVATE(HTBORDER
, MA_ACTIVATE
, MA_ACTIVATE
);
17649 TEST_MOUSEACTIVATE(HTOBJECT
, MA_ACTIVATE
, MA_ACTIVATE
);
17650 TEST_MOUSEACTIVATE(HTCLOSE
, MA_ACTIVATE
, MA_ACTIVATE
);
17651 TEST_MOUSEACTIVATE(HTHELP
, MA_ACTIVATE
, MA_ACTIVATE
);
17653 SetEvent( data
.wndproc_finished
);
17654 WaitForSingleObject( thread
, 1000 );
17655 CloseHandle( data
.wndproc_finished
);
17656 CloseHandle( thread
);
17658 SetCursorPos(pos
.x
, pos
.y
);
17660 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
17661 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
17662 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
17663 DispatchMessageA( &msg
);
17665 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
17666 DestroyWindow( hwnd
);
17669 static void test_desktop_winproc(void)
17671 HINSTANCE instance
= GetModuleHandleA(NULL
);
17672 RECT rect
, default_rect
;
17673 WNDPROC desktop_proc
;
17680 ret
= GetClassInfoA(instance
, (const CHAR
*)MAKEINTATOM(32769), &cls
);
17681 ok(ret
, "Failed to get desktop class.\n");
17682 desktop_proc
= cls
.lpfnWndProc
;
17684 memset(&cls
, 0, sizeof(cls
));
17685 cls
.lpfnWndProc
= desktop_proc
;
17686 cls
.hInstance
= instance
;
17687 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
17688 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
17689 cls
.lpszClassName
= "TestDesktopClass";
17690 register_class(&cls
);
17692 hwnd
= CreateWindowExA(0, cls
.lpszClassName
, "test_desktop_wndproc",
17693 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0, 0, 500, 100, 0, 0, 0, NULL
);
17694 if (!hwnd
) /* win2003 */
17696 skip("Failed to create window with desktop window procedure.\n");
17697 goto out_unregister
;
17700 memset(&cls
, 0, sizeof(cls
));
17701 ret
= GetClassInfoA(instance
, "TestDesktopClass", &cls
);
17702 ok(ret
, "Failed to get class info.\n");
17703 ok(cls
.lpfnWndProc
== desktop_proc
, "Got %p, expected %p.\n", cls
.lpfnWndProc
, desktop_proc
);
17705 GetWindowTextA(hwnd
, buffer
, ARRAY_SIZE(buffer
));
17706 todo_wine
ok(!strcmp(buffer
, "test_desktop_wndproc"), "Got unexpected window text: %s.\n", buffer
);
17708 res
= CallWindowProcA(desktop_proc
, hwnd
, WM_SETTEXT
, 0, (LPARAM
)"test");
17709 ok(res
== TRUE
, "Failed to set text, %Id.\n", res
);
17710 GetWindowTextA(hwnd
, buffer
, ARRAY_SIZE(buffer
));
17711 ok(!strcmp(buffer
, "test"), "Got unexpected window text: %s.\n", buffer
);
17713 SetRect(&default_rect
, 0, 0, 100, 100);
17714 res
= DefWindowProcW(hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&default_rect
);
17715 ok(!res
, "Got unexpected result %Id.\n", res
);
17717 SetRect(&rect
, 0, 0, 100, 100);
17718 res
= CallWindowProcA(desktop_proc
, hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
);
17719 ok(!res
, "Got unexpected result %Id.\n", res
);
17720 todo_wine
ok(EqualRect(&rect
, &default_rect
), "rect Got %s, expected %s.\n",
17721 wine_dbgstr_rect(&rect
), wine_dbgstr_rect(&default_rect
));
17723 DestroyWindow(hwnd
);
17726 UnregisterClassA("TestDesktopClass", instance
);
17729 #define open_clipboard(hwnd) open_clipboard_(__LINE__, hwnd)
17730 static BOOL
open_clipboard_(int line
, HWND hwnd
)
17732 DWORD start
= GetTickCount();
17735 BOOL ret
= OpenClipboard(hwnd
);
17736 if (ret
|| GetLastError() != ERROR_ACCESS_DENIED
)
17738 if (GetTickCount() - start
> 100)
17740 char classname
[256];
17741 DWORD le
= GetLastError();
17742 HWND clipwnd
= GetOpenClipboardWindow();
17743 /* Provide a hint as to the source of interference:
17744 * - The class name would typically be CLIPBRDWNDCLASS if the
17745 * clipboard was opened by a Windows application using the
17747 * - And it would be __wine_clipboard_manager if it was opened in
17748 * response to a native application.
17750 GetClassNameA(clipwnd
, classname
, ARRAY_SIZE(classname
));
17751 trace_(__FILE__
, line
)("%p (%s) opened the clipboard\n", clipwnd
, classname
);
17759 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
17760 static void clear_clipboard_(int line
, HWND hWnd
)
17763 succ
= open_clipboard_(line
, hWnd
);
17764 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%lu\n", GetLastError());
17765 succ
= EmptyClipboard();
17766 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%lu\n", GetLastError());
17767 succ
= CloseClipboard();
17768 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%lu\n", GetLastError());
17771 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
17772 static void expect_HWND_(int line
, HWND expected
, HWND got
)
17774 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
17777 static WNDPROC pOldViewerProc
;
17779 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
17781 static BOOL recursion_guard
;
17783 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
17785 recursion_guard
= TRUE
;
17786 clear_clipboard(hWnd
);
17787 recursion_guard
= FALSE
;
17789 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
17792 static void test_clipboard_viewers(void)
17794 static struct message wm_change_cb_chain
[] =
17796 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
17799 static const struct message wm_clipboard_destroyed
[] =
17801 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
17804 static struct message wm_clipboard_changed
[] =
17806 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
17809 static struct message wm_clipboard_changed_and_owned
[] =
17811 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
17812 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
17816 HINSTANCE hInst
= GetModuleHandleA(NULL
);
17817 HWND hWnd1
, hWnd2
, hWnd3
;
17821 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
17822 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
17823 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
17824 GetDesktopWindow(), NULL
, hInst
, NULL
);
17825 ok(!!hWnd1
, "Failed to create window, error %lu.\n", GetLastError());
17826 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
17827 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
17828 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
17829 GetDesktopWindow(), NULL
, hInst
, NULL
);
17830 ok(!!hWnd2
, "Failed to create window, error %lu.\n", GetLastError());
17831 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
17832 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
17833 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
17834 GetDesktopWindow(), NULL
, hInst
, NULL
);
17835 ok(!!hWnd3
, "Failed to create window, error %lu.\n", GetLastError());
17836 if (winetest_debug
> 1) trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
17838 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */
17841 /* Test getting the clipboard viewer and setting the viewer to NULL. */
17842 hOrigViewer
= GetClipboardViewer();
17843 hRet
= SetClipboardViewer(NULL
);
17844 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
17845 expect_HWND(hOrigViewer
, hRet
);
17846 expect_HWND(NULL
, GetClipboardViewer());
17848 /* Test registering hWnd1 as a viewer. */
17849 hRet
= SetClipboardViewer(hWnd1
);
17850 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
17851 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
17852 expect_HWND(NULL
, hRet
);
17853 expect_HWND(hWnd1
, GetClipboardViewer());
17855 /* Test that changing the clipboard actually refreshes the registered viewer. */
17856 clear_clipboard(hWnd1
);
17857 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
17858 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
17860 /* Again, but with different owner. */
17861 clear_clipboard(hWnd2
);
17862 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
17863 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
17865 /* Test re-registering same window. */
17866 hRet
= SetClipboardViewer(hWnd1
);
17867 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
17868 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
17869 expect_HWND(hWnd1
, hRet
);
17870 expect_HWND(hWnd1
, GetClipboardViewer());
17872 /* Test ChangeClipboardChain. */
17873 ChangeClipboardChain(hWnd2
, hWnd3
);
17874 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
17875 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
17876 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
17877 expect_HWND(hWnd1
, GetClipboardViewer());
17879 ChangeClipboardChain(hWnd2
, NULL
);
17880 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
17881 wm_change_cb_chain
[0].lParam
= 0;
17882 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
17883 expect_HWND(hWnd1
, GetClipboardViewer());
17885 ChangeClipboardChain(NULL
, hWnd2
);
17886 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", FALSE
);
17887 expect_HWND(hWnd1
, GetClipboardViewer());
17889 /* Actually change clipboard viewer with ChangeClipboardChain. */
17890 ChangeClipboardChain(hWnd1
, hWnd2
);
17891 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
17892 expect_HWND(hWnd2
, GetClipboardViewer());
17894 /* Test that no refresh messages are sent when viewer has unregistered. */
17895 clear_clipboard(hWnd2
);
17896 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
17898 /* Register hWnd1 again. */
17899 ChangeClipboardChain(hWnd2
, hWnd1
);
17900 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
17901 expect_HWND(hWnd1
, GetClipboardViewer());
17903 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
17904 * changes the clipboard. When this happens, the system shouldn't send
17905 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
17907 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
17908 clear_clipboard(hWnd2
);
17909 /* The clipboard owner is changed in recursive_viewer_proc: */
17910 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
17911 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
17913 /* Test unregistering. */
17914 ChangeClipboardChain(hWnd1
, NULL
);
17915 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
17916 expect_HWND(NULL
, GetClipboardViewer());
17918 clear_clipboard(hWnd1
);
17919 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
17921 DestroyWindow(hWnd1
);
17922 DestroyWindow(hWnd2
);
17923 DestroyWindow(hWnd3
);
17924 SetClipboardViewer(hOrigViewer
);
17927 static void test_PostMessage(void)
17929 static const struct
17935 { HWND_TOP
/* 0 */, TRUE
},
17936 { HWND_BROADCAST
, TRUE
},
17937 { HWND_BOTTOM
, TRUE
},
17938 { HWND_TOPMOST
, TRUE
},
17939 { HWND_NOTOPMOST
, FALSE
},
17940 { HWND_MESSAGE
, FALSE
},
17941 { (HWND
)0xdeadbeef, FALSE
}
17947 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
17949 SetLastError(0xdeadbeef);
17950 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
17951 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
17953 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
17956 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
17960 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
17961 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
17963 for (i
= 0; i
< ARRAY_SIZE(data
); i
++)
17965 memset(&msg
, 0xab, sizeof(msg
));
17966 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
17967 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
17971 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
17972 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
17973 "%d: got ret %d hwnd %p msg %04x wParam %08Ix lParam %08Ix instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
17974 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
17976 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
17977 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
17978 "%d: got ret %d hwnd %p msg %04x wParam %08Ix lParam %08Ix instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
17979 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
17983 DestroyWindow(hwnd
);
17987 static WPARAM g_broadcast_wparam
;
17988 static UINT g_broadcast_msg
;
17989 static LRESULT WINAPI
broadcast_test_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
17991 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
17993 if (message
== g_broadcast_msg
)
17994 g_broadcast_wparam
= wParam
;
17996 return CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
17998 static WNDPROC
*g_oldproc_sub
;
17999 static WPARAM
*g_broadcast_sub_wparam
;
18000 static LRESULT WINAPI
broadcast_test_sub_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
18002 int sub_index
= GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
18004 if (message
== g_broadcast_msg
)
18005 g_broadcast_sub_wparam
[sub_index
] = wParam
;
18007 return CallWindowProcA(g_oldproc_sub
[sub_index
], hwnd
, message
, wParam
, lParam
);
18010 static void test_broadcast(void)
18012 static const UINT messages
[] =
18018 0xc000, /* lowest possible atom returned by RegisterWindowMessage */
18021 static const struct
18027 {WS_OVERLAPPED
, TRUE
},
18028 {WS_OVERLAPPED
|WS_DLGFRAME
, TRUE
},
18029 {WS_OVERLAPPED
|WS_BORDER
, TRUE
},
18030 {WS_OVERLAPPED
|WS_CAPTION
, TRUE
},
18032 {WS_CHILD
|WS_DLGFRAME
, FALSE
},
18033 {WS_CHILD
|WS_BORDER
, FALSE
},
18034 {WS_CHILD
|WS_CAPTION
, FALSE
},
18035 {WS_CHILD
|WS_POPUP
, TRUE
},
18037 {WS_POPUP
|WS_DLGFRAME
, TRUE
},
18038 {WS_POPUP
|WS_BORDER
, TRUE
},
18039 {WS_POPUP
|WS_CAPTION
, TRUE
},
18046 hwnd_sub
= malloc(ARRAY_SIZE(bcast_expect
) * sizeof(*hwnd_sub
));
18047 g_oldproc_sub
= malloc(ARRAY_SIZE(bcast_expect
) * sizeof(*g_oldproc_sub
));
18048 g_broadcast_sub_wparam
= malloc(ARRAY_SIZE(bcast_expect
) * sizeof(*g_broadcast_sub_wparam
));
18050 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0, 0, 0, 0, 0, 0, 0, NULL
);
18051 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
18053 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_proc
);
18054 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
18056 for (i
= 0; i
< ARRAY_SIZE(messages
); i
++)
18059 BOOL msg_expected
= (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000);
18063 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
18066 /* post, broadcast */
18067 ret
= PostMessageA(HWND_BROADCAST
, messages
[i
], 0, 0);
18068 ok(ret
, "%d: got %d, error %ld\n", i
, ret
, GetLastError());
18070 memset(&msg
, 0xab, sizeof(msg
));
18071 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
18072 ok(ret
== msg_expected
, "%d: message %04x, got %d, error %ld\n", i
, messages
[i
], ret
, GetLastError());
18074 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
18076 /* post, topmost */
18077 ret
= PostMessageA(HWND_TOPMOST
, messages
[i
], 0, 0);
18078 ok(ret
, "%d: got %d, error %ld\n", i
, ret
, GetLastError());
18080 memset(&msg
, 0xab, sizeof(msg
));
18081 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
18082 ok(ret
== msg_expected
, "%d: message %04x, got %d, error %ld\n", i
, messages
[i
], ret
, GetLastError());
18084 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
18087 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18089 hwnd_sub
[j
] = CreateWindowA("static", NULL
, bcast_expect
[j
].style
, 0, 0, 0, 0, hwnd
, 0, 0, NULL
);
18090 ok(hwnd_sub
[j
] != NULL
, "got %p\n", hwnd_sub
[j
]);
18091 /* CreateWindow adds extra style flags, so call SetWindowLong to clear some of those. */
18092 SetWindowLongA(hwnd_sub
[j
], GWL_STYLE
, bcast_expect
[j
].style
);
18094 g_oldproc_sub
[j
] = (WNDPROC
)SetWindowLongPtrA(hwnd_sub
[j
], GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_sub_proc
);
18095 SetWindowLongPtrA(hwnd_sub
[j
], GWLP_USERDATA
, (LONG_PTR
)j
);
18098 for (i
= 0; i
< ARRAY_SIZE(messages
); i
++)
18101 BOOL msg_expected
= (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000);
18103 /* send, broadcast */
18104 g_broadcast_wparam
= 0xdead;
18105 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18106 g_broadcast_sub_wparam
[j
] = 0xdead;
18107 g_broadcast_msg
= messages
[i
];
18108 ret
= SendMessageTimeoutA(HWND_BROADCAST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
18109 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
18110 win_skip("broadcasting test %d, timeout\n", i
);
18113 WPARAM wparam_expected
= msg_expected
? 0xbaadbeef : 0xdead;
18114 ok(g_broadcast_wparam
== wparam_expected
, "%d: message %04x, got %#Ix, error %ld\n",
18115 i
, messages
[i
], g_broadcast_wparam
, GetLastError());
18116 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18118 wparam_expected
= (msg_expected
&& bcast_expect
[j
].receive
) ? 0xbaadbeef : 0xdead;
18119 ok(g_broadcast_sub_wparam
[j
] == wparam_expected
,
18120 "%d,%d: message %04x, got %#Ix, error %ld\n", i
, j
, messages
[i
],
18121 g_broadcast_sub_wparam
[j
], GetLastError());
18125 /* send, topmost */
18126 g_broadcast_wparam
= 0xdead;
18127 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18128 g_broadcast_sub_wparam
[j
] = 0xdead;
18129 ret
= SendMessageTimeoutA(HWND_TOPMOST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
18130 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
18131 win_skip("broadcasting test %d, timeout\n", i
);
18134 WPARAM wparam_expected
= msg_expected
? 0xbaadbeef : 0xdead;
18135 ok(g_broadcast_wparam
== wparam_expected
, "%d: message %04x, got %#Ix, error %ld\n",
18136 i
, messages
[i
], g_broadcast_wparam
, GetLastError());
18137 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18139 wparam_expected
= (msg_expected
&& bcast_expect
[j
].receive
) ? 0xbaadbeef : 0xdead;
18140 ok(g_broadcast_sub_wparam
[j
] == wparam_expected
,
18141 "%d,%d: message %04x, got %#Ix, error %ld\n", i
, j
, messages
[i
],
18142 g_broadcast_sub_wparam
[j
], GetLastError());
18147 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18148 DestroyWindow(hwnd_sub
[j
]);
18150 free(g_broadcast_sub_wparam
);
18151 free(g_oldproc_sub
);
18154 DestroyWindow(hwnd
);
18157 static const struct
18161 } wait_idle_expect
[] =
18163 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18164 { WAIT_TIMEOUT
, 0, FALSE
},
18165 { WAIT_TIMEOUT
, 0, FALSE
},
18166 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18167 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18168 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
18169 { WAIT_TIMEOUT
, 0, FALSE
},
18170 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18173 /* 10 */ { 0, 0, FALSE
},
18175 { 0, WAIT_TIMEOUT
, FALSE
},
18178 /* 15 */ { 0, 0, FALSE
},
18179 { WAIT_TIMEOUT
, 0, FALSE
},
18180 { WAIT_TIMEOUT
, 0, FALSE
},
18181 { WAIT_TIMEOUT
, 0, FALSE
},
18182 { WAIT_TIMEOUT
, 0, FALSE
},
18183 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
18186 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
18190 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18192 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
18196 static void do_wait_idle_child( int arg
)
18203 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
18204 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
18206 memset( &cls
, 0, sizeof(cls
) );
18207 cls
.lpfnWndProc
= DefWindowProcA
;
18208 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
18209 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
18210 cls
.lpszClassName
= "TestClass";
18211 register_class(&cls
);
18213 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
18215 ok( start_event
!= 0, "failed to create start event, error %lu\n", GetLastError() );
18216 ok( end_event
!= 0, "failed to create end event, error %lu\n", GetLastError() );
18221 SetEvent( start_event
);
18224 SetEvent( start_event
);
18226 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
18229 SetEvent( start_event
);
18231 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18232 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
18233 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
18236 SetEvent( start_event
);
18238 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
18241 SetEvent( start_event
);
18243 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18244 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
18247 SetEvent( start_event
);
18249 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18250 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
18253 SetEvent( start_event
);
18255 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18256 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
18258 GetMessageA( &msg
, 0, 0, 0 );
18259 DispatchMessageA( &msg
);
18263 SetEvent( start_event
);
18265 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18266 SetTimer( hwnd
, 3, 1, NULL
);
18268 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
18271 SetEvent( start_event
);
18273 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18274 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
18277 SetEvent( start_event
);
18279 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18280 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
18281 for (;;) GetMessageA( &msg
, 0, 0, 0 );
18284 SetEvent( start_event
);
18286 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18287 SetTimer( hwnd
, 3, 1, NULL
);
18289 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
18292 SetEvent( start_event
);
18294 return; /* exiting the process makes WaitForInputIdle return success too */
18296 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18298 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
18299 SetEvent( start_event
);
18302 SetEvent( start_event
);
18303 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18305 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
18306 WaitForSingleObject( thread
, 10000 );
18307 CloseHandle( thread
);
18310 SetEvent( start_event
);
18312 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
18315 SetEvent( start_event
);
18317 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
18320 SetEvent( start_event
);
18322 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
18325 SetEvent( start_event
);
18327 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
18330 SetEvent( start_event
);
18332 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
18335 SetEvent( start_event
);
18337 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
18340 SetEvent( start_event
);
18342 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
18345 WaitForSingleObject( end_event
, 2000 );
18346 CloseHandle( start_event
);
18347 CloseHandle( end_event
);
18348 if (hwnd
) DestroyWindow( hwnd
);
18351 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
18353 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
18354 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
18357 static DWORD CALLBACK
wait_idle_thread( void *arg
)
18363 memset( &cls
, 0, sizeof(cls
) );
18364 cls
.lpfnWndProc
= wait_idle_proc
;
18365 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
18366 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
18367 cls
.lpszClassName
= "TestClass";
18368 register_class(&cls
);
18370 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18371 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
18372 DestroyWindow(hwnd
);
18376 static void test_WaitForInputIdle( char *argv0
)
18378 char path
[MAX_PATH
];
18379 PROCESS_INFORMATION pi
;
18380 STARTUPINFOA startup
;
18382 HANDLE start_event
, end_event
, thread
;
18385 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
18386 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
18387 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
18389 if (console_app
) /* build the test with -mwindows for better coverage */
18390 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
18392 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
18393 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
18394 ok(start_event
!= 0, "failed to create start event, error %lu\n", GetLastError());
18395 ok(end_event
!= 0, "failed to create end event, error %lu\n", GetLastError());
18397 memset( &startup
, 0, sizeof(startup
) );
18398 startup
.cb
= sizeof(startup
);
18399 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
18400 startup
.wShowWindow
= SW_SHOWNORMAL
;
18402 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
18404 for (i
= 0; i
< ARRAY_SIZE(wait_idle_expect
); i
++)
18406 ResetEvent( start_event
);
18407 ResetEvent( end_event
);
18408 sprintf( path
, "%s msg %u", argv0
, i
);
18409 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
18410 ok( ret
, "CreateProcess '%s' failed err %lu.\n", path
, GetLastError() );
18413 ret
= WaitForSingleObject( start_event
, 5000 );
18414 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
18415 if (ret
== WAIT_OBJECT_0
)
18417 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
18418 if (ret
== WAIT_FAILED
)
18420 ret
== wait_idle_expect
[i
].exp
||
18421 broken(ret
== wait_idle_expect
[i
].broken
),
18422 "%u: WaitForInputIdle error %08x expected %08lx\n",
18423 i
, ret
, wait_idle_expect
[i
].exp
);
18424 else todo_wine_if (wait_idle_expect
[i
].todo
)
18425 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
18426 "%u: WaitForInputIdle error %08x expected %08lx\n",
18427 i
, ret
, wait_idle_expect
[i
].exp
);
18428 SetEvent( end_event
);
18429 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
18431 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
18432 wait_child_process( pi
.hProcess
);
18433 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
18434 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
18435 CloseHandle( pi
.hProcess
);
18436 CloseHandle( pi
.hThread
);
18439 CloseHandle( end_event
);
18440 CloseHandle( start_event
);
18441 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
18442 WaitForSingleObject( thread
, 10000 );
18443 CloseHandle( thread
);
18446 static const struct message WmSetParentSeq_1
[] = {
18447 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
18448 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18449 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
18450 { WM_CHILDACTIVATE
, sent
},
18451 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
18452 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
18453 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18454 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
18458 static const struct message WmSetParentSeq_2
[] = {
18459 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
18460 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
18461 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
18462 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
18463 { HCBT_SETFOCUS
, hook
|optional
},
18464 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
18465 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
18466 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
18467 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
18468 { WM_KILLFOCUS
, sent
|wparam
, 0 },
18469 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18470 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
18471 { HCBT_ACTIVATE
, hook
|optional
},
18472 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
18473 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
18474 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
18475 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
18476 { HCBT_SETFOCUS
, hook
|optional
},
18477 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
18478 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
18479 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
18480 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
18481 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18482 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
18483 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
18484 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
18485 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
18490 static void test_SetParent(void)
18492 HWND parent1
, parent2
, child
, popup
;
18495 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
18496 100, 100, 200, 200, 0, 0, 0, NULL
);
18497 ok(parent1
!= 0, "Failed to create parent1 window\n");
18499 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
18500 400, 100, 200, 200, 0, 0, 0, NULL
);
18501 ok(parent2
!= 0, "Failed to create parent2 window\n");
18503 /* WS_CHILD window */
18504 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
18505 10, 10, 150, 150, parent1
, 0, 0, NULL
);
18506 ok(child
!= 0, "Failed to create child window\n");
18508 GetWindowRect(parent1
, &rc
);
18509 if (winetest_debug
> 1) trace("parent1 %s\n", wine_dbgstr_rect(&rc
));
18510 GetWindowRect(child
, &rc_old
);
18511 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
18512 if (winetest_debug
> 1) trace("child %s\n", wine_dbgstr_rect(&rc_old
));
18516 SetParent(child
, parent2
);
18518 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", FALSE
);
18520 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
18521 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
18523 GetWindowRect(parent2
, &rc
);
18524 if (winetest_debug
> 1) trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
18525 GetWindowRect(child
, &rc
);
18526 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
18527 if (winetest_debug
> 1) trace("child %s\n", wine_dbgstr_rect(&rc
));
18529 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
18530 wine_dbgstr_rect(&rc
));
18532 /* WS_POPUP window */
18533 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
18534 20, 20, 100, 100, 0, 0, 0, NULL
);
18535 ok(popup
!= 0, "Failed to create popup window\n");
18537 GetWindowRect(popup
, &rc_old
);
18538 if (winetest_debug
> 1) trace("popup %s\n", wine_dbgstr_rect(&rc_old
));
18542 SetParent(popup
, child
);
18544 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
18546 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
18547 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
18549 GetWindowRect(child
, &rc
);
18550 if (winetest_debug
> 1) trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
18551 GetWindowRect(popup
, &rc
);
18552 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
18553 if (winetest_debug
> 1) trace("popup %s\n", wine_dbgstr_rect(&rc
));
18555 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
18556 wine_dbgstr_rect(&rc
));
18558 DestroyWindow(popup
);
18559 DestroyWindow(child
);
18560 DestroyWindow(parent1
);
18561 DestroyWindow(parent2
);
18566 static const struct message WmKeyReleaseOnly
[] = {
18567 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
18568 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
18571 static const struct message WmKeyPressNormal
[] = {
18572 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
18573 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
18576 static const struct message WmKeyPressRepeat
[] = {
18577 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
18578 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
18581 static const struct message WmKeyReleaseNormal
[] = {
18582 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
18583 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
18587 static void test_keyflags(void)
18591 BYTE keyboard_state
[256];
18594 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
18595 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
),
18601 /* keyup without a keydown */
18602 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
18603 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18604 DispatchMessageA(&msg
);
18605 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
18607 key_state
= GetAsyncKeyState(0x41);
18608 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18610 key_state
= GetKeyState(0x41);
18611 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18614 keybd_event(0x41, 0, 0, 0);
18615 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18616 DispatchMessageA(&msg
);
18617 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
18619 key_state
= GetAsyncKeyState(0x41);
18620 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18622 key_state
= GetKeyState(0x41);
18623 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18625 /* keydown repeat */
18626 keybd_event(0x41, 0, 0, 0);
18627 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18628 DispatchMessageA(&msg
);
18629 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
18631 key_state
= GetAsyncKeyState(0x41);
18632 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18634 key_state
= GetKeyState(0x41);
18635 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18638 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
18639 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18640 DispatchMessageA(&msg
);
18641 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
18643 key_state
= GetAsyncKeyState(0x41);
18644 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18646 key_state
= GetKeyState(0x41);
18647 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18649 /* set the key state in this thread */
18650 GetKeyboardState(keyboard_state
);
18651 keyboard_state
[0x41] = 0x80;
18652 SetKeyboardState(keyboard_state
);
18654 key_state
= GetAsyncKeyState(0x41);
18655 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18658 keybd_event(0x41, 0, 0, 0);
18659 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18660 DispatchMessageA(&msg
);
18661 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
18663 key_state
= GetAsyncKeyState(0x41);
18664 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18666 key_state
= GetKeyState(0x41);
18667 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18669 /* clear the key state in this thread */
18670 GetKeyboardState(keyboard_state
);
18671 keyboard_state
[0x41] = 0;
18672 SetKeyboardState(keyboard_state
);
18674 key_state
= GetAsyncKeyState(0x41);
18675 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18678 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
18679 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18680 DispatchMessageA(&msg
);
18681 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
18683 key_state
= GetAsyncKeyState(0x41);
18684 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18686 key_state
= GetKeyState(0x41);
18687 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18689 DestroyWindow(test_window
);
18693 static const struct message WmHotkeyPressLWIN
[] = {
18694 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
18695 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
18696 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
18699 static const struct message WmHotkeyPress
[] = {
18700 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
18701 { WM_HOTKEY
, sent
|wparam
, 5 },
18704 static const struct message WmHotkeyRelease
[] = {
18705 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
18706 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
18707 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
18710 static const struct message WmHotkeyReleaseLWIN
[] = {
18711 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
18712 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
18713 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
18716 static const struct message WmHotkeyCombined
[] = {
18717 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
18718 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
18719 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
18720 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
18721 { WM_APP
, sent
, 0, 0 },
18722 { WM_HOTKEY
, sent
|wparam
, 5 },
18723 { WM_APP
+1, sent
, 0, 0 },
18724 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
18725 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
18726 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
18727 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
18728 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
18729 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
18732 static const struct message WmHotkeyPrevious
[] = {
18733 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
18734 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
18735 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
18736 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
18737 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
18738 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
18739 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
18740 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
18741 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
18742 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
18743 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
18744 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
18747 static const struct message WmHotkeyNew
[] = {
18748 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
18749 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
18750 { WM_HOTKEY
, sent
|wparam
, 5 },
18751 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
18752 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
18755 static const struct message WmHotkeyPressALT
[] = {
18756 { WM_SYSKEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LMENU
, LLKHF_INJECTED
|LLKHF_ALTDOWN
},
18757 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
18758 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
18761 static const struct message WmHotkeyPressWithALT
[] = {
18762 { WM_SYSKEYDOWN
, kbd_hook
, 0, LLKHF_INJECTED
|LLKHF_ALTDOWN
}, /* lparam not checked */
18763 { WM_HOTKEY
, sent
|wparam
, 6 },
18766 static const struct message WmHotkeyReleaseWithALT
[] = {
18767 { WM_SYSKEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
|LLKHF_ALTDOWN
},
18768 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0xa0000001 },
18769 { WM_SYSKEYUP
, sent
|lparam
, 0, 0xa0000001 },
18772 static const struct message WmHotkeyReleaseALT
[] = {
18773 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LMENU
, LLKHF_INJECTED
|LLKHF_UP
},
18774 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
18775 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
18779 static int hotkey_letter
;
18781 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
18783 struct recvd_message msg
;
18785 if (nCode
== HC_ACTION
)
18787 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
18790 msg
.message
= wParam
;
18791 msg
.flags
= kbd_hook
|wparam
|lparam
;
18792 msg
.wParam
= kdbhookstruct
->vkCode
;
18793 msg
.lParam
= kdbhookstruct
->flags
;
18794 msg
.descr
= "KeyboardHookProc";
18797 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
||
18798 wParam
== WM_SYSKEYUP
|| wParam
== WM_SYSKEYDOWN
)
18800 ok(kdbhookstruct
->vkCode
== VK_LWIN
||
18801 kdbhookstruct
->vkCode
== VK_LMENU
||
18802 kdbhookstruct
->vkCode
== hotkey_letter
,
18803 "unexpected keycode %lx\n", kdbhookstruct
->vkCode
);
18807 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
18810 static void test_hotkey(void)
18812 HWND test_window
, taskbar_window
;
18815 DWORD queue_status
;
18818 SetLastError(0xdeadbeef);
18819 ret
= UnregisterHotKey(NULL
, 0);
18822 skip("hotkeys not supported\n");
18826 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
18827 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
18828 "unexpected error %ld\n", GetLastError());
18830 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
18831 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
),
18834 SetForegroundWindow(test_window
);
18838 SetLastError(0xdeadbeef);
18839 ret
= UnregisterHotKey(test_window
, 0);
18840 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
18841 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
18842 "unexpected error %ld\n", GetLastError());
18844 /* Search for a Windows Key + letter combination that hasn't been registered */
18845 for (hotkey_letter
= 'A'; hotkey_letter
<= 'Z'; hotkey_letter
++)
18847 SetLastError(0xdeadbeef);
18848 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
18856 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
18857 "unexpected error %ld\n", GetLastError());
18861 if (hotkey_letter
> 'Z')
18863 ok(0, "Couldn't find any free Windows Key + letter combination\n");
18867 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
18868 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
18870 /* Same key combination, different id */
18871 SetLastError(0xdeadbeef);
18872 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
18873 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
18874 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
18875 "unexpected error %ld\n", GetLastError());
18877 /* Same key combination, different window */
18878 SetLastError(0xdeadbeef);
18879 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
18880 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
18881 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
18882 "unexpected error %ld\n", GetLastError());
18884 /* Register the same hotkey twice */
18885 SetLastError(0xdeadbeef);
18886 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
18887 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
18888 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
18889 "unexpected error %ld\n", GetLastError());
18891 /* Window on another thread */
18892 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
18893 if (!taskbar_window
)
18895 skip("no taskbar?\n");
18899 SetLastError(0xdeadbeef);
18900 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
18901 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
18902 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
18903 "unexpected error %ld\n", GetLastError());
18906 /* Inject the appropriate key sequence */
18907 keybd_event(VK_LWIN
, 0, 0, 0);
18908 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18909 DispatchMessageA(&msg
);
18910 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
18912 keybd_event(hotkey_letter
, 0, 0, 0);
18913 queue_status
= GetQueueStatus(QS_HOTKEY
);
18914 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
18915 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18917 if (msg
.message
== WM_HOTKEY
)
18919 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
18920 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
18922 DispatchMessageA(&msg
);
18924 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
18926 queue_status
= GetQueueStatus(QS_HOTKEY
);
18927 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %lx\n", queue_status
);
18929 key_state
= GetAsyncKeyState(hotkey_letter
);
18930 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18932 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
18933 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18934 DispatchMessageA(&msg
);
18935 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
18937 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
18938 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18939 DispatchMessageA(&msg
);
18940 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
18942 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
18943 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
18944 queue_status
= GetQueueStatus(QS_HOTKEY
);
18945 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
18946 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
18947 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %lx\n", queue_status
);
18948 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18949 DispatchMessageA(&msg
);
18952 /* Send and process all messages at once */
18953 PostMessageA(test_window
, WM_APP
, 0, 0);
18954 keybd_event(VK_LWIN
, 0, 0, 0);
18955 keybd_event(hotkey_letter
, 0, 0, 0);
18956 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
18957 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
18959 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18961 if (msg
.message
== WM_HOTKEY
)
18963 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
18964 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
18966 DispatchMessageA(&msg
);
18968 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
18970 /* Register same hwnd/id with different key combination */
18971 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
18972 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
18974 /* Previous key combination does not work */
18975 keybd_event(VK_LWIN
, 0, 0, 0);
18976 keybd_event(hotkey_letter
, 0, 0, 0);
18977 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
18978 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
18980 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18981 DispatchMessageA(&msg
);
18982 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
18984 /* New key combination works */
18985 keybd_event(hotkey_letter
, 0, 0, 0);
18986 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
18988 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
18990 if (msg
.message
== WM_HOTKEY
)
18992 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
18993 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
18995 DispatchMessageA(&msg
);
18997 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
18999 /* Unregister hotkey properly */
19000 ret
= UnregisterHotKey(test_window
, 5);
19001 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
19003 /* Unregister hotkey again */
19004 SetLastError(0xdeadbeef);
19005 ret
= UnregisterHotKey(test_window
, 5);
19006 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19007 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19008 "unexpected error %ld\n", GetLastError());
19010 /* Register thread hotkey */
19011 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
19012 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
19014 /* Inject the appropriate key sequence */
19015 keybd_event(VK_LWIN
, 0, 0, 0);
19016 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19018 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19019 DispatchMessageA(&msg
);
19021 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
19023 keybd_event(hotkey_letter
, 0, 0, 0);
19024 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19026 if (msg
.message
== WM_HOTKEY
)
19028 struct recvd_message message
;
19029 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
19030 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
19031 message
.message
= msg
.message
;
19032 message
.flags
= sent
|wparam
|lparam
;
19033 message
.wParam
= msg
.wParam
;
19034 message
.lParam
= msg
.lParam
;
19035 message
.descr
= "test_hotkey thread message";
19036 add_message(&message
);
19039 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19040 DispatchMessageA(&msg
);
19042 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
19044 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19045 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19047 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19048 DispatchMessageA(&msg
);
19050 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
19052 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
19053 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19055 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19056 DispatchMessageA(&msg
);
19058 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
19060 /* Search for an ALT + letter combination that hasn't been registered */
19061 for (hotkey_letter
= 'A'; hotkey_letter
<= 'Z'; hotkey_letter
++)
19063 SetLastError(0xdeadbeef);
19064 ret
= RegisterHotKey(test_window
, 6, MOD_ALT
, hotkey_letter
);
19072 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19073 "unexpected error %ld\n", GetLastError());
19077 if (hotkey_letter
> 'Z')
19079 ok(0, "Couldn't find any free ALT + letter combination\n");
19083 keybd_event(VK_LMENU
, 0, 0, 0);
19084 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19085 DispatchMessageA(&msg
);
19086 ok_sequence(WmHotkeyPressALT
, "window hotkey press ALT", TRUE
);
19088 keybd_event(hotkey_letter
, 0, 0, 0);
19089 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19091 if (msg
.message
== WM_HOTKEY
)
19093 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
19094 ok(msg
.lParam
== MAKELPARAM(MOD_ALT
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
19096 DispatchMessageA(&msg
);
19098 ok_sequence(WmHotkeyPressWithALT
, "window hotkey press with ALT", FALSE
);
19100 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19101 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19102 DispatchMessageA(&msg
);
19103 ok_sequence(WmHotkeyReleaseWithALT
, "window hotkey release with ALT", TRUE
);
19105 keybd_event(VK_LMENU
, 0, KEYEVENTF_KEYUP
, 0);
19106 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19107 DispatchMessageA(&msg
);
19108 ok_sequence(WmHotkeyReleaseALT
, "window hotkey release ALT", FALSE
);
19110 /* Unregister thread hotkey */
19111 ret
= UnregisterHotKey(NULL
, 5);
19112 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
19114 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
19118 UnregisterHotKey(NULL
, 5);
19119 UnregisterHotKey(test_window
, 5);
19120 UnregisterHotKey(test_window
, 6);
19121 DestroyWindow(test_window
);
19126 static const struct message WmSetFocus_1
[] = {
19127 { HCBT_SETFOCUS
, hook
}, /* child */
19128 { HCBT_ACTIVATE
, hook
}, /* parent */
19129 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
19130 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
19131 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
19132 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
19133 { WM_NCACTIVATE
, sent
|parent
},
19134 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
19135 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
19136 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
19137 { HCBT_SETFOCUS
, hook
}, /* parent */
19138 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
19139 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
19140 { WM_KILLFOCUS
, sent
|parent
},
19141 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
19142 { WM_SETFOCUS
, sent
},
19145 static const struct message WmSetFocus_2
[] = {
19146 { HCBT_SETFOCUS
, hook
}, /* parent */
19147 { WM_KILLFOCUS
, sent
},
19148 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
19149 { WM_SETFOCUS
, sent
|parent
},
19152 static const struct message WmSetFocus_3
[] = {
19153 { HCBT_SETFOCUS
, hook
}, /* child */
19157 static void test_SetFocus(void)
19159 HWND parent
, old_parent
, child
, old_focus
, old_active
;
19161 struct wnd_event wnd_event
;
19165 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
19166 ok(wnd_event
.start_event
!= 0, "CreateEvent error %ld\n", GetLastError());
19167 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
19168 ok(hthread
!= 0, "CreateThread error %ld\n", GetLastError());
19169 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
19170 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
19171 CloseHandle(wnd_event
.start_event
);
19173 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
19174 0, 0, 0, 0, 0, 0, 0, NULL
);
19175 ok(parent
!= 0, "failed to create parent window\n");
19176 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
19177 0, 0, 0, 0, parent
, 0, 0, NULL
);
19178 ok(child
!= 0, "failed to create child window\n");
19180 if (winetest_debug
> 1) trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
19183 SetActiveWindow(0);
19188 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
19189 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
19191 log_all_parent_messages
++;
19193 old_focus
= SetFocus(child
);
19194 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19195 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
19196 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
19197 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19198 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
19200 old_focus
= SetFocus(parent
);
19201 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19202 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
19203 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
19204 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19205 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19207 SetLastError(0xdeadbeef);
19208 old_focus
= SetFocus((HWND
)0xdeadbeef);
19209 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
19210 "expected ERROR_INVALID_WINDOW_HANDLE, got %ld\n", GetLastError());
19211 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19212 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
19213 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19214 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19215 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19217 SetLastError(0xdeadbeef);
19218 old_focus
= SetFocus(GetDesktopWindow());
19219 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
19220 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
19221 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19222 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
19223 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19224 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19225 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19227 SetLastError(0xdeadbeef);
19228 old_focus
= SetFocus(wnd_event
.hwnd
);
19229 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
19230 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
19231 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19232 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
19233 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19234 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19235 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19237 SetLastError(0xdeadbeef);
19238 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
19239 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
19240 "expected ERROR_INVALID_WINDOW_HANDLE, got %ld\n", GetLastError());
19241 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19242 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
19243 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
19244 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19245 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19247 SetLastError(0xdeadbeef);
19248 old_active
= SetActiveWindow(GetDesktopWindow());
19250 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
19251 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19252 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
19253 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
19254 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19255 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19257 SetLastError(0xdeadbeef);
19258 old_active
= SetActiveWindow(wnd_event
.hwnd
);
19260 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
19261 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19262 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
19263 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
19264 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19265 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19267 SetLastError(0xdeadbeef);
19268 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
19269 ok(ret
, "AttachThreadInput error %ld\n", GetLastError());
19271 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19272 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19277 old_focus
= SetFocus(wnd_event
.hwnd
);
19278 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19279 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
19280 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
19281 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
19283 old_focus
= SetFocus(parent
);
19284 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19285 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
19286 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19287 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19292 old_active
= SetActiveWindow(wnd_event
.hwnd
);
19293 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19294 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
19295 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
19296 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
19298 SetLastError(0xdeadbeef);
19299 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
19300 ok(ret
, "AttachThreadInput error %ld\n", GetLastError());
19302 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
19303 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
19305 old_parent
= SetParent(child
, GetDesktopWindow());
19306 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
19308 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
19309 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
19311 old_focus
= SetFocus(parent
);
19312 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19313 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
19314 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19315 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19320 SetLastError(0xdeadbeef);
19321 old_focus
= SetFocus(child
);
19323 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
19324 broken(GetLastError() == 0) /* XP */ ||
19325 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
19326 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19327 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
19328 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19329 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19330 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19332 SetLastError(0xdeadbeef);
19333 old_active
= SetActiveWindow(child
);
19334 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
19335 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19336 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
19337 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
19338 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19339 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19341 log_all_parent_messages
--;
19343 DestroyWindow(child
);
19344 DestroyWindow(parent
);
19346 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
19347 ok(ret
, "PostMessage(WM_QUIT) error %ld\n", GetLastError());
19348 ret
= WaitForSingleObject(hthread
, INFINITE
);
19349 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
19350 CloseHandle(hthread
);
19353 static const struct message WmSetLayeredStyle
[] = {
19354 { WM_STYLECHANGING
, sent
},
19355 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
19356 { WM_STYLECHANGED
, sent
},
19357 { WM_GETTEXT
, sent
|defwinproc
|optional
},
19361 static const struct message WmSetLayeredStyle2
[] = {
19362 { WM_STYLECHANGING
, sent
},
19363 { WM_STYLECHANGED
, sent
},
19364 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
19365 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
19366 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
19367 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
19368 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
19369 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
19370 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
19374 static const struct message WmLayeredWinEmptySeq
[] = {
19375 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
19379 struct layered_window_info
19388 static DWORD CALLBACK
update_layered_proc( void *param
)
19390 struct layered_window_info
*info
= param
;
19391 POINT src
= { 0, 0 };
19393 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
19394 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19395 ok( info
->ret
, "failed\n");
19396 SetEvent( info
->event
);
19400 static void test_layered_window(void)
19411 struct layered_window_info info
;
19413 if (!pUpdateLayeredWindow
)
19415 win_skip( "UpdateLayeredWindow not supported\n" );
19419 hdc
= CreateCompatibleDC( 0 );
19420 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
19421 SelectObject( hdc
, bmp
);
19423 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
19424 100, 100, 300, 300, 0, 0, 0, NULL
);
19425 ok( hwnd
!= 0, "failed to create window\n" );
19426 ShowWindow( hwnd
, SW_SHOWNORMAL
);
19427 UpdateWindow( hwnd
);
19431 GetWindowRect( hwnd
, &rect
);
19432 GetClientRect( hwnd
, &client
);
19433 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
19434 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
19437 pos
.x
= pos
.y
= 300;
19438 size
.cx
= size
.cy
= 250;
19439 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19440 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
19441 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
19442 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
19443 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
19445 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19446 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
19447 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
19448 GetWindowRect( hwnd
, &rect
);
19449 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
19450 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19451 GetClientRect( hwnd
, &rect
);
19452 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
19453 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19457 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19458 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
19459 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
19460 GetWindowRect( hwnd
, &rect
);
19461 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
19462 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19463 GetClientRect( hwnd
, &rect
);
19464 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
19465 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19467 SetWindowLongA( hwnd
, GWL_STYLE
,
19468 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
19469 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
19473 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19474 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
19475 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
19476 GetWindowRect( hwnd
, &rect
);
19477 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
19478 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19479 GetClientRect( hwnd
, &rect
);
19480 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
19481 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
19482 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19485 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19486 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
19487 ok( GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == ERROR_MR_MID_NOT_FOUND
) ||
19488 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win7 */, "wrong error %lu\n", GetLastError() );
19491 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19492 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
19493 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
19495 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
19496 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
19497 GetWindowRect( hwnd
, &rect
);
19498 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
19499 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19500 GetClientRect( hwnd
, &rect
);
19501 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
19502 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
19503 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19505 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
19508 info
.size
.cx
= 250;
19509 info
.size
.cy
= 300;
19510 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
19512 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
19513 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
19514 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
19515 WaitForSingleObject( thread
, 1000 );
19516 CloseHandle( thread
);
19517 GetWindowRect( hwnd
, &rect
);
19518 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
19519 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19520 GetClientRect( hwnd
, &rect
);
19521 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
19522 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
19523 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19525 DestroyWindow( hwnd
);
19527 DeleteObject( bmp
);
19530 static HMENU hpopupmenu
;
19532 static LRESULT WINAPI
minimize_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
19536 if (ignore_message( message
)) return 0;
19537 ret
= MsgCheckProc( FALSE
, hwnd
, message
, wParam
, lParam
);
19541 ShowWindow(hwnd
, SW_MINIMIZE
);
19551 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
19553 if (ignore_message( message
)) return 0;
19557 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
19561 case WM_INITMENUPOPUP
:
19562 case WM_UNINITMENUPOPUP
:
19563 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %Ix\n", hpopupmenu
, wParam
);
19565 case WM_CAPTURECHANGED
:
19566 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %Ix\n", lParam
);
19570 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
19573 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
19575 if (ignore_message( message
)) return 0;
19578 case WM_ENTERMENULOOP
:
19579 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
19583 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
19586 static void test_TrackPopupMenu(void)
19592 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
19595 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
19597 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
19599 hpopupmenu
= CreatePopupMenu();
19600 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
19602 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
19603 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
19607 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19608 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
19609 ok(ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError());
19611 /* Test popup closing with an ESC-press */
19613 PostMessageW(hwnd
, WM_KEYDOWN
, VK_ESCAPE
, 0);
19614 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19615 ok(ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError());
19616 PostQuitMessage(0);
19618 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
19620 TranslateMessage(&msg
);
19621 DispatchMessageA(&msg
);
19623 ok_sequence(WmTrackPopupMenuEsc
, "TrackPopupMenuEsc", FALSE
); /* Shouldn't get any message */
19625 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
19629 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19630 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
19631 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
19633 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)minimize_popup_proc
);
19635 /* set cursor over the window, otherwise the WM_CANCELMODE message may not always be sent */
19636 SetCursorPos( 0, 0 );
19637 ShowWindow( hwnd
, SW_SHOW
);
19641 SetTimer( hwnd
, TIMER_ID
, 500, NULL
);
19642 ret
= TrackPopupMenu( hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19643 ok_sequence( WmTrackPopupMenuMinimizeWindow
, "TrackPopupMenuMinimizeWindow", TRUE
);
19644 ok( ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError() );
19645 KillTimer( hwnd
, TIMER_ID
);
19646 ShowWindow( hwnd
, SW_RESTORE
);
19648 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
19654 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19655 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
19656 ok(ret
== 1, "TrackPopupMenuCapture failed with error %li\n", GetLastError());
19658 DestroyMenu(hpopupmenu
);
19659 DestroyWindow(hwnd
);
19662 static void test_TrackPopupMenuEmpty(void)
19667 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
19670 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
19672 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
19674 hpopupmenu
= CreatePopupMenu();
19675 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
19679 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19680 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
19681 ok(ret
== 0, "TrackPopupMenu succeeded\n");
19683 DestroyMenu(hpopupmenu
);
19684 DestroyWindow(hwnd
);
19687 static const struct message send_message_1
[] = {
19688 { WM_USER
+2, sent
|wparam
|lparam
, 0, 0 },
19689 { WM_USER
, sent
|wparam
|lparam
, 0, 0 },
19692 static const struct message send_message_2
[] = {
19693 { WM_USER
+4, sent
|wparam
|lparam
, 0, 0 },
19696 static const struct message send_message_3
[] = {
19697 { WM_USER
+3, sent
|wparam
|lparam
, 0, 0 },
19698 { WM_USER
+1, sent
|wparam
|lparam
, 0, 0 },
19701 static const struct message send_message_5
[] = {
19702 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOZORDER
}, /* win7+ dual monitor */
19703 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* win7+ dual monitor */
19704 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOZORDER
}, /* win7+ dual monitor */
19705 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* win7+ dual monitor */
19709 static DWORD WINAPI
SendMessage_thread_1(void *param
)
19711 struct wnd_event
*wnd_event
= param
;
19714 if (winetest_debug
> 1) trace("thread: starting\n");
19715 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
19717 if (winetest_debug
> 1) trace("thread: call PostMessage\n");
19718 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
19720 if (winetest_debug
> 1) trace("thread: call PostMessage\n");
19721 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
19723 if (winetest_debug
> 1) trace("thread: call SendMessage\n");
19724 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
19725 SetEvent(wnd_event
->stop_event
);
19726 ret
= WaitForSingleObject(wnd_event
->getmessage_complete
, 100);
19727 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed, ret:%lx\n", ret
);
19729 if (winetest_debug
> 1) trace("thread: call SendMessage\n");
19730 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
19735 static DWORD WINAPI
SendMessage_thread_2(void *param
)
19737 struct wnd_event
*wnd_event
= param
;
19740 if (winetest_debug
> 1) trace("thread: starting\n");
19741 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
19743 if (winetest_debug
> 1) trace("thread: call PostMessage\n");
19744 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
19746 if (winetest_debug
> 1) trace("thread: call PostMessage\n");
19747 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
19749 /* this leads to sending an internal message under Wine */
19750 if (winetest_debug
> 1) trace("thread: call SetParent\n");
19751 SetParent(wnd_event
->hwnd
, wnd_event
->hwnd
);
19753 if (winetest_debug
> 1) trace("thread: call SendMessage\n");
19754 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
19755 SetEvent(wnd_event
->stop_event
);
19756 ret
= WaitForSingleObject(wnd_event
->getmessage_complete
, 100);
19757 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed, ret:%lx\n", ret
);
19759 if (winetest_debug
> 1) trace("thread: call SendMessage\n");
19760 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
19765 static void test_SendMessage_other_thread(int thread_n
)
19767 DWORD qs_all_input
= QS_ALLINPUT
& ~QS_RAWINPUT
;
19769 struct wnd_event wnd_event
;
19773 winetest_push_context("thread_%i", thread_n
);
19775 wnd_event
.start_event
= CreateEventA(NULL
, 0, 0, NULL
);
19776 wnd_event
.stop_event
= CreateEventA(NULL
, 0, 0, NULL
);
19777 wnd_event
.getmessage_complete
= CreateEventA(NULL
, 0, 0, NULL
);
19779 wnd_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
19780 100, 100, 200, 200, 0, 0, 0, NULL
);
19781 ok(wnd_event
.hwnd
!= 0, "CreateWindowEx failed\n");
19783 hthread
= CreateThread(NULL
, 0, thread_n
== 1 ? SendMessage_thread_1
: SendMessage_thread_2
, &wnd_event
, 0, &tid
);
19784 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
19785 CloseHandle(hthread
);
19790 ret
= GetQueueStatus(QS_SENDMESSAGE
);
19791 ok(ret
== 0, "wrong status %08lx\n", ret
);
19793 SetEvent(wnd_event
.start_event
);
19795 /* wait for other thread's SendMessage */
19798 ret
= GetQueueStatus(QS_SENDMESSAGE
);
19799 if (ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
)) break;
19803 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
19804 ok(ret
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08lx\n", ret
);
19806 if (winetest_debug
> 1) trace("main: call GetMessage\n");
19807 GetMessageA(&msg
, 0, 0, 0);
19808 ok(msg
.message
== WM_USER
, "expected WM_USER, got %04x\n", msg
.message
);
19809 DispatchMessageA(&msg
);
19810 ok_sequence(send_message_1
, "SendMessage from other thread 1", thread_n
== 2);
19812 SetEvent(wnd_event
.getmessage_complete
);
19814 ret
= WaitForSingleObject(wnd_event
.stop_event
, 100);
19815 todo_wine_if (thread_n
== 2)
19816 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed, ret:%lx\n", ret
);
19818 /* intentionally yield */
19819 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
19821 if (winetest_debug
> 1) trace("main: call SendMessage\n");
19822 SendMessageA(wnd_event
.hwnd
, WM_USER
+4, 0, 0);
19823 ok_sequence(send_message_2
, "SendMessage from other thread 2", FALSE
);
19825 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
19826 ok(ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08lx\n", ret
);
19828 if (winetest_debug
> 1) trace("main: call PeekMessage\n");
19829 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should not fail\n");
19830 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
19831 DispatchMessageA(&msg
);
19832 ok_sequence(send_message_3
, "SendMessage from other thread 3", thread_n
== 2);
19834 /* intentionally yield */
19835 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
19837 if (winetest_debug
> 1) trace("main: call PeekMessage\n");
19838 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
19839 ok(ignore_message(msg
.message
), "got unexpected message %04x from PeekMessageA\n", msg
.message
);
19841 ok_sequence(send_message_5
, "SendMessage from other thread 5", thread_n
== 2);
19843 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
19844 ok(ret
== 0, "wrong status %08lx\n", ret
);
19846 if (winetest_debug
> 1) trace("main: call DestroyWindow\n");
19847 DestroyWindow(msg
.hwnd
);
19852 winetest_pop_context();
19854 CloseHandle(wnd_event
.start_event
);
19855 CloseHandle(wnd_event
.stop_event
);
19856 CloseHandle(wnd_event
.getmessage_complete
);
19859 static LRESULT CALLBACK
insendmessage_wnd_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
19861 DWORD flags
= InSendMessageEx( NULL
);
19867 ok( flags
== ISMEX_SEND
, "wrong flags %lx\n", flags
);
19868 ok( InSendMessage(), "InSendMessage returned false\n" );
19869 ret
= ReplyMessage( msg
);
19870 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
19871 flags
= InSendMessageEx( NULL
);
19872 ok( flags
== (ISMEX_SEND
| ISMEX_REPLIED
) || broken( flags
== (ISMEX_NOTIFY
| ISMEX_REPLIED
) ),
19873 "wrong flags %lx\n", flags
);
19874 ok( InSendMessage(), "InSendMessage returned false\n" );
19877 ok( flags
== ISMEX_NOTIFY
, "wrong flags %lx\n", flags
);
19878 ok( InSendMessage(), "InSendMessage returned false\n" );
19879 ret
= ReplyMessage( msg
);
19880 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
19881 flags
= InSendMessageEx( NULL
);
19882 ok( flags
== ISMEX_NOTIFY
, "wrong flags %lx\n", flags
);
19883 ok( InSendMessage(), "InSendMessage returned false\n" );
19886 ok( flags
== ISMEX_CALLBACK
, "wrong flags %lx\n", flags
);
19887 ok( InSendMessage(), "InSendMessage returned false\n" );
19888 ret
= ReplyMessage( msg
);
19889 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
19890 flags
= InSendMessageEx( NULL
);
19891 ok( flags
== (ISMEX_CALLBACK
| ISMEX_REPLIED
) || flags
== ISMEX_SEND
, "wrong flags %lx\n", flags
);
19892 ok( InSendMessage(), "InSendMessage returned false\n" );
19895 ok( flags
== ISMEX_NOSEND
, "wrong flags %lx\n", flags
);
19896 ok( !InSendMessage(), "InSendMessage returned true\n" );
19897 ret
= ReplyMessage( msg
);
19898 ok( !ret
, "ReplyMessage succeeded\n" );
19902 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
19905 static void CALLBACK
msg_callback( HWND hwnd
, UINT msg
, ULONG_PTR arg
, LRESULT result
)
19907 ok( msg
== WM_USER
+ 2, "wrong msg %x\n", msg
);
19908 ok( result
== WM_USER
+ 2, "wrong result %Ix\n", result
);
19911 static DWORD WINAPI
send_message_thread( void *arg
)
19915 SendMessageA( win
, WM_USER
, 0, 0 );
19916 SendNotifyMessageA( win
, WM_USER
+ 1, 0, 0 );
19917 SendMessageCallbackA( win
, WM_USER
+ 2, 0, 0, msg_callback
, 0 );
19918 PostMessageA( win
, WM_USER
+ 3, 0, 0 );
19919 PostMessageA( win
, WM_QUIT
, 0, 0 );
19923 static void test_InSendMessage(void)
19931 memset(&cls
, 0, sizeof(cls
));
19932 cls
.lpfnWndProc
= insendmessage_wnd_proc
;
19933 cls
.hInstance
= GetModuleHandleA(NULL
);
19934 cls
.lpszClassName
= "InSendMessage_test";
19935 register_class(&cls
);
19937 win
= CreateWindowA( "InSendMessage_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
19938 ok( win
!= NULL
, "CreateWindow failed: %ld\n", GetLastError() );
19940 thread
= CreateThread( NULL
, 0, send_message_thread
, win
, 0, &tid
);
19941 ok( thread
!= NULL
, "CreateThread failed: %ld\n", GetLastError() );
19943 while (GetMessageA(&msg
, NULL
, 0, 0)) DispatchMessageA( &msg
);
19945 ok( WaitForSingleObject( thread
, 30000 ) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
19946 CloseHandle( thread
);
19948 DestroyWindow( win
);
19949 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL
) );
19952 static const struct message DoubleSetCaptureSeq
[] =
19954 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
19955 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
19956 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
19957 { WM_CAPTURECHANGED
, sent
},
19961 static void test_DoubleSetCapture(void)
19965 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture",
19966 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
19967 100, 100, 200, 200, 0, 0, 0, NULL
);
19968 ok (hwnd
!= 0, "Failed to create overlapped window\n");
19970 ShowWindow( hwnd
, SW_SHOW
);
19971 UpdateWindow( hwnd
);
19975 SetCapture( hwnd
);
19976 SetCapture( hwnd
);
19977 ok_sequence(DoubleSetCaptureSeq
, "SetCapture( hwnd ) twice", FALSE
);
19979 DestroyWindow(hwnd
);
19982 static const struct message WmRestoreMinimizedSeq
[] =
19984 { HCBT_ACTIVATE
, hook
},
19985 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
19986 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
19987 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
19988 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
19989 { WM_NCACTIVATE
, sent
|wparam
, 0x200001 },
19990 { WM_GETTEXT
, sent
|defwinproc
|optional
},
19991 { WM_ACTIVATE
, sent
|wparam
, 0x200001 }, /* Note that activate messages are after WM_WINDOWPOSCHANGED and before WM_SYSCOMMAND */
19992 { HCBT_KEYSKIPPED
, hook
|optional
},
19993 { WM_SYSKEYUP
, sent
|optional
},
19994 { WM_SYSCOMMAND
, sent
|wparam
, SC_RESTORE
},
19995 { HCBT_SYSCOMMAND
, hook
|wparam
, SC_RESTORE
},
19996 { HCBT_SYSCOMMAND
, hook
|wparam
|optional
, SC_RESTORE
},
19997 { HCBT_MINMAX
, hook
},
19998 { HCBT_MINMAX
, hook
|optional
},
19999 { WM_QUERYOPEN
, sent
|defwinproc
},
20000 { WM_QUERYOPEN
, sent
|optional
},
20001 { WM_GETTEXT
, sent
|defwinproc
|optional
},
20002 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
20003 { WM_GETMINMAXINFO
, sent
|defwinproc
},
20004 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
20005 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
20006 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
20007 { WM_GETTEXT
, sent
|defwinproc
|optional
},
20008 { WM_ERASEBKGND
, sent
|defwinproc
},
20009 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
20010 { WM_MOVE
, sent
|defwinproc
},
20011 { WM_SIZE
, sent
|defwinproc
},
20012 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
20013 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
20014 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
20015 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
20016 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
20017 { HCBT_SETFOCUS
, hook
},
20018 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
20019 { WM_SETFOCUS
, sent
|defwinproc
},
20020 { WM_ACTIVATE
, sent
|wparam
|defwinproc
, 1 },
20021 { WM_PAINT
, sent
| optional
},
20022 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
20023 { HCBT_KEYSKIPPED
, hook
|optional
},
20024 { WM_KEYUP
, sent
|optional
},
20025 { HCBT_KEYSKIPPED
, hook
|optional
},
20026 { WM_SYSKEYUP
, sent
|optional
},
20027 { HCBT_KEYSKIPPED
, hook
|optional
},
20028 { WM_KEYUP
, sent
|optional
},
20029 { HCBT_KEYSKIPPED
, hook
|optional
},
20030 { WM_SYSKEYUP
, sent
|optional
},
20031 { HCBT_KEYSKIPPED
, hook
|optional
},
20032 { WM_KEYUP
, sent
|optional
},
20033 { WM_PAINT
, sent
| optional
},
20037 static void test_restore_messages(void)
20043 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, 100,
20044 100, 200, 200, 0, 0, 0, NULL
);
20045 ok (hwnd
!= 0, "Failed to create overlapped window\n");
20046 SetForegroundWindow(hwnd
);
20047 ShowWindow(hwnd
, SW_MINIMIZE
);
20051 for (i
= 0; i
< 5; i
++)
20053 /* Send Alt+Tab to restore test window from minimized state */
20054 ip
.type
= INPUT_KEYBOARD
;
20055 ip
.ki
.wVk
= VK_MENU
;
20056 SendInput(1, &ip
, sizeof(INPUT
));
20057 ip
.ki
.wVk
= VK_TAB
;
20058 SendInput(1, &ip
, sizeof(INPUT
));
20059 ip
.ki
.wVk
= VK_MENU
;
20060 ip
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
20061 SendInput(1, &ip
, sizeof(INPUT
));
20062 ip
.ki
.wVk
= VK_TAB
;
20063 ip
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
20064 SendInput(1, &ip
, sizeof(INPUT
));
20066 if (!IsIconic(hwnd
))
20070 if (IsIconic(hwnd
))
20072 skip("Alt+Tab failed to bring up test window.\n");
20075 ok_sequence(WmRestoreMinimizedSeq
, "Restore minimized window", TRUE
);
20078 DestroyWindow(hwnd
);
20081 static void test_invalid_window(void)
20086 SetLastError(0xdeadbeef);
20087 ret
= GetMessageA(&msg
, (HWND
)0xdeadbeef, 0, 0);
20088 ok(ret
== -1, "wrong ret %d\n", ret
);
20089 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError());
20091 SetLastError(0xdeadbeef);
20092 ret
= PeekMessageA(&msg
, (HWND
)0xdeadbeef, 0, 0, PM_REMOVE
);
20093 ok(!ret
, "wrong ret %d\n", ret
);
20094 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError());
20097 static void test_button_style(void)
20099 DWORD type
, expected_type
;
20104 for (i
= BS_PUSHBUTTON
; i
<= BS_DEFCOMMANDLINK
; ++i
)
20106 button
= CreateWindowA(WC_BUTTONA
, "test", i
, 0, 0, 50, 50, NULL
, 0, 0, NULL
);
20107 ok(button
!= NULL
, "Expected button not null.\n");
20109 type
= GetWindowLongW(button
, GWL_STYLE
) & BS_TYPEMASK
;
20110 expected_type
= (i
== BS_USERBUTTON
? BS_PUSHBUTTON
: i
);
20111 ok(type
== expected_type
, "Expected type %#lx, got %#lx.\n", expected_type
, type
);
20113 for (j
= BS_PUSHBUTTON
; j
<= BS_DEFCOMMANDLINK
; ++j
)
20115 ret
= SendMessageA(button
, BM_SETSTYLE
, j
, FALSE
);
20116 ok(ret
== 0, "Expected %#x, got %#Ix.\n", 0, ret
);
20118 type
= GetWindowLongW(button
, GWL_STYLE
) & BS_TYPEMASK
;
20121 ok(type
== expected_type
, "Original type %#lx, expected new type %#lx, got %#lx.\n", i
,
20122 expected_type
, type
);
20124 DestroyWindow(button
);
20128 static LRESULT WINAPI
test_create_name_procW( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
20135 CREATESTRUCTW
*cs
= (CREATESTRUCTW
*)lparam
;
20136 memcpy( cs
->lpCreateParams
, cs
->lpszName
, 3 * sizeof(WCHAR
) );
20140 if (winetest_debug
> 1) trace("%s\n", debugstr_w((const WCHAR
*)lparam
));
20144 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
20147 static void test_create_name(void)
20149 WNDCLASSW clsW
= { 0 };
20153 clsW
.lpfnWndProc
= test_create_name_procW
;
20154 clsW
.lpszClassName
= L
"TestCreateNameClassW";
20155 RegisterClassW( &clsW
);
20157 hwnd
= CreateWindowExW( 0, L
"TestCreateNameClassW", L
"\xffff\x6162",
20158 WS_POPUP
, 0,0,0,0,0,0,0, name_buf
);
20159 ok( hwnd
!= NULL
, "CreateWindowEx failed: %lu\n", GetLastError() );
20160 ok(!memcmp(name_buf
, L
"\xffff\x6162", 2 * sizeof(WCHAR
)),
20161 "name param = %s\n", debugstr_wn(name_buf
, 2));
20162 DestroyWindow( hwnd
);
20164 hwnd
= CreateWindowExA( 0, "TestCreateNameClassW", "\xff\0\x61\x60",
20165 WS_POPUP
, 0,0,0,0,0,0,0, name_buf
);
20166 ok( hwnd
!= NULL
, "CreateWindowEx failed: %lu\n", GetLastError() );
20167 ok(!memcmp(name_buf
, L
"\xffff\x6100", 2 * sizeof(WCHAR
)),
20168 "name param = %s\n", debugstr_wn(name_buf
, 2));
20169 DestroyWindow( hwnd
);
20171 UnregisterClassW( L
"TestCreateNameClassW", NULL
);
20174 static LRESULT WINAPI
changed_window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
20176 if (msg
== WM_USER
) return 3;
20177 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
20180 static LRESULT WINAPI
call_window_proc_hook( INT code
, WPARAM wparam
, LPARAM lparam
)
20182 CWPSTRUCT
*cwp
= (CWPSTRUCT
*)lparam
;
20184 ok( cwp
->message
== WM_USER
, "message = %u\n", cwp
->message
);
20185 SetWindowLongPtrW( cwp
->hwnd
, GWLP_WNDPROC
, (LONG_PTR
)changed_window_proc
);
20186 return CallNextHookEx( NULL
, code
, wparam
, lparam
);
20189 static void test_hook_changing_window_proc(void)
20195 hwnd
= CreateWindowExW( 0, L
"static", NULL
, WS_POPUP
, 0,0,0,0,GetDesktopWindow(),0,0, NULL
);
20196 hook
= SetWindowsHookExW( WH_CALLWNDPROC
, call_window_proc_hook
, NULL
, GetCurrentThreadId() );
20197 ok( hook
!= NULL
, "SetWindowsHookExW failed: %lu\n", GetLastError() );
20199 res
= SendMessageW( hwnd
, WM_USER
, 1, 2 );
20200 ok( res
== 3, "SendMessageW(WM_USER) returned %Iu\n", res
);
20202 UnhookWindowsHookEx( hook
);
20203 DestroyWindow( hwnd
);
20210 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
20213 argc
= winetest_get_mainargs( &test_argv
);
20217 /* Child process. */
20218 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
20219 do_wait_idle_child( arg
);
20223 InitializeCriticalSection( &sequence_cs
);
20227 register_classes();
20229 if (pSetWinEventHook
)
20231 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
20232 GetModuleHandleA(0), win_event_proc
,
20233 0, GetCurrentThreadId(),
20234 WINEVENT_INCONTEXT
);
20235 if (pIsWinEventHookInstalled
&& hEvent_hook
)
20238 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
20239 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
20242 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
20244 cbt_hook_thread_id
= winevent_hook_thread_id
= GetCurrentThreadId();
20245 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
20246 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
20249 test_SendMessage_other_thread(1);
20250 test_SendMessage_other_thread(2);
20251 test_InSendMessage();
20254 test_PostMessage();
20257 test_PeekMessage();
20258 test_PeekMessage2();
20259 test_PeekMessage3();
20260 test_WaitForInputIdle( test_argv
[0] );
20261 test_scrollwindowex();
20263 test_setwindowpos();
20265 invisible_parent_tests();
20266 test_mdi_messages();
20267 test_button_messages();
20268 test_button_bm_get_set_image();
20269 test_button_style();
20270 test_autoradio_BM_CLICK();
20271 test_autoradio_kbd_move();
20272 test_static_messages();
20273 test_listbox_messages();
20274 test_combobox_messages();
20275 test_wmime_keydown_message();
20276 test_paint_messages();
20277 run_in_temp_desktop(test_swp_paint_regions
);
20278 run_in_temp_desktop(test_swp_paint_region_on_show
);
20279 run_in_temp_desktop(test_swp_paint_region_on_extend_zerosize
);
20280 run_in_temp_desktop(test_hvredraw
);
20281 test_interthread_messages();
20282 test_message_conversion();
20283 test_accelerators();
20285 test_timers_no_wnd();
20286 test_timers_exceptions();
20290 test_recursive_hook();
20292 test_DestroyWindow();
20293 test_DispatchMessage();
20294 test_SendMessageTimeout();
20295 test_edit_messages();
20296 test_quit_message();
20297 test_notify_message();
20298 test_SetActiveWindow();
20299 test_restore_messages();
20300 test_invalid_window();
20301 test_menu_messages();
20302 test_paintingloop();
20304 if (!pTrackMouseEvent
)
20305 win_skip("TrackMouseEvent is not available\n");
20307 test_TrackMouseEvent();
20309 test_SetWindowRgn();
20311 test_dialog_messages();
20313 test_nullCallback();
20314 test_dbcs_wm_char();
20315 test_unicode_wm_char();
20317 test_desktop_winproc();
20318 test_clipboard_viewers();
20321 test_layered_window();
20322 test_TrackPopupMenu();
20323 test_TrackPopupMenuEmpty();
20324 test_DoubleSetCapture();
20325 test_create_name();
20326 test_hook_changing_window_proc();
20327 /* keep it the last test, under Windows it tends to break the tests
20328 * which rely on active/foreground windows being correct.
20330 test_SetForegroundWindow();
20332 UnhookWindowsHookEx(hCBT_hook
);
20333 if (pUnhookWinEvent
&& hEvent_hook
)
20335 ret
= pUnhookWinEvent(hEvent_hook
);
20336 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
20337 SetLastError(0xdeadbeef);
20338 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
20339 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
20340 GetLastError() == 0xdeadbeef, /* Win9x */
20341 "unexpected error %ld\n", GetLastError());
20343 DeleteCriticalSection( &sequence_cs
);