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
);
123 FIXME: add tests for these
124 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
125 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
126 WS_THICKFRAME: thick border
127 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
128 WS_BORDER (default for overlapped windows): single black border
129 none (default for child (and popup?) windows): no border
144 winevent_hook_todo
=0x800
148 UINT message
; /* the WM_* code */
149 msg_flags_t flags
; /* message props */
150 WPARAM wParam
; /* expected value of wParam */
151 LPARAM lParam
; /* expected value of lParam */
152 WPARAM wp_mask
; /* mask for wParam checks */
153 LPARAM lp_mask
; /* mask for lParam checks */
156 struct recvd_message
{
157 UINT message
; /* the WM_* code */
158 msg_flags_t flags
; /* message props */
159 HWND hwnd
; /* window that received the message */
160 WPARAM wParam
; /* expected value of wParam */
161 LPARAM lParam
; /* expected value of lParam */
162 int line
; /* source line where logged */
163 const char *descr
; /* description for trace output */
164 char output
[512]; /* trace output */
167 /* Empty message sequence */
168 static const struct message WmEmptySeq
[] =
172 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
173 static const struct message WmCreateOverlappedSeq
[] = {
174 { HCBT_CREATEWND
, hook
},
175 { WM_GETMINMAXINFO
, sent
},
176 { WM_NCCREATE
, sent
},
177 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
178 { 0x0093, sent
|defwinproc
|optional
},
179 { 0x0094, sent
|defwinproc
|optional
},
180 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
182 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
185 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
186 * for a not visible overlapped window.
188 static const struct message WmSWP_ShowOverlappedSeq
[] = {
189 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
190 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
191 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
192 { WM_GETTEXT
, sent
|defwinproc
|optional
},
193 { WM_ERASEBKGND
, sent
|optional
},
194 { HCBT_ACTIVATE
, hook
},
195 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
196 { WM_NOTIFYFORMAT
, sent
|optional
},
197 { WM_QUERYUISTATE
, sent
|optional
},
198 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
199 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
200 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
201 { WM_NCACTIVATE
, sent
},
202 { WM_GETTEXT
, sent
|defwinproc
|optional
},
203 { WM_ACTIVATE
, sent
|wparam
, 1 },
204 { HCBT_SETFOCUS
, hook
},
205 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
206 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
207 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
208 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
209 { WM_GETTEXT
, sent
|optional
},
210 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
211 { WM_GETTEXT
, sent
|defwinproc
|optional
},
212 { WM_ERASEBKGND
, sent
|optional
},
213 /* Win9x adds SWP_NOZORDER below */
214 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
215 { WM_GETTEXT
, sent
|optional
},
216 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
217 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
218 { WM_ERASEBKGND
, sent
|optional
},
219 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10 */
220 { WM_SYNCPAINT
, sent
|optional
},
221 { WM_GETTITLEBARINFOEX
, sent
|optional
},
222 { WM_PAINT
, sent
|optional
},
223 { WM_NCPAINT
, sent
|beginpaint
|optional
},
224 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
225 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
228 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
229 * for a visible overlapped window.
231 static const struct message WmSWP_HideOverlappedSeq
[] = {
232 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
233 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
234 { HCBT_ACTIVATE
, hook
|optional
},
235 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
236 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
237 { WM_NCACTIVATE
, sent
|optional
},
238 { WM_ACTIVATE
, sent
|optional
},
239 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
243 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
244 * for a visible overlapped window.
246 static const struct message WmSWP_ResizeSeq
[] = {
247 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
248 { WM_GETMINMAXINFO
, sent
|defwinproc
},
249 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
250 { WM_NCPAINT
, sent
|optional
},
251 { WM_GETTEXT
, sent
|defwinproc
|optional
},
252 { WM_ERASEBKGND
, sent
|optional
},
253 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
254 { WM_SIZE
, sent
|defwinproc
|optional
},
255 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
256 { WM_NCPAINT
, sent
|optional
},
257 { WM_GETTEXT
, sent
|defwinproc
|optional
},
258 { WM_ERASEBKGND
, sent
|optional
},
259 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
260 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
264 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
265 * for a visible popup window.
267 static const struct message WmSWP_ResizePopupSeq
[] = {
268 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
269 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* Win9x */
270 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
271 { WM_NCPAINT
, sent
|optional
},
272 { WM_GETTEXT
, sent
|defwinproc
|optional
},
273 { WM_ERASEBKGND
, sent
|optional
},
274 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
275 { WM_SIZE
, sent
|defwinproc
|wparam
|optional
, SIZE_RESTORED
},
276 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
277 { WM_NCPAINT
, sent
|optional
},
278 { WM_GETTEXT
, sent
|defwinproc
|optional
},
279 { WM_ERASEBKGND
, sent
|optional
},
280 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
284 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
285 * for a visible overlapped window.
287 static const struct message WmSWP_MoveSeq
[] = {
288 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
},
289 { WM_NCPAINT
, sent
|optional
},
290 { WM_GETTEXT
, sent
|defwinproc
|optional
},
291 { WM_ERASEBKGND
, sent
|optional
},
292 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
293 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
294 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
297 /* Resize with SetWindowPos(SWP_NOZORDER)
298 * for a visible overlapped window
299 * SWP_NOZORDER is stripped by the logging code
301 static const struct message WmSWP_ResizeNoZOrder
[] = {
302 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
},
303 { WM_GETMINMAXINFO
, sent
|defwinproc
},
304 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
305 { WM_NCPAINT
, sent
|optional
},
306 { WM_GETTEXT
, sent
|defwinproc
|optional
},
307 { WM_ERASEBKGND
, sent
|optional
},
308 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
, 0,
309 SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
310 { WM_MOVE
, sent
|defwinproc
|optional
},
311 { WM_SIZE
, sent
|defwinproc
|optional
},
312 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
313 { WM_NCPAINT
, sent
|optional
}, /* Win9x doesn't send it */
314 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
315 { WM_ERASEBKGND
, sent
|optional
}, /* Win9x doesn't send it */
316 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
317 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
321 /* Switch visible mdi children */
322 static const struct message WmSwitchChild
[] = {
323 /* Switch MDI child */
324 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
325 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 1st MDI child */
326 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
327 { WM_CHILDACTIVATE
, sent
},/* in the 1st MDI child */
328 /* Deactivate 2nd MDI child */
329 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
330 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
331 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
332 /* Preparing for maximize and maximize the 1st MDI child */
333 { WM_GETMINMAXINFO
, sent
|defwinproc
}, /* in the 1st MDI child */
334 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
}, /* in the 1st MDI child */
335 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
336 { WM_CHILDACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
337 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 1st MDI child */
338 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
}, /* in the 1st MDI child */
339 /* Lock redraw 2nd MDI child */
340 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
341 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
342 /* Restore 2nd MDI child */
343 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},/* in the 2nd MDI child */
344 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
345 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
346 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 2nd MDI child */
347 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
}, /* in the 2nd MDI child */
348 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
349 /* Redraw 2nd MDI child */
350 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
351 /* Redraw MDI frame */
352 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},/* in MDI frame */
353 { WM_NCCALCSIZE
, sent
|wparam
, 1 },/* in MDI frame */
354 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in MDI frame */
355 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in MDI frame */
356 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
357 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
358 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
359 { HCBT_SETFOCUS
, hook
},
360 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
361 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },/* in the 1st MDI child */
362 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
363 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
364 { WM_SETFOCUS
, sent
},/* in the MDI client */
365 { HCBT_SETFOCUS
, hook
},
366 { WM_KILLFOCUS
, sent
},/* in the MDI client */
367 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
368 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 }, /* in the 1st MDI child */
369 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
370 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
371 { WM_MDIACTIVATE
, sent
|defwinproc
},/* in the 1st MDI child */
372 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 1st MDI child */
376 /* Switch visible not maximized mdi children */
377 static const struct message WmSwitchNotMaximizedChild
[] = {
378 /* Switch not maximized MDI child */
379 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
380 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 2nd MDI child */
381 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
382 { WM_CHILDACTIVATE
, sent
},/* in the 2nd MDI child */
383 /* Deactivate 1st MDI child */
384 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
385 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
386 /* Activate 2nd MDI child */
387 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
}, /* in the 2nd MDI child */
388 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 2nd MDI child */
389 { HCBT_SETFOCUS
, hook
}, /* in the 1st MDI child */
390 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
391 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
392 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
393 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
394 { WM_SETFOCUS
, sent
, 0 }, /* in the MDI client */
395 { HCBT_SETFOCUS
, hook
},
396 { WM_KILLFOCUS
, sent
}, /* in the MDI client */
397 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
398 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
399 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
400 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
401 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
402 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 2nd MDI child */
407 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
408 SWP_NOZORDER|SWP_FRAMECHANGED)
409 * for a visible overlapped window with WS_CLIPCHILDREN style set.
411 static const struct message WmSWP_FrameChanged_clip
[] = {
412 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
413 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
414 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
415 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
416 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
417 { WM_NCPAINT
, sent
}, /* wparam != 1 */
418 { WM_ERASEBKGND
, sent
},
419 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
420 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
424 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
425 SWP_NOZORDER|SWP_FRAMECHANGED)
426 * for a visible overlapped window.
428 static const struct message WmSWP_FrameChangedDeferErase
[] = {
429 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
430 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
431 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
432 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
433 { WM_PAINT
, sent
|parent
|optional
},
434 { WM_NCPAINT
, sent
|beginpaint
|parent
|optional
}, /* wparam != 1 */
435 { WM_GETTEXT
, sent
|beginpaint
|parent
|defwinproc
|optional
},
437 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
438 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
442 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
443 SWP_NOZORDER|SWP_FRAMECHANGED)
444 * for a visible overlapped window without WS_CLIPCHILDREN style set.
446 static const struct message WmSWP_FrameChanged_noclip
[] = {
447 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
448 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
449 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
450 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
451 { WM_ERASEBKGND
, sent
|parent
|optional
},
452 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
453 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
455 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
456 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
460 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
461 static const struct message WmShowOverlappedSeq
[] = {
462 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
463 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
464 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
465 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
466 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
467 { WM_GETTEXT
, sent
|defwinproc
|optional
},
468 { WM_ERASEBKGND
, sent
|optional
},
469 { HCBT_ACTIVATE
, hook
|optional
},
470 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
471 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
472 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
473 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
474 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
475 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
476 { WM_GETTEXT
, sent
|defwinproc
|optional
},
477 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
478 { HCBT_SETFOCUS
, hook
|optional
},
479 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
480 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
481 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
482 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
483 { WM_GETTEXT
, sent
|optional
},
484 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
485 { WM_GETTEXT
, sent
|defwinproc
|optional
},
486 { WM_ERASEBKGND
, sent
|optional
},
487 /* Win9x adds SWP_NOZORDER below */
488 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
489 { WM_NCCALCSIZE
, sent
|optional
},
490 { WM_GETTEXT
, sent
|optional
},
491 { WM_NCPAINT
, sent
|optional
},
492 { WM_ERASEBKGND
, sent
|optional
},
493 { WM_SYNCPAINT
, sent
|optional
},
494 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
495 * messages. Does that mean that CreateWindow doesn't set initial
496 * window dimensions for overlapped windows?
501 { WM_PAINT
, sent
|optional
},
502 { WM_NCPAINT
, sent
|beginpaint
|optional
},
505 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
506 static const struct message WmShowMaxOverlappedSeq
[] = {
507 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
508 { WM_GETMINMAXINFO
, sent
},
509 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
510 { WM_GETMINMAXINFO
, sent
|defwinproc
},
511 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
512 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
513 { HCBT_ACTIVATE
, hook
|optional
},
514 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
515 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
516 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
517 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
518 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
519 { WM_GETTEXT
, sent
|defwinproc
|optional
},
520 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
521 { HCBT_SETFOCUS
, hook
|optional
},
522 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
523 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
524 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
525 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
526 { WM_GETTEXT
, sent
|optional
},
527 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
528 { WM_GETTEXT
, sent
|defwinproc
|optional
},
529 { WM_ERASEBKGND
, sent
|optional
},
530 /* Win9x adds SWP_NOZORDER below */
531 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
532 { WM_MOVE
, sent
|defwinproc
},
533 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
534 { WM_GETTEXT
, sent
|optional
},
535 { WM_NCCALCSIZE
, sent
|optional
},
536 { WM_NCPAINT
, sent
|optional
},
537 { WM_ERASEBKGND
, sent
|optional
},
538 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
539 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
540 { WM_SYNCPAINT
, sent
|optional
},
541 { WM_GETTITLEBARINFOEX
, sent
|optional
},
542 { WM_PAINT
, sent
|optional
},
543 { WM_NCPAINT
, sent
|beginpaint
|optional
},
544 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
547 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
548 static const struct message WmShowRestoreMaxOverlappedSeq
[] = {
549 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
550 { WM_GETTEXT
, sent
|optional
},
551 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
552 { WM_GETMINMAXINFO
, sent
|defwinproc
},
553 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
554 { WM_NCPAINT
, sent
|optional
},
555 { WM_GETTEXT
, sent
|defwinproc
|optional
},
556 { WM_ERASEBKGND
, sent
|optional
},
557 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
558 { WM_MOVE
, sent
|defwinproc
|optional
},
559 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
560 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
561 { WM_NCPAINT
, sent
|optional
},
562 { WM_ERASEBKGND
, sent
|optional
},
563 { WM_PAINT
, sent
|optional
},
564 { WM_GETTITLEBARINFOEX
, sent
|optional
},
565 { WM_NCPAINT
, sent
|beginpaint
|optional
},
566 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
567 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
568 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
569 { WM_SYNCPAINT
, sent
|optional
},
572 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
573 static const struct message WmShowRestoreMinOverlappedSeq
[] = {
574 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
575 { WM_QUERYOPEN
, sent
|optional
},
576 { WM_GETTEXT
, sent
|optional
},
577 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
578 { WM_WINDOWPOSCHANGING
, sent
|optional
}, /* SWP_NOSIZE|SWP_NOMOVE */
579 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
580 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
581 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
582 { WM_MOVE
, sent
|optional
},
583 { WM_SIZE
, sent
|wparam
|optional
, SIZE_RESTORED
},
584 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
585 { WM_GETTEXT
, sent
|optional
},
586 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
|SWP_NOCOPYBITS
},
587 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
},
588 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
589 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win10. */
590 { HCBT_ACTIVATE
, hook
|optional
},
591 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
592 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
593 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
594 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
595 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
596 { WM_GETTEXT
, sent
|defwinproc
|optional
},
597 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
598 { HCBT_SETFOCUS
, hook
|optional
},
599 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
600 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
601 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
602 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
603 { WM_GETTEXT
, sent
|optional
},
604 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
605 { WM_GETTEXT
, sent
|defwinproc
|optional
},
606 { WM_ERASEBKGND
, sent
},
607 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_STATECHANGED
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
},
608 { WM_MOVE
, sent
|defwinproc
},
609 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
610 { HCBT_SETFOCUS
, hook
|optional
},
611 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
612 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
613 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
614 { WM_ERASEBKGND
, sent
|optional
},
615 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
616 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
617 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
618 { HCBT_SETFOCUS
, hook
|optional
},
619 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
620 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
621 { WM_ACTIVATE
, sent
|wparam
, 1 },
622 { WM_GETTEXT
, sent
|optional
},
623 { WM_PAINT
, sent
|optional
},
624 { WM_GETTITLEBARINFOEX
, sent
|optional
},
625 { WM_NCPAINT
, sent
|beginpaint
|optional
},
626 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
629 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
630 static const struct message WmShowMinOverlappedSeq
[] = {
631 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
632 { HCBT_SETFOCUS
, hook
|optional
},
633 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
634 { WM_KILLFOCUS
, sent
|optional
},
635 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
636 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
637 { WM_GETTEXT
, sent
|optional
},
638 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCOPYBITS
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
639 { WM_GETMINMAXINFO
, sent
|defwinproc
},
640 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
641 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
642 { WM_NCPAINT
, sent
|optional
},
643 { WM_GETTEXT
, sent
|defwinproc
|optional
},
644 { WM_WINDOWPOSCHANGED
, sent
},
645 { WM_MOVE
, sent
|defwinproc
},
646 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
647 { WM_NCCALCSIZE
, sent
|optional
},
648 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
649 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
650 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
651 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
652 { WM_GETTEXT
, sent
|defwinproc
|optional
},
653 { WM_ACTIVATE
, sent
|optional
},
654 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
656 /* Vista sometimes restores the window right away... */
657 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
658 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
659 { HCBT_MINMAX
, hook
|optional
|lparam
, 0, SW_RESTORE
},
660 { WM_QUERYOPEN
, sent
|optional
},
661 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
662 { WM_GETMINMAXINFO
, sent
|optional
|defwinproc
},
663 { WM_NCCALCSIZE
, sent
|optional
|wparam
, TRUE
},
664 { HCBT_ACTIVATE
, hook
|optional
},
665 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 1 },
666 { WM_NCACTIVATE
, sent
|optional
},
667 { WM_GETTEXT
, sent
|optional
},
668 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
669 { HCBT_SETFOCUS
, hook
|optional
},
670 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
671 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
672 { WM_SETFOCUS
, sent
|optional
},
673 { WM_NCPAINT
, sent
|optional
},
674 { WM_GETTEXT
, sent
|defwinproc
|optional
},
675 { WM_ERASEBKGND
, sent
|optional
},
676 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
677 { WM_MOVE
, sent
|defwinproc
|optional
},
678 { WM_SIZE
, sent
|defwinproc
|optional
|wparam
, SIZE_RESTORED
},
679 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
680 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
681 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
683 { WM_PAINT
, sent
|optional
},
684 { WM_NCPAINT
, sent
|beginpaint
|optional
},
685 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
688 /* ShowWindow(SW_HIDE) for a visible overlapped window */
689 static const struct message WmHideOverlappedSeq
[] = {
690 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
691 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
692 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
693 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
694 { WM_SIZE
, sent
|optional
}, /* XP doesn't send it */
695 { WM_MOVE
, sent
|optional
}, /* XP doesn't send it */
696 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
697 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
698 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
699 { HCBT_SETFOCUS
, hook
|optional
},
700 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
701 { WM_KILLFOCUS
, sent
|wparam
|optional
, 0 },
702 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
703 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
706 /* DestroyWindow for a visible overlapped window */
707 static const struct message WmDestroyOverlappedSeq
[] = {
708 { HCBT_DESTROYWND
, hook
},
709 { 0x0090, sent
|optional
},
710 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
711 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
712 { 0x0090, sent
|optional
},
713 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
714 { WM_NCACTIVATE
, sent
|optional
|wparam
, 0 },
715 { WM_ACTIVATE
, sent
|optional
},
716 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 0 },
717 { WM_KILLFOCUS
, sent
|optional
|wparam
, 0 },
718 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
719 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
720 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
721 { WM_DESTROY
, sent
},
722 { WM_NCDESTROY
, sent
},
725 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
726 static const struct message WmCreateMaxPopupSeq
[] = {
727 { HCBT_CREATEWND
, hook
},
728 { WM_NCCREATE
, sent
},
729 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
731 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
732 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
734 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
735 { WM_GETMINMAXINFO
, sent
},
736 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
737 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
738 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
739 { WM_MOVE
, sent
|defwinproc
},
740 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
741 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
742 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
743 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
744 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
745 { HCBT_ACTIVATE
, hook
},
746 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
747 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
748 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
749 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
750 { WM_ERASEBKGND
, sent
|optional
},
751 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_NOMOVE
|SWP_NOSIZE
},
752 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
753 { WM_NCACTIVATE
, sent
},
754 { WM_ACTIVATE
, sent
|wparam
, 1 },
755 { HCBT_SETFOCUS
, hook
},
756 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
757 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
758 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
759 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
760 { WM_GETTEXT
, sent
|optional
},
761 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
762 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
763 { WM_ERASEBKGND
, sent
|optional
},
764 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
765 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
766 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
769 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
770 static const struct message WmCreateInvisibleMaxPopupSeq
[] = {
771 { HCBT_CREATEWND
, hook
},
772 { WM_NCCREATE
, sent
},
773 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
775 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
776 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
778 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
779 { WM_GETMINMAXINFO
, sent
},
780 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
781 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
782 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
783 { WM_MOVE
, sent
|defwinproc
},
784 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
785 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
788 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
789 static const struct message WmShowMaxPopupResizedSeq
[] = {
790 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
791 { WM_GETMINMAXINFO
, sent
},
792 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
793 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
794 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
795 { HCBT_ACTIVATE
, hook
},
796 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
797 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
798 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
799 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
800 { WM_ERASEBKGND
, sent
|optional
},
801 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
802 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
803 { WM_NCACTIVATE
, sent
},
804 { WM_ACTIVATE
, sent
|wparam
, 1 },
805 { HCBT_SETFOCUS
, hook
},
806 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
807 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
808 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
809 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
810 { WM_GETTEXT
, sent
|optional
},
811 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
812 { WM_ERASEBKGND
, sent
|optional
},
813 { WM_WINDOWPOSCHANGED
, sent
},
814 /* WinNT4.0 sends WM_MOVE */
815 { WM_MOVE
, sent
|defwinproc
|optional
},
816 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
817 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
820 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
821 static const struct message WmShowMaxPopupSeq
[] = {
822 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
823 { WM_GETMINMAXINFO
, sent
},
824 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
825 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
826 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
827 { HCBT_ACTIVATE
, hook
},
828 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
829 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
830 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
831 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
832 { WM_ERASEBKGND
, sent
|optional
},
833 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOMOVE
|SWP_NOSIZE
},
834 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
835 { WM_NCACTIVATE
, sent
},
836 { WM_ACTIVATE
, sent
|wparam
, 1 },
837 { HCBT_SETFOCUS
, hook
},
838 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
839 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
840 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
841 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
842 { WM_GETTEXT
, sent
|optional
},
843 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
844 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
845 { WM_ERASEBKGND
, sent
|optional
},
846 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
847 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
848 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
849 { WM_SIZE
, sent
|defwinproc
|optional
},
850 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
853 /* CreateWindow(WS_VISIBLE) for popup window */
854 static const struct message WmCreatePopupSeq
[] = {
855 { HCBT_CREATEWND
, hook
},
856 { WM_NCCREATE
, sent
},
857 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
859 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
860 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
862 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
863 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
864 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
865 { HCBT_ACTIVATE
, hook
},
866 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
867 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
868 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
869 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
870 { WM_ERASEBKGND
, sent
|optional
},
871 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
872 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
873 { WM_NCACTIVATE
, sent
},
874 { WM_ACTIVATE
, sent
|wparam
, 1 },
875 { HCBT_SETFOCUS
, hook
},
876 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
877 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
878 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
879 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
880 { WM_GETTEXT
, sent
|optional
},
881 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
882 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
883 { WM_ERASEBKGND
, sent
|optional
},
884 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
887 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
888 static const struct message WmShowVisMaxPopupSeq
[] = {
889 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
890 { WM_GETMINMAXINFO
, sent
},
891 { WM_GETTEXT
, sent
|optional
},
892 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
893 { WM_GETTEXT
, sent
|optional
},
894 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
895 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
896 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
897 { WM_ERASEBKGND
, sent
|optional
},
898 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
899 { WM_MOVE
, sent
|defwinproc
},
900 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
901 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
904 /* ShowWindow(hwnd, SW_RESTORE) to a minimized window */
905 static const struct message WmShowRestoreMinimizedOverlappedSeq
[] =
907 { HCBT_MINMAX
, hook
},
908 { WM_QUERYOPEN
, sent
},
909 { WM_GETTEXT
, sent
|optional
},
910 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
911 { WM_GETMINMAXINFO
, sent
|defwinproc
},
912 { WM_NCCALCSIZE
, sent
},
913 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
914 { HCBT_ACTIVATE
, hook
},
915 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
916 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
917 { WM_NCACTIVATE
, sent
},
918 { WM_GETTEXT
, sent
|defwinproc
|optional
},
919 { WM_ACTIVATE
, sent
|wparam
, WA_ACTIVE
},
920 { HCBT_SETFOCUS
, hook
},
921 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
922 { WM_SETFOCUS
, sent
|defwinproc
},
923 { WM_NCPAINT
, sent
},
924 { WM_GETTEXT
, sent
|defwinproc
|optional
},
925 { WM_GETTEXT
, sent
|defwinproc
|optional
},
926 { WM_ERASEBKGND
, sent
},
927 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
928 { WM_MOVE
, sent
|defwinproc
},
929 { WM_SIZE
, sent
|defwinproc
},
930 { WM_NCCALCSIZE
, sent
|optional
},
931 { WM_NCPAINT
, sent
|optional
},
932 { WM_ERASEBKGND
, sent
|optional
},
933 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
934 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
935 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
936 /* Note this WM_ACTIVATE message even if the window is already active and focused */
937 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
938 { WM_SYNCPAINT
, sent
|optional
},
940 { WM_GETMINMAXINFO
, sent
|optional
},
943 /* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to a minimized window */
944 static const struct message WmShowNoActivateMinimizedOverlappedSeq
[] =
946 { HCBT_MINMAX
, hook
},
947 { WM_QUERYOPEN
, sent
},
948 { WM_GETTEXT
, sent
|optional
},
949 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
950 { WM_GETMINMAXINFO
, sent
|defwinproc
},
951 { WM_NCCALCSIZE
, sent
},
952 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
953 { WM_NCPAINT
, sent
},
954 { WM_GETTEXT
, sent
|defwinproc
|optional
},
955 { WM_ERASEBKGND
, sent
},
956 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
957 { WM_MOVE
, sent
|defwinproc
},
958 { WM_SIZE
, sent
|defwinproc
},
959 /* Following optional messages are on XP/2003 */
960 { WM_NCCALCSIZE
, sent
|optional
},
961 { WM_NCPAINT
, sent
|optional
},
962 { WM_ERASEBKGND
, sent
|optional
},
963 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
964 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
965 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
966 { HCBT_SETFOCUS
, hook
|optional
},
967 { WM_SETFOCUS
, sent
|optional
},
968 { HCBT_ACTIVATE
, hook
|optional
},
969 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
970 { WM_NCACTIVATE
, sent
|optional
},
971 { WM_GETTEXT
, sent
|defwinproc
|optional
},
972 { WM_ACTIVATE
, sent
|wparam
|optional
, WA_ACTIVE
},
973 { HCBT_SETFOCUS
, hook
|optional
},
974 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
975 { WM_KILLFOCUS
, sent
|optional
},
976 { WM_SETFOCUS
, sent
|optional
},
977 /* Note this WM_ACTIVATE message on XP even if the window is already active and focused */
978 { WM_ACTIVATE
, sent
|wparam
|lparam
|optional
, WA_ACTIVE
, 0 },
979 { WM_SYNCPAINT
, sent
|optional
},
981 { WM_GETMINMAXINFO
, sent
|optional
},
984 /* ShowWindow(hwnd, SW_RESTORE) to an active minimized window */
985 static const struct message WmShowRestoreActiveMinimizedOverlappedSeq
[] =
987 { HCBT_MINMAX
, hook
},
988 { WM_QUERYOPEN
, sent
},
989 { WM_GETTEXT
, sent
|optional
},
990 { WM_NCACTIVATE
, sent
},
991 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
992 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
993 { WM_NCCALCSIZE
, sent
|optional
},
994 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
995 { WM_MOVE
, sent
|optional
},
996 { WM_SIZE
, sent
|optional
},
997 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
998 { WM_GETTEXT
, sent
|optional
},
999 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1000 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1001 { WM_NCCALCSIZE
, sent
},
1002 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win8+ sends this. */
1003 { WM_NCPAINT
, sent
},
1004 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1005 { WM_ERASEBKGND
, sent
},
1006 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1007 { WM_MOVE
, sent
|defwinproc
},
1008 { WM_SIZE
, sent
|defwinproc
},
1009 { WM_NCCALCSIZE
, sent
|optional
},
1010 { WM_NCPAINT
, sent
|optional
},
1011 { WM_ERASEBKGND
, sent
|optional
},
1012 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1013 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1014 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1015 { HCBT_SETFOCUS
, hook
},
1016 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1017 { WM_SETFOCUS
, sent
},
1018 /* Note this WM_ACTIVATE message even if the window is already active */
1019 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
1020 { WM_SYNCPAINT
, sent
|optional
},
1022 { WM_GETMINMAXINFO
, sent
|optional
},
1025 /* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to an active minimized window */
1026 static const struct message WmShowNoActivateActiveMinimizedOverlappedSeq
[] =
1028 { HCBT_MINMAX
, hook
},
1029 { WM_QUERYOPEN
, sent
},
1030 { WM_GETTEXT
, sent
|optional
},
1031 { WM_NCACTIVATE
, sent
},
1032 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1033 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1034 { WM_NCCALCSIZE
, sent
|optional
},
1035 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1036 { WM_MOVE
, sent
|optional
},
1037 { WM_SIZE
, sent
|optional
},
1038 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1039 { WM_GETTEXT
, sent
|optional
},
1040 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1041 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1042 { WM_NCCALCSIZE
, sent
},
1043 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win8+ sends this. */
1044 { WM_NCPAINT
, sent
},
1045 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1046 { WM_ERASEBKGND
, sent
},
1047 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1048 { WM_MOVE
, sent
|defwinproc
},
1049 { WM_SIZE
, sent
|defwinproc
},
1050 { WM_NCCALCSIZE
, sent
|optional
},
1051 { WM_NCPAINT
, sent
|optional
},
1052 { WM_ERASEBKGND
, sent
|optional
},
1053 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1054 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1055 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1056 /* Following optional messages are present on XP */
1057 { HCBT_SETFOCUS
, hook
|optional
},
1058 { WM_SETFOCUS
, sent
|optional
},
1059 /* Note this WM_ACTIVATE message even if the window is already active and with flag SW_SHOWNOACTIVATE */
1060 { WM_ACTIVATE
, sent
|wparam
|lparam
|optional
, WA_ACTIVE
, 0 },
1061 { WM_SYNCPAINT
, sent
|optional
},
1063 { WM_GETMINMAXINFO
, sent
|optional
},
1066 /* CreateWindow (for a child popup window, not initially visible) */
1067 static const struct message WmCreateChildPopupSeq
[] = {
1068 { HCBT_CREATEWND
, hook
},
1069 { WM_NCCREATE
, sent
},
1070 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1071 { WM_CREATE
, sent
},
1072 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1073 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1077 /* CreateWindow (for a popup window, not initially visible,
1078 * which sets WS_VISIBLE in WM_CREATE handler)
1080 static const struct message WmCreateInvisiblePopupSeq
[] = {
1081 { HCBT_CREATEWND
, hook
},
1082 { WM_NCCREATE
, sent
},
1083 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1084 { WM_CREATE
, sent
},
1085 { WM_STYLECHANGING
, sent
},
1086 { WM_STYLECHANGED
, sent
},
1087 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1088 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1092 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
1093 * for a popup window with WS_VISIBLE style set
1095 static const struct message WmShowVisiblePopupSeq_2
[] = {
1096 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1099 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1100 * for a popup window with WS_VISIBLE style set
1102 static const struct message WmShowVisiblePopupSeq_3
[] = {
1103 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1104 { HCBT_ACTIVATE
, hook
},
1105 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1106 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1107 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1108 { WM_NCACTIVATE
, sent
},
1109 { WM_ACTIVATE
, sent
|wparam
, 1 },
1110 { HCBT_SETFOCUS
, hook
},
1111 { WM_KILLFOCUS
, sent
|parent
},
1112 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1113 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1114 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1115 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1116 { WM_SETFOCUS
, sent
|defwinproc
},
1117 { WM_GETTEXT
, sent
|optional
},
1118 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_SHOWWINDOW
},
1121 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
1123 static const struct message WmShowPopupExtremeLocationSeq
[] = {
1124 { HCBT_CREATEWND
, hook
},
1125 { WM_NCCREATE
, sent
},
1126 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1127 { WM_CREATE
, sent
},
1128 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1129 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1131 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1132 { WM_WINDOWPOSCHANGING
, sent
},
1133 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1134 { HCBT_ACTIVATE
, hook
},
1135 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1136 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1137 { WM_QUERYNEWPALETTE
, sent
|optional
},
1139 /* occasionally received on test machines */
1140 { WM_NCPAINT
, sent
|optional
},
1141 { WM_ERASEBKGND
, sent
|optional
},
1142 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1144 { WM_ACTIVATEAPP
, sent
},
1145 { WM_NCACTIVATE
, sent
},
1146 { WM_ACTIVATE
, sent
},
1147 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1148 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1149 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1150 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1151 { HCBT_SETFOCUS
, hook
},
1152 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1153 { WM_SETFOCUS
, sent
|defwinproc
},
1154 { WM_NCPAINT
, sent
|wparam
|optional
, 1 }, /* Not always sent on Win8+ */
1155 { WM_ERASEBKGND
, sent
|optional
}, /* Not always sent on Win8+ */
1156 { WM_WINDOWPOSCHANGED
, sent
},
1157 /* occasionally received on test machines */
1158 { WM_NCPAINT
, sent
|optional
},
1159 { WM_ERASEBKGND
, sent
|optional
},
1162 /* CreateWindow (for a popup window with WS_VISIBLE style set)
1164 static const struct message WmShowPopupFirstDrawSeq_1
[] = {
1165 { HCBT_CREATEWND
, hook
},
1166 { WM_NCCREATE
, sent
},
1167 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1168 { WM_CREATE
, sent
},
1169 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1170 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1172 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1173 { WM_WINDOWPOSCHANGING
, sent
},
1174 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1175 { HCBT_ACTIVATE
, hook
},
1176 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1177 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1178 { WM_QUERYNEWPALETTE
, sent
|optional
},
1179 { WM_ACTIVATEAPP
, sent
},
1180 { WM_NCACTIVATE
, sent
},
1181 { WM_ACTIVATE
, sent
},
1182 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1183 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1184 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1185 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1186 { HCBT_SETFOCUS
, hook
},
1187 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1188 { WM_SETFOCUS
, sent
|defwinproc
},
1189 { WM_NCPAINT
, sent
|wparam
, 1 },
1190 { WM_ERASEBKGND
, sent
},
1191 { WM_WINDOWPOSCHANGED
, sent
},
1193 /* occasionally received on test machines */
1194 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1195 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1198 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1200 static const struct message WmShowPopupFirstDrawSeq_2
[] = {
1201 { HCBT_CREATEWND
, hook
},
1202 { WM_NCCREATE
, sent
},
1203 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1204 { WM_CREATE
, sent
},
1205 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1206 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1208 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1209 { WM_GETMINMAXINFO
, sent
},
1210 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_STATECHANGED
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
1211 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
1212 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1213 { HCBT_ACTIVATE
, hook
},
1214 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1215 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1216 { WM_NCPAINT
, sent
|optional
|wparam
, 1 },
1217 { WM_ERASEBKGND
, sent
|optional
},
1218 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1219 { WM_QUERYNEWPALETTE
, sent
|optional
},
1220 { WM_ACTIVATEAPP
, sent
},
1221 { WM_NCACTIVATE
, sent
},
1222 { WM_ACTIVATE
, sent
},
1223 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1224 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1225 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1226 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1227 { HCBT_SETFOCUS
, hook
},
1228 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1229 { WM_SETFOCUS
, sent
|defwinproc
},
1230 { WM_NCPAINT
, sent
|wparam
, 1 },
1231 { WM_ERASEBKGND
, sent
},
1232 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1233 { WM_MOVE
, sent
|defwinproc
},
1234 { WM_SIZE
, sent
|defwinproc
, 0 },
1235 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1237 /* occasionally received on test machines */
1238 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1239 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1242 static const struct message WmFirstDrawSetWindowPosSeq1
[] = {
1243 { HCBT_CREATEWND
, hook
},
1244 { WM_NCCREATE
, sent
},
1245 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1246 { WM_CREATE
, sent
},
1247 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1248 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1250 { WM_WINDOWPOSCHANGING
, sent
},
1251 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1252 { HCBT_ACTIVATE
, hook
},
1253 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1254 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1255 { WM_QUERYNEWPALETTE
, sent
|optional
},
1256 { WM_ACTIVATEAPP
, sent
},
1257 { WM_NCACTIVATE
, sent
},
1258 { WM_ACTIVATE
, sent
},
1259 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1260 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1261 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1262 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1263 { HCBT_SETFOCUS
, hook
},
1264 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1265 { WM_SETFOCUS
, sent
|defwinproc
},
1266 { WM_NCPAINT
, sent
|wparam
, 1 },
1267 { WM_ERASEBKGND
, sent
},
1268 { WM_WINDOWPOSCHANGED
, sent
},
1269 { WM_MOVE
, sent
|defwinproc
},
1270 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1273 static const struct message WmFirstDrawSetWindowPosSeq2
[] = {
1274 { HCBT_CREATEWND
, hook
},
1275 { WM_NCCREATE
, sent
},
1276 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1277 { WM_CREATE
, sent
},
1278 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1279 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1281 { WM_WINDOWPOSCHANGING
, sent
},
1282 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not always sent. */
1283 { HCBT_ACTIVATE
, hook
},
1284 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1285 { WM_QUERYNEWPALETTE
, sent
|optional
},
1286 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1287 { WM_ACTIVATEAPP
, sent
},
1288 { WM_NCACTIVATE
, sent
},
1289 { WM_ACTIVATE
, sent
},
1290 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1291 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1292 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1293 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1294 { HCBT_SETFOCUS
, hook
},
1295 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1296 { WM_SETFOCUS
, sent
|defwinproc
},
1297 { WM_WINDOWPOSCHANGED
, sent
},
1298 { WM_MOVE
, sent
|defwinproc
},
1299 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1302 static const struct message WmFirstDrawSetWindowPosSeq3
[] = {
1303 { HCBT_CREATEWND
, hook
},
1304 { WM_NCCREATE
, sent
},
1305 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1306 { WM_CREATE
, sent
},
1307 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1308 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1310 { HCBT_ACTIVATE
, hook
|optional
},
1311 /* Probably shouldn't happen, but not part of this test */
1312 { WM_QUERYNEWPALETTE
, sent
|optional
},
1313 { WM_ACTIVATEAPP
, sent
|optional
},
1314 { WM_NCACTIVATE
, sent
|optional
},
1315 { WM_ACTIVATE
, sent
|optional
},
1316 { HCBT_SETFOCUS
, hook
|optional
},
1317 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
1320 static const struct message WmFirstDrawSetWindowPosSeq4
[] = {
1321 { HCBT_CREATEWND
, hook
},
1322 { WM_NCCREATE
, sent
},
1323 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1324 { WM_CREATE
, sent
},
1325 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1326 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1328 { WM_WINDOWPOSCHANGING
, sent
},
1329 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1330 { HCBT_ACTIVATE
, hook
},
1331 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1332 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1333 { WM_QUERYNEWPALETTE
, sent
|optional
},
1334 { WM_ACTIVATEAPP
, sent
},
1335 { WM_NCACTIVATE
, sent
},
1336 { WM_ACTIVATE
, sent
},
1337 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1338 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1339 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1340 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1341 { HCBT_SETFOCUS
, hook
},
1342 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1343 { WM_SETFOCUS
, sent
|defwinproc
},
1344 { WM_NCPAINT
, sent
|wparam
, 1 },
1345 { WM_ERASEBKGND
, sent
},
1346 { WM_WINDOWPOSCHANGED
, sent
},
1349 static const struct message WmFirstDrawSetWindowPosSeq5
[] = {
1350 { HCBT_CREATEWND
, hook
},
1351 { WM_NCCREATE
, sent
},
1352 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1353 { WM_CREATE
, sent
},
1354 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1355 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1357 { WM_WINDOWPOSCHANGING
, sent
},
1358 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1359 { HCBT_ACTIVATE
, hook
},
1360 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1361 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1362 { WM_QUERYNEWPALETTE
, sent
|optional
},
1363 { WM_ACTIVATEAPP
, sent
},
1364 { WM_NCACTIVATE
, sent
},
1365 { WM_ACTIVATE
, sent
},
1366 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1367 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1368 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1369 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1370 { HCBT_SETFOCUS
, hook
},
1371 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
1372 { WM_SETFOCUS
, sent
|defwinproc
},
1373 { WM_WINDOWPOSCHANGED
, sent
},
1376 static const struct message WmFirstDrawChildSeq1
[] = {
1377 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1378 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1381 static const struct message WmFirstDrawChildSeq2
[] = {
1382 { WM_NCPAINT
, sent
|wparam
, 1 },
1383 { WM_ERASEBKGND
, sent
},
1384 /* occasionally received on test machines */
1385 { WM_NCPAINT
, sent
|optional
},
1386 { WM_ERASEBKGND
, sent
|optional
},
1387 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1388 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1391 /* CreateWindow (for child window, not initially visible) */
1392 static const struct message WmCreateChildSeq
[] = {
1393 { HCBT_CREATEWND
, hook
},
1394 { WM_NCCREATE
, sent
},
1395 /* child is inserted into parent's child list after WM_NCCREATE returns */
1396 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1397 { WM_CREATE
, sent
},
1398 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1399 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1401 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1404 /* CreateWindow (for maximized child window, not initially visible) */
1405 static const struct message WmCreateMaximizedChildSeq
[] = {
1406 { HCBT_CREATEWND
, hook
},
1407 { WM_NCCREATE
, sent
},
1408 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1409 { WM_CREATE
, sent
},
1410 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1411 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1413 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1414 { WM_GETMINMAXINFO
, sent
},
1415 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
1416 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1417 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1418 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1419 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1420 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1423 /* CreateWindow (for a child window, initially visible) */
1424 static const struct message WmCreateVisibleChildSeq
[] = {
1425 { HCBT_CREATEWND
, hook
},
1426 { WM_NCCREATE
, sent
},
1427 /* child is inserted into parent's child list after WM_NCCREATE returns */
1428 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1429 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1430 { WM_CREATE
, sent
},
1431 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1432 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1434 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1435 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1436 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1437 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1438 { WM_ERASEBKGND
, sent
|parent
|optional
},
1439 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1440 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
1441 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1444 /* ShowWindow(SW_SHOW) for a not visible child window */
1445 static const struct message WmShowChildSeq
[] = {
1446 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1447 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1448 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1449 { WM_ERASEBKGND
, sent
|parent
|optional
},
1450 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1453 /* ShowWindow(SW_HIDE) for a visible child window */
1454 static const struct message WmHideChildSeq
[] = {
1455 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1456 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1457 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1458 { WM_ERASEBKGND
, sent
|parent
|optional
},
1459 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1462 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1463 static const struct message WmHideChildSeq2
[] = {
1464 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1465 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1466 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1467 { WM_ERASEBKGND
, sent
|parent
|optional
},
1468 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1471 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1472 * for a not visible child window
1474 static const struct message WmShowChildSeq_2
[] = {
1475 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1476 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1477 { WM_CHILDACTIVATE
, sent
},
1478 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1481 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1482 * for a not visible child window
1484 static const struct message WmShowChildSeq_3
[] = {
1485 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1486 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1487 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1490 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1491 * for a visible child window with a caption
1493 static const struct message WmShowChildSeq_4
[] = {
1494 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1495 { WM_CHILDACTIVATE
, sent
},
1498 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1499 static const struct message WmShowChildInvisibleParentSeq_1
[] = {
1500 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1501 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1502 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1503 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1504 { WM_CHILDACTIVATE
, sent
|optional
},
1505 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1506 { WM_MOVE
, sent
|defwinproc
},
1507 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1508 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1509 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1510 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1511 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1512 { WM_GETTEXT
, sent
|optional
},
1515 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1516 static const struct message WmShowChildInvisibleParentSeq_1r
[] = {
1517 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1520 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1521 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
1522 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1523 { WM_GETMINMAXINFO
, sent
},
1524 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
1525 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1526 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1527 { WM_CHILDACTIVATE
, sent
},
1528 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1529 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1530 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1533 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1534 static const struct message WmShowChildInvisibleParentSeq_2r
[] = {
1535 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1538 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1539 static const struct message WmShowChildInvisibleParentSeq_3
[] = {
1540 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1541 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1542 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1543 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1544 { WM_CHILDACTIVATE
, sent
},
1545 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1546 { WM_MOVE
, sent
|defwinproc
},
1547 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1548 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1549 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1550 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1551 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1552 { WM_GETTEXT
, sent
|optional
},
1555 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1556 static const struct message WmShowChildInvisibleParentSeq_3r
[] = {
1557 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1560 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1561 static const struct message WmShowChildInvisibleParentSeq_4
[] = {
1562 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1563 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1564 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1565 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1566 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1567 { WM_MOVE
, sent
|defwinproc
},
1568 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1569 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1570 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1571 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1572 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1573 { WM_GETTEXT
, sent
|optional
},
1576 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1577 static const struct message WmShowChildInvisibleParentSeq_4r
[] = {
1578 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1581 /* ShowWindow(SW_SHOW) for child with invisible parent */
1582 static const struct message WmShowChildInvisibleParentSeq_5
[] = {
1583 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1586 /* ShowWindow(SW_HIDE) for child with invisible parent */
1587 static const struct message WmHideChildInvisibleParentSeq
[] = {
1588 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1591 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1592 static const struct message WmShowChildInvisibleParentSeq_6
[] = {
1593 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1594 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1595 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1598 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1599 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
1600 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1601 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1602 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1605 /* DestroyWindow for a visible child window */
1606 static const struct message WmDestroyChildSeq
[] = {
1607 { HCBT_DESTROYWND
, hook
},
1608 { 0x0090, sent
|optional
},
1609 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1610 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1611 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1612 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1613 { WM_ERASEBKGND
, sent
|parent
|optional
},
1614 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1615 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
1616 { WM_KILLFOCUS
, sent
},
1617 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1618 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
1619 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1620 { WM_SETFOCUS
, sent
|parent
},
1621 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1622 { WM_DESTROY
, sent
},
1623 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
1624 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
1625 { WM_NCDESTROY
, sent
},
1628 /* visible child window destroyed by thread exit */
1629 static const struct message WmExitThreadSeq
[] = {
1630 { WM_NCDESTROY
, sent
}, /* actually in grandchild */
1631 { WM_PAINT
, sent
|parent
},
1632 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
1635 /* DestroyWindow for a visible child window with invisible parent */
1636 static const struct message WmDestroyInvisibleChildSeq
[] = {
1637 { HCBT_DESTROYWND
, hook
},
1638 { 0x0090, sent
|optional
},
1639 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1640 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1641 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1642 { WM_DESTROY
, sent
},
1643 { WM_NCDESTROY
, sent
},
1646 /* Resizing child window with MoveWindow (32) */
1647 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1648 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1649 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1650 { WM_ERASEBKGND
, sent
|parent
|optional
},
1651 { WM_ERASEBKGND
, sent
|optional
},
1652 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1653 { WM_MOVE
, sent
|defwinproc
},
1654 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1655 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1658 /* Creation of a custom dialog (32) */
1659 static const struct message WmCreateCustomDialogSeq
[] = {
1660 { HCBT_CREATEWND
, hook
},
1661 { WM_GETMINMAXINFO
, sent
},
1662 { WM_NCCREATE
, sent
},
1663 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1664 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1665 { WM_CREATE
, sent
},
1666 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1667 { WM_NOTIFYFORMAT
, sent
|optional
},
1668 { WM_QUERYUISTATE
, sent
|optional
},
1669 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1670 { WM_GETMINMAXINFO
, sent
|optional
},
1671 { WM_NCCALCSIZE
, sent
|optional
},
1672 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1673 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1674 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1675 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1676 { HCBT_ACTIVATE
, hook
},
1677 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1680 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1682 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1684 { WM_NCACTIVATE
, sent
},
1685 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1686 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1687 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1688 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1689 { WM_ACTIVATE
, sent
|wparam
, 1 },
1690 { WM_GETTEXT
, sent
|optional
},
1691 { WM_KILLFOCUS
, sent
|parent
},
1692 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1693 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1694 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1695 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1696 { WM_SETFOCUS
, sent
},
1697 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1698 { WM_NCPAINT
, sent
|wparam
, 1 },
1699 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1700 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1701 { WM_ERASEBKGND
, sent
},
1702 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1703 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1704 { WM_GETTEXT
, sent
|optional
},
1705 { WM_GETTEXT
, sent
|optional
},
1706 { WM_NCCALCSIZE
, sent
|optional
},
1707 { WM_NCPAINT
, sent
|optional
},
1708 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1709 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1710 { WM_ERASEBKGND
, sent
|optional
},
1711 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1712 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1713 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1717 /* Calling EndDialog for a custom dialog (32) */
1718 static const struct message WmEndCustomDialogSeq
[] = {
1719 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1720 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1721 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1722 { WM_GETTEXT
, sent
|optional
},
1723 { HCBT_ACTIVATE
, hook
},
1724 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1725 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1726 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1727 { WM_ACTIVATE
, sent
|wparam
, 0 },
1728 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1729 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1730 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1731 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1732 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1733 { HCBT_SETFOCUS
, hook
},
1734 { WM_KILLFOCUS
, sent
},
1735 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1736 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1737 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1738 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1739 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1742 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1743 static const struct message WmShowCustomDialogSeq
[] = {
1744 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1745 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1746 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1747 { HCBT_ACTIVATE
, hook
},
1748 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1750 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1752 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1753 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1754 { WM_NCACTIVATE
, sent
},
1755 { WM_ACTIVATE
, sent
|wparam
, 1 },
1756 { WM_GETTEXT
, sent
|optional
},
1758 { WM_KILLFOCUS
, sent
|parent
},
1759 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1760 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1761 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1762 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1763 { WM_SETFOCUS
, sent
},
1764 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1765 { WM_NCPAINT
, sent
|wparam
, 1 },
1766 { WM_ERASEBKGND
, sent
},
1767 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1768 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1771 /* Creation and destruction of a modal dialog (32) */
1772 static const struct message WmModalDialogSeq
[] = {
1773 { WM_CANCELMODE
, sent
|parent
},
1774 { HCBT_SETFOCUS
, hook
},
1775 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1776 { WM_KILLFOCUS
, sent
|parent
},
1777 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1778 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1779 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1780 { HCBT_CREATEWND
, hook
},
1781 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1782 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1783 { WM_SETFONT
, sent
},
1784 { WM_INITDIALOG
, sent
},
1785 { WM_CHANGEUISTATE
, sent
|optional
},
1786 { WM_UPDATEUISTATE
, sent
|optional
},
1787 { WM_SHOWWINDOW
, sent
},
1788 { HCBT_ACTIVATE
, hook
},
1789 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1790 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1791 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1792 { WM_NCACTIVATE
, sent
},
1793 { WM_GETTEXT
, sent
|optional
},
1794 { WM_ACTIVATE
, sent
|wparam
, 1 },
1795 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1796 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1797 { WM_NCPAINT
, sent
|optional
},
1798 { WM_GETTEXT
, sent
|optional
},
1799 { WM_ERASEBKGND
, sent
|optional
},
1800 { WM_CTLCOLORDLG
, sent
|optional
},
1801 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1802 { WM_GETTEXT
, sent
|optional
},
1803 { WM_NCCALCSIZE
, sent
|optional
},
1804 { WM_NCPAINT
, sent
|optional
},
1805 { WM_GETTEXT
, sent
|optional
},
1806 { WM_ERASEBKGND
, sent
|optional
},
1807 { WM_CTLCOLORDLG
, sent
|optional
},
1808 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1809 { WM_PAINT
, sent
|optional
},
1810 { WM_CTLCOLORBTN
, sent
|optional
},
1811 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1812 { WM_ENTERIDLE
, sent
|parent
|optional
},
1813 { WM_ENTERIDLE
, sent
|parent
|optional
},
1814 { WM_ENTERIDLE
, sent
|parent
|optional
},
1815 { WM_ENTERIDLE
, sent
|parent
|optional
},
1816 { WM_ENTERIDLE
, sent
|parent
|optional
},
1817 { WM_ENTERIDLE
, sent
|parent
|optional
},
1818 { WM_ENTERIDLE
, sent
|parent
|optional
},
1819 { WM_ENTERIDLE
, sent
|parent
|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
},
1833 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1834 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1835 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1836 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1837 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1838 { WM_GETTEXT
, sent
|optional
},
1839 { HCBT_ACTIVATE
, hook
},
1840 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1841 { WM_GETTEXT
, sent
|optional
},
1842 { WM_ACTIVATE
, sent
|wparam
, 0 },
1843 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1844 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1845 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1846 { HCBT_SETFOCUS
, hook
},
1847 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1848 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1849 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1850 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1851 { HCBT_DESTROYWND
, hook
},
1852 { 0x0090, sent
|optional
},
1853 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1854 { WM_DESTROY
, sent
},
1855 { WM_NCDESTROY
, sent
},
1858 static const struct message WmModalDialogSeq_2
[] = {
1859 { WM_CANCELMODE
, sent
},
1860 { HCBT_SETFOCUS
, hook
},
1861 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1862 { WM_KILLFOCUS
, sent
},
1863 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1864 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1865 { WM_ENABLE
, sent
|wparam
, 0 },
1866 { HCBT_CREATEWND
, hook
},
1867 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
1868 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1869 { WM_SETFONT
, sent
},
1870 { WM_INITDIALOG
, sent
},
1871 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1872 { WM_CHANGEUISTATE
, sent
|optional
},
1873 { WM_UPDATEUISTATE
, sent
|optional
},
1874 { WM_ENABLE
, sent
|wparam
, 1 },
1875 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1876 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
1877 { WM_CHANGEUISTATE
, sent
|optional
},
1878 { WM_UPDATEUISTATE
, sent
|optional
},
1879 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1880 { HCBT_DESTROYWND
, hook
},
1881 { 0x0090, sent
|optional
},
1882 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1883 { WM_DESTROY
, sent
},
1884 { WM_NCDESTROY
, sent
},
1887 /* SetMenu for NonVisible windows with size change*/
1888 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1889 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1890 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1891 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1892 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1893 { WM_MOVE
, sent
|defwinproc
},
1894 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1895 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1896 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1897 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1898 { WM_GETTEXT
, sent
|optional
},
1899 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1902 /* SetMenu for NonVisible windows with no size change */
1903 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1904 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1905 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1906 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1907 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1910 /* SetMenu for Visible windows with size change */
1911 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1912 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1913 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1914 { 0x0093, sent
|defwinproc
|optional
},
1915 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1916 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1917 { 0x0093, sent
|defwinproc
|optional
},
1918 { 0x0093, sent
|defwinproc
|optional
},
1919 { 0x0091, sent
|defwinproc
|optional
},
1920 { 0x0092, sent
|defwinproc
|optional
},
1921 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1922 { WM_ERASEBKGND
, sent
|optional
},
1923 { WM_ACTIVATE
, sent
|optional
},
1924 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1925 { WM_MOVE
, sent
|defwinproc
},
1926 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1927 { 0x0093, sent
|optional
},
1928 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1929 { 0x0093, sent
|defwinproc
|optional
},
1930 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1931 { 0x0093, sent
|defwinproc
|optional
},
1932 { 0x0093, sent
|defwinproc
|optional
},
1933 { 0x0091, sent
|defwinproc
|optional
},
1934 { 0x0092, sent
|defwinproc
|optional
},
1935 { WM_ERASEBKGND
, sent
|optional
},
1936 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1937 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1940 /* SetMenu for Visible windows with no size change */
1941 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1942 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1943 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1944 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1945 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1946 { WM_ERASEBKGND
, sent
|optional
},
1947 { WM_ACTIVATE
, sent
|optional
},
1948 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1949 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1952 /* DrawMenuBar for a visible window */
1953 static const struct message WmDrawMenuBarSeq
[] =
1955 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1956 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1957 { 0x0093, sent
|defwinproc
|optional
},
1958 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1959 { 0x0093, sent
|defwinproc
|optional
},
1960 { 0x0093, sent
|defwinproc
|optional
},
1961 { 0x0091, sent
|defwinproc
|optional
},
1962 { 0x0092, sent
|defwinproc
|optional
},
1963 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1964 { WM_ERASEBKGND
, sent
|optional
},
1965 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1966 { 0x0093, sent
|optional
},
1967 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1971 static const struct message WmSetRedrawFalseSeq
[] =
1973 { WM_SETREDRAW
, sent
|wparam
, 0 },
1977 static const struct message WmSetRedrawTrueSeq
[] =
1979 { WM_SETREDRAW
, sent
|wparam
, 1 },
1983 static const struct message WmEnableWindowSeq_1
[] =
1985 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1986 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
1987 { HCBT_SETFOCUS
, hook
|optional
},
1988 { WM_KILLFOCUS
, sent
|optional
},
1989 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
1993 static const struct message WmEnableWindowSeq_2
[] =
1995 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1996 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
2000 static const struct message WmEnableWindowSeq_3
[] =
2002 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2003 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
2007 static const struct message WmEnableWindowSeq_4
[] =
2009 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
2013 static const struct message WmGetScrollRangeSeq
[] =
2015 { SBM_GETRANGE
, sent
},
2018 static const struct message WmGetScrollInfoSeq
[] =
2020 { SBM_GETSCROLLINFO
, sent
},
2023 static const struct message WmSetScrollRangeSeq
[] =
2025 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
2026 sends SBM_SETSCROLLINFO.
2028 { SBM_SETSCROLLINFO
, sent
},
2031 /* SetScrollRange for a window without a non-client area */
2032 static const struct message WmSetScrollRangeHSeq_empty
[] =
2034 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_HSCROLL
, 0 },
2037 static const struct message WmSetScrollRangeVSeq_empty
[] =
2039 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_VSCROLL
, 0 },
2042 static const struct message WmSetScrollRangeHVSeq
[] =
2044 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
2045 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2046 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2047 { WM_ERASEBKGND
, sent
|optional
},
2048 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2049 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2050 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2053 /* SetScrollRange for a window with a non-client area */
2054 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
2056 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
2057 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2058 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2059 { WM_NCPAINT
, sent
|optional
},
2060 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2061 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2062 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2063 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2064 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2065 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2066 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2067 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2068 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2069 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2070 { WM_ERASEBKGND
, sent
|optional
},
2071 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
2072 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
2073 { WM_SIZE
, sent
|defwinproc
|optional
},
2074 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2075 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2076 { WM_GETTEXT
, sent
|optional
},
2077 { WM_GETTEXT
, sent
|optional
},
2078 { WM_GETTEXT
, sent
|optional
},
2079 { WM_GETTEXT
, sent
|optional
},
2082 /* test if we receive the right sequence of messages */
2083 /* after calling ShowWindow( SW_SHOWNA) */
2084 static const struct message WmSHOWNAChildInvisParInvis
[] = {
2085 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2088 static const struct message WmSHOWNAChildVisParInvis
[] = {
2089 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2092 static const struct message WmSHOWNAChildVisParVis
[] = {
2093 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2094 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
2097 static const struct message WmSHOWNAChildInvisParVis
[] = {
2098 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2099 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2100 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2101 { WM_ERASEBKGND
, sent
|optional
},
2102 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
2105 static const struct message WmSHOWNATopVisible
[] = {
2106 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2107 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
2108 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2109 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2110 { WM_ERASEBKGND
, sent
|optional
},
2111 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2114 static const struct message WmSHOWNATopInvisible
[] = {
2115 { WM_NOTIFYFORMAT
, sent
|optional
},
2116 { WM_QUERYUISTATE
, sent
|optional
},
2117 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2118 { WM_GETMINMAXINFO
, sent
|optional
},
2119 { WM_NCCALCSIZE
, sent
|optional
},
2120 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2121 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2122 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2123 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2124 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2125 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2126 { WM_ERASEBKGND
, sent
|optional
},
2127 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2128 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2129 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2130 { WM_ERASEBKGND
, sent
|optional
},
2131 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
2132 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2137 static const struct message WmTrackPopupMenuMinimizeWindow
[] = {
2138 { HCBT_CREATEWND
, hook
},
2139 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2140 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2141 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2142 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2143 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2144 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2145 { 0x0093, sent
|optional
},
2146 { 0x0094, sent
|optional
},
2147 { 0x0094, sent
|optional
},
2148 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2149 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2150 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2151 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2152 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2153 { HCBT_MINMAX
, hook
},
2154 { HCBT_SETFOCUS
, hook
},
2155 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2156 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2157 { WM_GETTEXT
, sent
|optional
},
2158 { WM_WINDOWPOSCHANGING
, sent
},
2159 { WM_GETMINMAXINFO
, sent
|defwinproc
},
2160 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2161 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2162 { WM_WINDOWPOSCHANGED
, sent
},
2163 { WM_MOVE
, sent
|defwinproc
},
2164 { WM_SIZE
, sent
|defwinproc
},
2165 { WM_GETTEXT
, sent
|optional
},
2166 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2167 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2168 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
2169 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2170 { WM_CANCELMODE
, sent
},
2171 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2172 { WM_CAPTURECHANGED
, sent
|defwinproc
},
2173 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2174 { HCBT_DESTROYWND
, hook
},
2175 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2176 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2177 { WM_UNINITMENUPOPUP
, sent
|defwinproc
|lparam
, 0, 0 },
2178 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
2179 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2180 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 1, 0 },
2181 { WM_NCACTIVATE
, sent
},
2182 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2183 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2184 { WM_ACTIVATE
, sent
},
2185 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
2189 static const struct message WmTrackPopupMenu
[] = {
2190 { HCBT_CREATEWND
, hook
},
2191 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2192 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2193 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2194 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2195 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2196 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2197 { 0x0093, sent
|optional
},
2198 { 0x0094, sent
|optional
},
2199 { 0x0094, sent
|optional
},
2200 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2201 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2202 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2203 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2204 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2205 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2206 { WM_CAPTURECHANGED
, sent
},
2207 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2208 { HCBT_DESTROYWND
, hook
},
2209 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2210 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2211 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2212 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2213 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2214 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2218 static const struct message WmTrackPopupMenuEsc
[] = {
2222 static const struct message WmTrackPopupMenuCapture
[] = {
2223 { HCBT_CREATEWND
, hook
},
2224 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2225 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2226 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2227 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2228 { WM_CAPTURECHANGED
, sent
},
2229 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2230 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2231 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2232 { 0x0093, sent
|optional
},
2233 { 0x0094, sent
|optional
},
2234 { 0x0094, sent
|optional
},
2235 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2236 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2237 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2238 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2239 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2240 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2241 { WM_CAPTURECHANGED
, sent
},
2242 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2243 { HCBT_DESTROYWND
, hook
},
2244 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2245 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2246 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2247 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2248 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2249 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2253 static const struct message WmTrackPopupMenuEmpty
[] = {
2254 { HCBT_CREATEWND
, hook
},
2255 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2256 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2257 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2258 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2259 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2260 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2261 { 0x0093, sent
|optional
},
2262 { 0x0094, sent
|optional
},
2263 { 0x0094, sent
|optional
},
2264 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2265 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2266 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2267 { WM_CAPTURECHANGED
, sent
},
2268 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2269 { HCBT_DESTROYWND
, hook
},
2270 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2271 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2275 static const struct message WmTrackPopupMenuAbort
[] = {
2276 { HCBT_CREATEWND
, hook
},
2277 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2278 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2279 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2280 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2281 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2282 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2283 { 0x0093, sent
|optional
},
2284 { 0x0094, sent
|optional
},
2285 { 0x0094, sent
|optional
},
2286 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2287 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2288 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2289 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2290 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2291 { WM_CAPTURECHANGED
, sent
},
2292 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2293 { HCBT_DESTROYWND
, hook
},
2294 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2295 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2296 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2297 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2298 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2299 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2303 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
2304 static int sequence_cnt
, sequence_size
;
2305 static struct recvd_message
* sequence
;
2306 static int log_all_parent_messages
;
2307 static CRITICAL_SECTION sequence_cs
;
2309 /* user32 functions */
2310 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
2311 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
2312 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
2313 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
2314 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
2315 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
2316 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
2317 static UINT_PTR (WINAPI
*pSetCoalescableTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
, ULONG
);
2318 /* kernel32 functions */
2319 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
2321 static void init_procs(void)
2323 HMODULE user32
= GetModuleHandleA("user32.dll");
2324 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
2326 #define GET_PROC(dll, func) \
2327 p ## func = (void*)GetProcAddress(dll, #func); \
2329 trace("GetProcAddress(%s) failed\n", #func); \
2332 GET_PROC(user32
, NotifyWinEvent
)
2333 GET_PROC(user32
, SetWinEventHook
)
2334 GET_PROC(user32
, TrackMouseEvent
)
2335 GET_PROC(user32
, UnhookWinEvent
)
2336 GET_PROC(user32
, UpdateLayeredWindow
)
2337 GET_PROC(user32
, SetSystemTimer
)
2338 GET_PROC(user32
, KillSystemTimer
)
2339 GET_PROC(user32
, SetCoalescableTimer
)
2341 GET_PROC(kernel32
, GetCPInfoExA
)
2346 static const char *get_winpos_flags(UINT flags
)
2348 static char buffer
[300];
2351 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2352 DUMP( SWP_SHOWWINDOW
);
2353 DUMP( SWP_HIDEWINDOW
);
2354 DUMP( SWP_NOACTIVATE
);
2355 DUMP( SWP_FRAMECHANGED
);
2356 DUMP( SWP_NOCOPYBITS
);
2357 DUMP( SWP_NOOWNERZORDER
);
2358 DUMP( SWP_NOSENDCHANGING
);
2359 DUMP( SWP_DEFERERASE
);
2360 DUMP( SWP_ASYNCWINDOWPOS
);
2361 DUMP( SWP_NOZORDER
);
2362 DUMP( SWP_NOREDRAW
);
2365 DUMP( SWP_NOCLIENTSIZE
);
2366 DUMP( SWP_NOCLIENTMOVE
);
2367 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
2372 static BOOL
ignore_message( UINT message
)
2374 /* these are always ignored */
2375 return (message
>= 0xc000 ||
2376 message
== WM_GETICON
||
2377 message
== WM_GETOBJECT
||
2378 message
== WM_TIMECHANGE
||
2379 message
== WM_DISPLAYCHANGE
||
2380 message
== WM_DEVICECHANGE
||
2381 message
== WM_DWMNCRENDERINGCHANGED
||
2382 message
== WM_WININICHANGE
);
2385 static unsigned hash_Ly_W(const WCHAR
*str
)
2390 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2395 static unsigned hash_Ly(const char *str
)
2400 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2405 #define add_message(msg) add_message_(__LINE__,msg);
2406 static void add_message_(int line
, const struct recvd_message
*msg
)
2408 struct recvd_message
*seq
;
2410 EnterCriticalSection( &sequence_cs
);
2414 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
) );
2416 if (sequence_cnt
== sequence_size
)
2419 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof(*sequence
) );
2423 seq
= &sequence
[sequence_cnt
++];
2424 seq
->hwnd
= msg
->hwnd
;
2425 seq
->message
= msg
->message
;
2426 seq
->flags
= msg
->flags
;
2427 seq
->wParam
= msg
->wParam
;
2428 seq
->lParam
= msg
->lParam
;
2430 seq
->descr
= msg
->descr
;
2432 LeaveCriticalSection( &sequence_cs
);
2436 if (msg
->flags
& hook
)
2438 static const char * const CBT_code_name
[10] =
2446 "HCBT_CLICKSKIPPED",
2451 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
2453 sprintf( seq
->output
, "%s: hook %d (%s) wp %08Ix lp %08Ix",
2454 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
2456 else if (msg
->flags
& winevent_hook
)
2458 sprintf( seq
->output
, "%s: winevent %p %08x %08Ix %08Ix",
2459 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2463 switch (msg
->message
)
2465 case WM_WINDOWPOSCHANGING
:
2466 case WM_WINDOWPOSCHANGED
:
2468 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
2470 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08Ix lp %08Ix after %p x %d y %d cx %d cy %d flags %s",
2471 msg
->descr
, msg
->hwnd
,
2472 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
2473 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
2474 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
2475 get_winpos_flags(winpos
->flags
) );
2477 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2478 * in the high word for internal purposes
2480 seq
->wParam
= winpos
->flags
& 0xffff;
2481 /* We are not interested in the flags that don't match under XP and Win9x */
2482 seq
->wParam
&= ~SWP_NOZORDER
;
2483 seq
->lParam
= (!!winpos
->cx
) | ((!!winpos
->cy
) << 1)
2484 | ((!!winpos
->x
) << 2) | ((!!winpos
->y
) << 3);
2491 NCCALCSIZE_PARAMS
*p
= (NCCALCSIZE_PARAMS
*)msg
->lParam
;
2492 WINDOWPOS
*winpos
= p
->lppos
;
2494 sprintf(seq
->output
, "%s: %p WM_NCCALCSIZE: winpos->cx %u, winpos->cy %u",
2495 msg
->descr
, msg
->hwnd
, winpos
->cx
, winpos
->cy
);
2496 seq
->lParam
= (!!winpos
->cx
) | ((!!winpos
->cy
) << 1)
2497 | ((!!winpos
->x
) << 2) | ((!!winpos
->y
) << 3);
2506 DRAW_ITEM_STRUCT di
;
2507 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
2509 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2510 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
2511 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
2514 di
.u
.item
.type
= dis
->CtlType
;
2515 di
.u
.item
.ctl_id
= dis
->CtlID
;
2516 if (dis
->CtlType
== ODT_LISTBOX
||
2517 dis
->CtlType
== ODT_COMBOBOX
||
2518 dis
->CtlType
== ODT_MENU
)
2519 di
.u
.item
.item_id
= dis
->itemID
;
2520 di
.u
.item
.action
= dis
->itemAction
;
2521 di
.u
.item
.state
= dis
->itemState
;
2523 seq
->lParam
= di
.u
.lp
;
2527 case WM_MEASUREITEM
:
2529 MEASURE_ITEM_STRUCT mi
;
2530 MEASUREITEMSTRUCT
*mis
= (MEASUREITEMSTRUCT
*)msg
->lParam
;
2531 BOOL is_unicode_data
= TRUE
;
2533 sprintf( seq
->output
, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#Ix",
2534 msg
->descr
, msg
->hwnd
, mis
->CtlType
, mis
->CtlID
,
2535 mis
->itemID
, mis
->itemData
);
2537 if (mis
->CtlType
== ODT_LISTBOX
)
2539 HWND ctrl
= GetDlgItem(msg
->hwnd
, mis
->CtlID
);
2540 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2544 mi
.u
.item
.CtlType
= mis
->CtlType
;
2545 mi
.u
.item
.CtlID
= mis
->CtlID
;
2546 mi
.u
.item
.itemID
= mis
->itemID
;
2547 mi
.u
.item
.wParam
= msg
->wParam
;
2548 seq
->wParam
= mi
.u
.wp
;
2549 if (is_unicode_data
)
2550 seq
->lParam
= mis
->itemData
? hash_Ly_W((const WCHAR
*)mis
->itemData
) : 0;
2552 seq
->lParam
= mis
->itemData
? hash_Ly((const char *)mis
->itemData
) : 0;
2556 case WM_COMPAREITEM
:
2558 COMPAREITEMSTRUCT
*cis
= (COMPAREITEMSTRUCT
*)msg
->lParam
;
2559 HWND ctrl
= GetDlgItem(msg
->hwnd
, cis
->CtlID
);
2560 BOOL is_unicode_data
= TRUE
;
2562 ok(msg
->wParam
== cis
->CtlID
, "expected %#x, got %#Ix\n", cis
->CtlID
, msg
->wParam
);
2563 ok(cis
->hwndItem
== ctrl
, "expected %p, got %p\n", ctrl
, cis
->hwndItem
);
2564 ok((int)cis
->itemID1
>= 0, "expected >= 0, got %d\n", cis
->itemID1
);
2565 ok((int)cis
->itemID2
== -1, "expected -1, got %d\n", cis
->itemID2
);
2567 sprintf( seq
->output
, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#Ix, itemID2 %#x, itemData2 %#Ix",
2568 msg
->descr
, msg
->hwnd
, cis
->CtlType
, cis
->CtlID
,
2569 cis
->itemID1
, cis
->itemData1
, cis
->itemID2
, cis
->itemData2
);
2571 if (cis
->CtlType
== ODT_LISTBOX
)
2572 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2574 if (is_unicode_data
)
2576 seq
->wParam
= cis
->itemData1
? hash_Ly_W((const WCHAR
*)cis
->itemData1
) : 0;
2577 seq
->lParam
= cis
->itemData2
? hash_Ly_W((const WCHAR
*)cis
->itemData2
) : 0;
2581 seq
->wParam
= cis
->itemData1
? hash_Ly((const char *)cis
->itemData1
) : 0;
2582 seq
->lParam
= cis
->itemData2
? hash_Ly((const char *)cis
->itemData2
) : 0;
2588 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
2589 sprintf( seq
->output
, "%s: %p %04x wp %08Ix lp %08Ix",
2590 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2592 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
2593 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
2598 /* try to make sure pending X events have been processed before continuing */
2599 static void flush_events(void)
2603 int min_timeout
= 100;
2604 DWORD time
= GetTickCount() + diff
;
2608 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
2609 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2610 diff
= time
- GetTickCount();
2614 static void flush_sequence(void)
2616 EnterCriticalSection( &sequence_cs
);
2617 HeapFree(GetProcessHeap(), 0, sequence
);
2619 sequence_cnt
= sequence_size
= 0;
2620 LeaveCriticalSection( &sequence_cs
);
2623 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
2625 const struct recvd_message
*actual
= sequence
;
2626 unsigned int count
= 0;
2628 trace_(file
, line
)("Failed sequence %s:\n", context
);
2629 while (expected
->message
&& actual
->message
)
2631 if (actual
->output
[0])
2633 if (expected
->flags
& hook
)
2635 trace_(file
, line
)( " %u: expected: hook %04x - actual: %s\n",
2636 count
, expected
->message
, actual
->output
);
2638 else if (expected
->flags
& winevent_hook
)
2640 trace_(file
, line
)( " %u: expected: winevent %04x - actual: %s\n",
2641 count
, expected
->message
, actual
->output
);
2643 else if (expected
->flags
& kbd_hook
)
2645 trace_(file
, line
)( " %u: expected: kbd %04x - actual: %s\n",
2646 count
, expected
->message
, actual
->output
);
2650 trace_(file
, line
)( " %u: expected: msg %04x - actual: %s\n",
2651 count
, expected
->message
, actual
->output
);
2655 if (expected
->message
== actual
->message
)
2657 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) &&
2658 (expected
->flags
& optional
))
2660 /* don't match messages if their defwinproc status differs */
2669 /* silently drop winevent messages if there is no support for them */
2670 else if ((expected
->flags
& optional
) || ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2671 ((expected
->flags
& winevent_hook_todo
) && !strcmp(winetest_platform
, "wine")))
2681 /* optional trailing messages */
2682 while (expected
->message
&& ((expected
->flags
& optional
) ||
2683 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2685 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2690 if (expected
->message
)
2692 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2696 while (actual
->message
&& actual
->output
[0])
2698 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
2704 #define ok_sequence( exp, contx, todo) \
2705 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2708 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2709 const char *file
, int line
)
2711 static const struct recvd_message end_of_sequence
;
2712 const struct message
*expected
= expected_list
;
2713 const struct recvd_message
*actual
;
2714 int failcount
= 0, dump
= 0;
2715 unsigned int count
= 0;
2717 add_message(&end_of_sequence
);
2721 while (expected
->message
&& actual
->message
)
2723 if (expected
->message
== actual
->message
&&
2724 !((expected
->flags
^ actual
->flags
) & (hook
|winevent_hook
|kbd_hook
)))
2726 if (expected
->flags
& wparam
)
2728 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2732 if (strcmp(winetest_platform
, "wine")) dump
++;
2733 ok_( file
, line
) (FALSE
,
2734 "%s: %u: in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2735 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2740 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2741 "%s: %u: in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2742 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2743 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2747 if (expected
->flags
& lparam
)
2749 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2753 if (strcmp(winetest_platform
, "wine")) dump
++;
2754 ok_( file
, line
) (FALSE
,
2755 "%s: %u: in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2756 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2761 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2762 "%s: %u: in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2763 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2764 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2767 if ((expected
->flags
& optional
) &&
2768 ((expected
->flags
^ actual
->flags
) & (defwinproc
|parent
)))
2770 /* don't match optional messages if their defwinproc or parent status differs */
2775 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2779 if (strcmp(winetest_platform
, "wine")) dump
++;
2780 ok_( file
, line
) (FALSE
,
2781 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2782 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2787 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2788 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2789 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2790 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2793 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2794 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n",
2795 context
, count
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2796 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2798 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2799 "%s: %u: the msg 0x%04x should have been %s\n",
2800 context
, count
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2801 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2803 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2804 "%s: %u: the msg 0x%04x was expected in %s\n",
2805 context
, count
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2806 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2808 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
2809 "%s: %u: the msg 0x%04x should have been sent by a hook\n",
2810 context
, count
, expected
->message
);
2811 if ((expected
->flags
& hook
) != (actual
->flags
& hook
)) dump
++;
2813 ok_( file
, line
) ((expected
->flags
& winevent_hook
) == (actual
->flags
& winevent_hook
),
2814 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n",
2815 context
, count
, expected
->message
);
2816 if ((expected
->flags
& winevent_hook
) != (actual
->flags
& winevent_hook
)) dump
++;
2818 ok_( file
, line
) ((expected
->flags
& kbd_hook
) == (actual
->flags
& kbd_hook
),
2819 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n",
2820 context
, count
, expected
->message
);
2821 if ((expected
->flags
& kbd_hook
) != (actual
->flags
& kbd_hook
)) dump
++;
2827 * silently drop hook messages if there is no support for them, mark
2830 else if ((expected
->flags
& optional
) ||
2831 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2832 ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2833 ((expected
->flags
& kbd_hook
) && !hKBD_hook
) ||
2834 ((expected
->flags
& winevent_hook_todo
) && !strcmp(winetest_platform
, "wine")))
2836 if ((expected
->flags
& winevent_hook_todo
) && hEvent_hook
)
2839 ok_( file
, line
) (FALSE
,
2840 "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2841 context
, count
, expected
->message
, actual
->message
);
2850 if (strcmp(winetest_platform
, "wine")) dump
++;
2851 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2852 context
, count
, expected
->message
, actual
->message
);
2858 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2859 context
, count
, expected
->message
, actual
->message
);
2867 /* skip all optional trailing messages, check for winevent todo's. */
2868 while (expected
->message
&& ((expected
->flags
& optional
) ||
2869 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2870 ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2871 ((expected
->flags
& winevent_hook_todo
) && !strcmp(winetest_platform
, "wine"))))
2873 if ((expected
->flags
& winevent_hook_todo
) && hEvent_hook
)
2876 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected 0x%04x - actual 0x%04x\n",
2877 context
, count
, expected
->message
, actual
->message
);
2886 if (expected
->message
|| actual
->message
) {
2888 if (strcmp(winetest_platform
, "wine")) dump
++;
2889 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2890 context
, count
, expected
->message
, actual
->message
);
2896 if (expected
->message
|| actual
->message
)
2899 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2900 context
, count
, expected
->message
, actual
->message
);
2903 if( todo
&& !failcount
) /* succeeded yet marked todo */
2905 if (!strcmp(winetest_platform
, "wine")) dump
++;
2906 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
2910 if (dump
) dump_sequence(expected_list
, context
, file
, line
);
2914 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
2916 /******************************** MDI test **********************************/
2918 /* CreateWindow for MDI frame window, initially visible */
2919 static const struct message WmCreateMDIframeSeq
[] = {
2920 { HCBT_CREATEWND
, hook
},
2921 { WM_GETMINMAXINFO
, sent
},
2922 { WM_NCCREATE
, sent
},
2923 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2924 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
2925 { WM_CREATE
, sent
},
2926 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2927 { WM_NOTIFYFORMAT
, sent
|optional
},
2928 { WM_QUERYUISTATE
, sent
|optional
},
2929 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2930 { WM_GETMINMAXINFO
, sent
|optional
},
2931 { WM_NCCALCSIZE
, sent
|optional
},
2932 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2933 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2934 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2935 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2936 { HCBT_ACTIVATE
, hook
},
2937 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2938 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2939 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2940 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2941 { WM_NCACTIVATE
, sent
},
2942 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2943 { WM_ACTIVATE
, sent
|wparam
, 1 },
2944 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2945 { HCBT_SETFOCUS
, hook
},
2946 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2947 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2948 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
2949 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2950 /* Win9x adds SWP_NOZORDER below */
2951 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2952 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2953 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
2954 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2958 /* DestroyWindow for MDI frame window, initially visible */
2959 static const struct message WmDestroyMDIframeSeq
[] = {
2960 { HCBT_DESTROYWND
, hook
},
2961 { 0x0090, sent
|optional
},
2962 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2963 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2964 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2965 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2966 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
2967 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2968 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
2969 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
2970 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2971 { WM_DESTROY
, sent
},
2972 { WM_NCDESTROY
, sent
},
2975 /* CreateWindow for MDI client window, initially visible */
2976 static const struct message WmCreateMDIclientSeq
[] = {
2977 { HCBT_CREATEWND
, hook
},
2978 { WM_NCCREATE
, sent
},
2979 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2980 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2981 { WM_CREATE
, sent
},
2982 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2983 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2984 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2986 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
2987 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2988 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2989 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2990 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2993 /* ShowWindow(SW_SHOW) for MDI client window */
2994 static const struct message WmShowMDIclientSeq
[] = {
2995 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2996 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2997 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
2998 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3001 /* ShowWindow(SW_HIDE) for MDI client window */
3002 static const struct message WmHideMDIclientSeq
[] = {
3003 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3004 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3005 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
3006 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
3007 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3010 /* DestroyWindow for MDI client window, initially visible */
3011 static const struct message WmDestroyMDIclientSeq
[] = {
3012 { HCBT_DESTROYWND
, hook
},
3013 { 0x0090, sent
|optional
},
3014 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
3015 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3016 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3017 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3018 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3019 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3020 { WM_DESTROY
, sent
},
3021 { WM_NCDESTROY
, sent
},
3024 /* CreateWindow for MDI child window, initially visible */
3025 static const struct message WmCreateMDIchildVisibleSeq
[] = {
3026 { HCBT_CREATEWND
, hook
},
3027 { WM_NCCREATE
, sent
},
3028 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3029 { WM_CREATE
, sent
},
3030 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3031 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3033 /* Win2k sends wparam set to
3034 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3035 * while Win9x doesn't bother to set child window id according to
3036 * CLIENTCREATESTRUCT.idFirstChild
3038 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3039 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3040 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3041 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3042 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3043 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3044 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3045 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3046 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3048 /* Win9x: message sequence terminates here. */
3050 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3051 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3052 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3053 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3054 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3055 { WM_SETFOCUS
, sent
}, /* in MDI client */
3056 { HCBT_SETFOCUS
, hook
},
3057 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3058 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3059 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3060 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3061 { WM_SETFOCUS
, sent
|defwinproc
},
3062 { WM_MDIACTIVATE
, sent
|defwinproc
},
3065 /* WM_CHILDACTIVATE sent to disabled window */
3066 static const struct message WmChildActivateDisabledWindowSeq
[] = {
3067 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3070 /* WM_CHILDACTIVATE sent to enabled window */
3071 static const struct message WmChildActivateWindowSeq
[] = {
3072 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3073 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 },
3074 { WM_MDIACTIVATE
, sent
|defwinproc
},
3075 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3076 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3077 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3078 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3079 { HCBT_SETFOCUS
, hook
},
3080 { WM_KILLFOCUS
, sent
|defwinproc
},
3081 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3082 { WM_SETFOCUS
, sent
},
3083 { HCBT_SETFOCUS
, hook
},
3084 { WM_KILLFOCUS
, sent
},
3085 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3086 { WM_SETFOCUS
, sent
|defwinproc
},
3087 { WM_MDIACTIVATE
, sent
|defwinproc
},
3090 /* CreateWindow for MDI child window with invisible parent */
3091 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
3092 { HCBT_CREATEWND
, hook
},
3093 { WM_GETMINMAXINFO
, sent
},
3094 { WM_NCCREATE
, sent
},
3095 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3096 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
3097 { WM_CREATE
, sent
},
3098 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3099 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3101 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3102 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3103 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3104 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3105 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3106 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3108 /* Win9x: message sequence terminates here. */
3110 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3111 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3112 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3113 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3114 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3115 { WM_SETFOCUS
, sent
}, /* in MDI client */
3116 { HCBT_SETFOCUS
, hook
},
3117 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3118 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3119 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3120 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3121 { WM_SETFOCUS
, sent
|defwinproc
},
3122 { WM_MDIACTIVATE
, sent
|defwinproc
},
3125 /* DestroyWindow for MDI child window, initially visible */
3126 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
3127 { HCBT_DESTROYWND
, hook
},
3128 /* Win2k sends wparam set to
3129 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3130 * while Win9x doesn't bother to set child window id according to
3131 * CLIENTCREATESTRUCT.idFirstChild
3133 { 0x0090, sent
|optional
},
3134 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3135 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3136 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3137 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3138 { WM_ERASEBKGND
, sent
|parent
|optional
},
3139 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3141 /* { WM_DESTROY, sent }
3142 * Win9x: message sequence terminates here.
3145 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3146 { WM_KILLFOCUS
, sent
},
3147 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3148 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3149 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3150 { WM_SETFOCUS
, sent
}, /* in MDI client */
3152 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3153 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3154 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3155 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3156 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3157 { WM_SETFOCUS
, sent
}, /* in MDI client */
3159 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3161 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3162 { WM_KILLFOCUS
, sent
},
3163 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3164 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3165 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3166 { WM_SETFOCUS
, sent
}, /* in MDI client */
3168 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3169 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3170 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3171 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3172 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3173 { WM_SETFOCUS
, sent
}, /* in MDI client */
3175 { WM_DESTROY
, sent
},
3177 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3178 { WM_KILLFOCUS
, sent
},
3179 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3180 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3181 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3182 { WM_SETFOCUS
, sent
}, /* in MDI client */
3184 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3185 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3186 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3187 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3188 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3189 { WM_SETFOCUS
, sent
}, /* in MDI client */
3191 { WM_NCDESTROY
, sent
},
3194 /* CreateWindow for MDI child window, initially invisible */
3195 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
3196 { HCBT_CREATEWND
, hook
},
3197 { WM_NCCREATE
, sent
},
3198 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3199 { WM_CREATE
, sent
},
3200 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3201 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3203 /* Win2k sends wparam set to
3204 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3205 * while Win9x doesn't bother to set child window id according to
3206 * CLIENTCREATESTRUCT.idFirstChild
3208 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3211 /* DestroyWindow for MDI child window, initially invisible */
3212 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
3213 { HCBT_DESTROYWND
, hook
},
3214 /* Win2k sends wparam set to
3215 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3216 * while Win9x doesn't bother to set child window id according to
3217 * CLIENTCREATESTRUCT.idFirstChild
3219 { 0x0090, sent
|optional
},
3220 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3221 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3222 { WM_DESTROY
, sent
},
3223 { WM_NCDESTROY
, sent
},
3224 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
3225 { WM_PARENTNOTIFY
, sent
|wparam
|optional
, WM_DESTROY
}, /* MDI client */
3228 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
3229 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
3230 { HCBT_CREATEWND
, hook
},
3231 { WM_NCCREATE
, sent
},
3232 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3233 { WM_CREATE
, sent
},
3234 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3235 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3237 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3238 { WM_GETMINMAXINFO
, sent
},
3239 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3240 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3241 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3242 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3244 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3245 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3246 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3247 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3248 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3249 /* Win2k sends wparam set to
3250 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3251 * while Win9x doesn't bother to set child window id according to
3252 * CLIENTCREATESTRUCT.idFirstChild
3254 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3255 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3256 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3257 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3258 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3259 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3260 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3261 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3262 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
3264 /* Win9x: message sequence terminates here. */
3266 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3267 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
3268 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3269 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3270 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3271 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3272 { HCBT_SETFOCUS
, hook
|optional
},
3273 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3274 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3275 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3276 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3277 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3278 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3280 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3281 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3282 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3283 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3286 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
3287 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
3288 /* restore the 1st MDI child */
3289 { WM_SETREDRAW
, sent
|wparam
, 0 },
3290 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3291 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3292 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3293 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3294 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3295 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3297 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3298 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3299 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3300 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3301 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3302 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
3303 /* create the 2nd MDI child */
3304 { HCBT_CREATEWND
, hook
},
3305 { WM_NCCREATE
, sent
},
3306 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3307 { WM_CREATE
, sent
},
3308 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3309 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3311 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3312 { WM_GETMINMAXINFO
, sent
},
3313 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3314 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3315 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3316 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3317 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3319 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3320 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3321 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3322 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3323 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3324 /* Win2k sends wparam set to
3325 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3326 * while Win9x doesn't bother to set child window id according to
3327 * CLIENTCREATESTRUCT.idFirstChild
3329 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3330 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3331 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3332 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3333 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3334 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3335 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3336 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3338 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3339 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3341 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3343 /* Win9x: message sequence terminates here. */
3345 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3346 { HCBT_SETFOCUS
, hook
},
3347 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
3348 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
3349 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3350 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3351 { WM_SETFOCUS
, sent
}, /* in MDI client */
3352 { HCBT_SETFOCUS
, hook
},
3353 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3354 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3355 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3356 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3357 { WM_SETFOCUS
, sent
|defwinproc
},
3359 { WM_MDIACTIVATE
, sent
|defwinproc
},
3361 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3362 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3363 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3364 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3367 /* WM_MDICREATE MDI child window, initially visible and maximized */
3368 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
3369 { WM_MDICREATE
, sent
},
3370 { HCBT_CREATEWND
, hook
},
3371 { WM_NCCREATE
, sent
},
3372 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3373 { WM_CREATE
, sent
},
3374 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3375 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3377 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3378 { WM_GETMINMAXINFO
, sent
},
3379 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3380 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3381 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3382 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
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 */
3389 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3391 /* Win2k sends wparam set to
3392 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3393 * while Win9x doesn't bother to set child window id according to
3394 * CLIENTCREATESTRUCT.idFirstChild
3396 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3397 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3398 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3400 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3402 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3403 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3404 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3406 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3407 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3409 /* Win9x: message sequence terminates here. */
3411 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3412 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3413 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3414 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3415 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
3416 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
3417 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3418 { HCBT_SETFOCUS
, hook
|optional
},
3419 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3420 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3421 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3422 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3423 { WM_SETFOCUS
, sent
|defwinproc
},
3425 { WM_MDIACTIVATE
, sent
|defwinproc
},
3428 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3429 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3430 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3431 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3434 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3435 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3436 { 0x0093, sent
|defwinproc
|optional
},
3437 { 0x0093, sent
|defwinproc
|optional
},
3438 { 0x0093, sent
|defwinproc
|optional
},
3439 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3440 { WM_MOVE
, sent
|defwinproc
},
3441 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3444 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3445 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3446 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3447 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3450 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3451 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3452 { 0x0093, sent
|optional
},
3453 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3454 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3456 { 0x0093, sent
|optional
},
3457 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3458 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client, not sent on Win7. */
3459 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3460 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
3461 { 0x0093, sent
|defwinproc
|optional
},
3462 { 0x0093, sent
|defwinproc
|optional
},
3463 { 0x0093, sent
|defwinproc
|optional
},
3464 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3465 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3469 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3470 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
3471 { HCBT_CREATEWND
, hook
},
3472 { WM_GETMINMAXINFO
, sent
},
3473 { WM_NCCREATE
, sent
},
3474 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3475 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
3476 { WM_CREATE
, sent
},
3477 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3478 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3479 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3480 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
3481 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3483 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3484 { WM_GETMINMAXINFO
, sent
},
3485 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3486 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3487 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3488 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3489 { WM_MOVE
, sent
|defwinproc
},
3490 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3492 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3493 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3494 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3495 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3496 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
3497 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3498 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3499 /* Win2k sends wparam set to
3500 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3501 * while Win9x doesn't bother to set child window id according to
3502 * CLIENTCREATESTRUCT.idFirstChild
3504 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3507 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3508 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
3509 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
3510 { HCBT_SYSCOMMAND
, hook
},
3511 { WM_CLOSE
, sent
|defwinproc
},
3512 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3514 /* bring the 1st MDI child to top */
3515 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
3516 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
3518 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3520 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
3521 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3522 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3524 /* maximize the 1st MDI child */
3525 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3526 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3527 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3528 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3529 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3530 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3531 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3533 /* restore the 2nd MDI child */
3534 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
3535 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
3536 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3537 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3539 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3541 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3542 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3544 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3546 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
3548 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3549 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3550 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3551 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3552 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3554 /* bring the 1st MDI child to top */
3555 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3556 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3557 { HCBT_SETFOCUS
, hook
},
3558 { WM_KILLFOCUS
, sent
|defwinproc
},
3559 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
3560 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3561 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3562 { WM_SETFOCUS
, sent
}, /* in MDI client */
3563 { HCBT_SETFOCUS
, hook
},
3564 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3565 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3566 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3567 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3568 { WM_SETFOCUS
, sent
|defwinproc
},
3569 { WM_MDIACTIVATE
, sent
|defwinproc
},
3570 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3572 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3573 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3574 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3575 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3576 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3577 { WM_MDIREFRESHMENU
, sent
},
3579 { HCBT_DESTROYWND
, hook
},
3580 /* Win2k sends wparam set to
3581 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3582 * while Win9x doesn't bother to set child window id according to
3583 * CLIENTCREATESTRUCT.idFirstChild
3585 { 0x0090, sent
|defwinproc
|optional
},
3586 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3587 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
3588 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3589 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3590 { WM_ERASEBKGND
, sent
|parent
|optional
},
3591 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3593 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3594 { WM_DESTROY
, sent
|defwinproc
},
3595 { WM_NCDESTROY
, sent
|defwinproc
},
3598 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3599 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
3600 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3601 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3602 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3603 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3604 { WM_ERASEBKGND
, sent
|parent
|optional
},
3605 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3607 { HCBT_SETFOCUS
, hook
},
3608 { WM_KILLFOCUS
, sent
},
3609 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3610 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3611 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3612 { WM_SETFOCUS
, sent
}, /* in MDI client */
3613 { HCBT_SETFOCUS
, hook
},
3614 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3615 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3616 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3617 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3618 { WM_SETFOCUS
, sent
},
3621 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3622 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3623 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3624 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3627 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3628 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3629 { 0x0093, sent
|defwinproc
|optional
},
3630 { 0x0093, sent
|defwinproc
|optional
},
3631 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3632 { WM_MOVE
, sent
|defwinproc
},
3633 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3636 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3637 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3638 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3639 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3642 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3643 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3644 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3645 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3648 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3649 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3650 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3651 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3654 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3655 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3656 { 0x0093, sent
|defwinproc
|optional
},
3657 { 0x0093, sent
|defwinproc
|optional
},
3658 { 0x0093, sent
|defwinproc
|optional
},
3659 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3660 { WM_MOVE
, sent
|defwinproc
},
3661 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3664 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3665 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3666 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3667 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3670 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3671 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3672 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3673 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3674 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3675 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI client */
3677 { 0x0093, sent
|defwinproc
|optional
},
3678 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
3679 { 0x0093, sent
|defwinproc
|optional
},
3680 { 0x0093, sent
|defwinproc
|optional
},
3681 { 0x0093, sent
|defwinproc
|optional
},
3682 { 0x0093, sent
|optional
},
3684 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3685 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3686 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI client */
3687 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame */
3688 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3689 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3692 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3693 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3694 { 0x0093, sent
|defwinproc
|optional
},
3695 { 0x0093, sent
|defwinproc
|optional
},
3696 { 0x0093, sent
|defwinproc
|optional
},
3697 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3698 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3699 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3700 { 0x0093, sent
|optional
},
3702 { WM_NCACTIVATE
, sent
|wparam
, 0 },
3703 { WM_MDIACTIVATE
, sent
},
3705 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3706 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3707 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3709 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3711 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3712 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3713 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3716 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3717 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3718 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3719 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3722 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3723 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3724 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3725 { WM_MOVE
, sent
|defwinproc
},
3726 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3729 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3730 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3731 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3732 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3733 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3734 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3735 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI client */
3736 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3737 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3739 { HCBT_SETFOCUS
, hook
},
3740 { WM_KILLFOCUS
, sent
},
3741 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3742 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3743 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3744 { WM_SETFOCUS
, sent
}, /* in MDI client */
3746 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3748 { HCBT_DESTROYWND
, hook
},
3749 /* Win2k sends wparam set to
3750 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3751 * while Win9x doesn't bother to set child window id according to
3752 * CLIENTCREATESTRUCT.idFirstChild
3754 { 0x0090, sent
|optional
},
3755 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3757 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3758 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3759 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3760 { WM_ERASEBKGND
, sent
|parent
|optional
},
3761 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3763 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3764 { WM_DESTROY
, sent
},
3765 { WM_NCDESTROY
, sent
},
3768 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3769 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3770 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3771 { WM_GETMINMAXINFO
, sent
},
3772 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3773 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3774 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3775 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3777 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3778 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3779 { HCBT_SETFOCUS
, hook
|optional
},
3780 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3781 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3782 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3783 { HCBT_SETFOCUS
, hook
|optional
},
3784 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3785 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3786 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3787 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3788 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3789 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3790 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3791 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3793 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3794 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3795 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3796 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3797 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3800 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3801 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3802 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3803 { WM_GETMINMAXINFO
, sent
},
3804 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
3805 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3806 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3807 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3808 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3810 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3811 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3812 { HCBT_SETFOCUS
, hook
|optional
},
3813 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3814 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3815 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3816 { HCBT_SETFOCUS
, hook
|optional
},
3817 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3818 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3819 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3820 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3821 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3822 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3823 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
3824 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child, not sent on Win8+. */
3825 { WM_SIZE
, sent
|defwinproc
|optional
},
3826 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* w1064v1809. */
3829 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3830 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3831 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3832 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3833 { WM_GETMINMAXINFO
, sent
},
3834 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3835 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3836 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3837 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3838 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3839 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3840 { WM_MOVE
, sent
|defwinproc
},
3841 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3843 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3844 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3845 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3846 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3847 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3848 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3850 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3851 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3852 { 0x0093, sent
|defwinproc
|optional
},
3853 { 0x0094, sent
|defwinproc
|optional
},
3854 { 0x0094, sent
|defwinproc
|optional
},
3855 { 0x0094, sent
|defwinproc
|optional
},
3856 { 0x0094, sent
|defwinproc
|optional
},
3857 { 0x0093, sent
|defwinproc
|optional
},
3858 { 0x0093, sent
|defwinproc
|optional
},
3859 { 0x0091, sent
|defwinproc
|optional
},
3860 { 0x0092, sent
|defwinproc
|optional
},
3861 { 0x0092, sent
|defwinproc
|optional
},
3862 { 0x0092, sent
|defwinproc
|optional
},
3863 { 0x0092, sent
|defwinproc
|optional
},
3864 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3865 { WM_MOVE
, sent
|defwinproc
},
3866 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3867 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3869 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3870 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3871 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3872 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3874 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3875 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3876 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3877 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3878 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3879 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3880 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3881 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3882 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3883 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3885 { 0x0093, sent
|optional
},
3886 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3887 { 0x0093, sent
|defwinproc
|optional
},
3888 { 0x0093, sent
|defwinproc
|optional
},
3889 { 0x0093, sent
|defwinproc
|optional
},
3890 { 0x0091, sent
|defwinproc
|optional
},
3891 { 0x0092, sent
|defwinproc
|optional
},
3892 { 0x0092, sent
|defwinproc
|optional
},
3893 { 0x0092, sent
|defwinproc
|optional
},
3894 { 0x0092, sent
|defwinproc
|optional
},
3895 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3896 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3897 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3900 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3901 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3902 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3903 { WM_GETMINMAXINFO
, sent
},
3904 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3905 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3906 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3907 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3908 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3910 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3911 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3912 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3913 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3914 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3917 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3918 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3919 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3920 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3921 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3922 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3923 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3924 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3926 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3927 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3928 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3929 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3930 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3933 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3934 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3935 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3936 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3937 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3938 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3939 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3940 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3941 { WM_MOVE
, sent
|defwinproc
},
3942 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3943 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3944 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3945 { HCBT_SETFOCUS
, hook
},
3946 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3947 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3948 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
3949 { WM_SETFOCUS
, sent
},
3952 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3953 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
3954 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
3955 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3956 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3957 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3958 { WM_MOVE
, sent
|defwinproc
},
3959 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
3960 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
3961 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3962 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3963 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3964 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
}, /* MDI client */
3967 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3968 static const struct message WmRestoreMDIchildInvisibleSeq
[] = {
3969 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3970 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3971 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3972 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
3973 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3974 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3975 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3977 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3978 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3979 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3980 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI frame */
3981 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* MDI child */
3985 static HWND mdi_client
;
3986 static WNDPROC old_mdi_client_proc
;
3988 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3990 struct recvd_message msg
;
3992 /* do not log painting messages */
3993 if (message
!= WM_PAINT
&&
3994 message
!= WM_NCPAINT
&&
3995 message
!= WM_SYNCPAINT
&&
3996 message
!= WM_ERASEBKGND
&&
3997 message
!= WM_NCHITTEST
&&
3998 message
!= WM_GETTEXT
&&
3999 message
!= WM_MDIGETACTIVE
&&
4000 !ignore_message( message
))
4003 msg
.message
= message
;
4004 msg
.flags
= sent
|wparam
|lparam
;
4005 msg
.wParam
= wParam
;
4006 msg
.lParam
= lParam
;
4007 msg
.descr
= "mdi client";
4011 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
4014 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4016 static LONG defwndproc_counter
= 0;
4018 struct recvd_message msg
;
4020 /* do not log painting messages */
4021 if (message
!= WM_PAINT
&&
4022 message
!= WM_NCPAINT
&&
4023 message
!= WM_SYNCPAINT
&&
4024 message
!= WM_ERASEBKGND
&&
4025 message
!= WM_NCHITTEST
&&
4026 message
!= WM_GETTEXT
&&
4027 !ignore_message( message
))
4031 case WM_MDIACTIVATE
:
4033 HWND active
, client
= GetParent(hwnd
);
4035 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
4037 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
4038 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
4040 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
4046 msg
.message
= message
;
4047 msg
.flags
= sent
|wparam
|lparam
;
4048 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4049 msg
.wParam
= wParam
;
4050 msg
.lParam
= lParam
;
4051 msg
.descr
= "mdi child";
4055 defwndproc_counter
++;
4056 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
4057 defwndproc_counter
--;
4062 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4064 static LONG defwndproc_counter
= 0;
4066 struct recvd_message msg
;
4068 /* do not log painting messages */
4069 if (message
!= WM_PAINT
&&
4070 message
!= WM_NCPAINT
&&
4071 message
!= WM_SYNCPAINT
&&
4072 message
!= WM_ERASEBKGND
&&
4073 message
!= WM_NCHITTEST
&&
4074 message
!= WM_GETTEXT
&&
4075 !ignore_message( message
))
4078 msg
.message
= message
;
4079 msg
.flags
= sent
|wparam
|lparam
;
4080 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4081 msg
.wParam
= wParam
;
4082 msg
.lParam
= lParam
;
4083 msg
.descr
= "mdi frame";
4087 defwndproc_counter
++;
4088 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
4089 defwndproc_counter
--;
4094 static BOOL
mdi_RegisterWindowClasses(void)
4099 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
4102 cls
.hInstance
= GetModuleHandleA(0);
4104 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
4105 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
4106 cls
.lpszMenuName
= NULL
;
4107 cls
.lpszClassName
= "MDI_frame_class";
4108 if (!RegisterClassA(&cls
)) return FALSE
;
4110 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
4111 cls
.lpszClassName
= "MDI_child_class";
4112 if (!RegisterClassA(&cls
)) return FALSE
;
4114 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
4115 old_mdi_client_proc
= cls
.lpfnWndProc
;
4116 cls
.hInstance
= GetModuleHandleA(0);
4117 cls
.lpfnWndProc
= mdi_client_hook_proc
;
4118 cls
.lpszClassName
= "MDI_client_class";
4119 if (!RegisterClassA(&cls
)) assert(0);
4124 static void test_mdi_messages(void)
4126 MDICREATESTRUCTA mdi_cs
;
4127 CLIENTCREATESTRUCT client_cs
;
4128 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
4131 HMENU hMenu
= CreateMenu();
4134 if (!mdi_RegisterWindowClasses()) assert(0);
4138 trace("creating MDI frame window\n");
4139 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
4140 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
4141 WS_MAXIMIZEBOX
| WS_VISIBLE
,
4142 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
4143 GetDesktopWindow(), hMenu
,
4144 GetModuleHandleA(0), NULL
);
4146 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
4148 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4149 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
4151 trace("creating MDI client window\n");
4152 GetClientRect(mdi_frame
, &rc
);
4153 client_cs
.hWindowMenu
= 0;
4154 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
4155 mdi_client
= CreateWindowExA(0, "MDI_client_class",
4157 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
4158 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
4159 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4161 SetWindowLongA(mdi_client
, 0, 0xdeadbeef);
4163 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
4164 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4165 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
4167 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4168 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4169 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4174 trace("creating invisible MDI child window\n");
4175 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4177 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4178 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4182 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
4183 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
4185 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4186 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4188 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4189 ok(GetFocus() == 0, "wrong focus window %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
);
4195 ShowWindow(mdi_child
, SW_HIDE
);
4196 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
4199 ShowWindow(mdi_child
, SW_SHOW
);
4200 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
4202 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4203 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4205 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4206 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4208 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4209 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4210 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4212 DestroyWindow(mdi_child
);
4215 trace("creating visible MDI child window\n");
4216 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4217 WS_CHILD
| WS_VISIBLE
,
4218 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4219 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4221 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
4223 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4224 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4226 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4227 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4229 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4230 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4231 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4234 DestroyWindow(mdi_child
);
4235 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4237 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4238 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4240 /* Win2k: MDI client still returns a just destroyed child as active
4241 * Win9x: MDI client returns 0
4243 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4244 ok(active_child
== mdi_child
|| /* win2k */
4245 !active_child
, /* win9x */
4246 "wrong active MDI child %p\n", active_child
);
4247 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4251 trace("creating invisible MDI child window\n");
4252 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4254 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4255 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4257 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
4259 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
4260 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
4262 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4263 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4265 /* Win2k: MDI client still returns a just destroyed child as active
4266 * Win9x: MDI client returns mdi_child2
4268 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4269 ok(active_child
== mdi_child
|| /* win2k */
4270 active_child
== mdi_child2
, /* win9x */
4271 "wrong active MDI child %p\n", active_child
);
4272 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4275 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4276 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
4278 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4279 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4281 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4282 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4283 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4286 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4287 ok(GetFocus() == mdi_child2
|| /* win2k */
4288 GetFocus() == 0, /* win9x */
4289 "wrong focus window %p\n", GetFocus());
4294 ShowWindow(mdi_child2
, SW_HIDE
);
4295 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4297 ShowWindow(mdi_child2
, SW_RESTORE
);
4298 ok_sequence(WmRestoreMDIchildInvisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
4301 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4302 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4304 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4305 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4306 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4312 ShowWindow(mdi_child2
, SW_HIDE
);
4313 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4315 ShowWindow(mdi_child2
, SW_SHOW
);
4316 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
4318 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4319 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4321 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4322 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
4324 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4325 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4327 ShowWindow(mdi_child2
, SW_RESTORE
);
4328 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
4330 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4331 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4333 ShowWindow(mdi_child2
, SW_MINIMIZE
);
4334 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", FALSE
);
4336 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4337 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4339 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4340 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4341 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4344 ShowWindow(mdi_child2
, SW_RESTORE
);
4345 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
4347 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4348 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4350 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4351 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4352 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4358 ShowWindow(mdi_child2
, SW_HIDE
);
4359 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4361 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4362 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4364 DestroyWindow(mdi_child2
);
4365 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
4367 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4368 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4370 trace("Testing WM_CHILDACTIVATE\n");
4372 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4373 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_DISABLED
,
4374 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4375 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4377 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4378 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
,
4379 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4380 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4382 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4383 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4384 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4387 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4388 ok_sequence(WmChildActivateDisabledWindowSeq
, "WM_CHILDACTIVATE sent to disabled window", FALSE
);
4390 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4391 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4392 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4395 EnableWindow(mdi_child
, TRUE
);
4397 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4398 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4399 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4402 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4403 ok_sequence(WmChildActivateWindowSeq
, "WM_CHILDACTIVATE sent to enabled window", FALSE
);
4405 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4406 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4407 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4410 DestroyWindow(mdi_child
);
4411 DestroyWindow(mdi_child2
);
4414 /* test for maximized MDI children */
4415 trace("creating maximized visible MDI child window 1\n");
4416 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4417 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4418 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4419 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4421 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
4422 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4424 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4425 ok(GetFocus() == mdi_child
|| /* win2k */
4426 GetFocus() == 0, /* win9x */
4427 "wrong focus window %p\n", GetFocus());
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 trace("creating maximized visible MDI child window 2\n");
4435 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4436 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4437 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4438 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4440 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4441 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4442 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4444 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4445 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4447 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4448 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4449 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4452 trace("destroying maximized visible MDI child window 2\n");
4453 DestroyWindow(mdi_child2
);
4454 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4456 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4458 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4459 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4461 /* Win2k: MDI client still returns a just destroyed child as active
4462 * Win9x: MDI client returns 0
4464 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4465 ok(active_child
== mdi_child2
|| /* win2k */
4466 !active_child
, /* win9x */
4467 "wrong active MDI child %p\n", active_child
);
4470 ShowWindow(mdi_child
, SW_MAXIMIZE
);
4471 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4474 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4475 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4477 trace("re-creating maximized visible MDI child window 2\n");
4478 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4479 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4480 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4481 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4483 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4484 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4485 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4487 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4488 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4490 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4491 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4492 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4495 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
4496 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
4497 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
4499 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4500 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4501 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4503 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4504 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4505 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4508 DestroyWindow(mdi_child
);
4509 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4511 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4512 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4514 /* Win2k: MDI client still returns a just destroyed child as active
4515 * Win9x: MDI client returns 0
4517 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4518 ok(active_child
== mdi_child
|| /* win2k */
4519 !active_child
, /* win9x */
4520 "wrong active MDI child %p\n", active_child
);
4523 trace("creating maximized invisible MDI child window\n");
4524 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4525 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
4526 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4527 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4529 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
4530 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4531 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
4532 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
4534 /* Win2k: MDI client still returns a just destroyed child as active
4535 * Win9x: MDI client returns 0
4537 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4538 ok(active_child
== mdi_child
|| /* win2k */
4539 !active_child
|| active_child
== mdi_child2
, /* win9x */
4540 "wrong active MDI child %p\n", active_child
);
4543 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4544 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4545 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
4546 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4547 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4548 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4550 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4551 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4552 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4555 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4558 /* end of test for maximized MDI children */
4561 trace("creating maximized visible MDI child window 1(Switch test)\n");
4562 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4563 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4564 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4565 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4567 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
4568 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
4570 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4571 ok(GetFocus() == mdi_child
|| /* win2k */
4572 GetFocus() == 0, /* win9x */
4573 "wrong focus window %p(Switch test)\n", GetFocus());
4575 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4576 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4577 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4580 trace("creating maximized visible MDI child window 2(Switch test)\n");
4581 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4582 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4583 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4584 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4586 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
4588 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
4589 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
4591 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4592 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
4594 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4595 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
4596 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4599 trace("Switch child window.\n");
4600 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
4601 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
4602 trace("end of test for switch maximized MDI children\n");
4605 /* Prepare for switching test of not maximized MDI children */
4606 ShowWindow( mdi_child
, SW_NORMAL
);
4607 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
4608 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
4609 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
4610 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4613 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
4614 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
4615 trace("end of test for switch not maximized MDI children\n");
4618 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4621 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4626 /* end of tests for switch maximized/not maximized MDI children */
4628 mdi_cs
.szClass
= "MDI_child_Class";
4629 mdi_cs
.szTitle
= "MDI child";
4630 mdi_cs
.hOwner
= GetModuleHandleA(0);
4633 mdi_cs
.cx
= CW_USEDEFAULT
;
4634 mdi_cs
.cy
= CW_USEDEFAULT
;
4635 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
4637 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
4638 ok(mdi_child
!= 0, "MDI child creation failed\n");
4639 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
4641 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
4643 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4644 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4646 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
4647 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4648 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4650 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4651 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4652 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4655 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4656 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
4658 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
4659 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4660 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4665 val
= GetWindowLongA(mdi_client
, 0);
4666 ok(val
== 0xdeadbeef || broken(val
== 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%lx\n", val
);
4667 DestroyWindow(mdi_client
);
4668 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4670 /* test maximization of MDI child with invisible parent */
4671 client_cs
.hWindowMenu
= 0;
4672 mdi_client
= CreateWindowA("MDI_client_class",
4674 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
4676 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4677 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
4679 ShowWindow(mdi_client
, SW_HIDE
);
4680 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
4682 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4683 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
4685 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4686 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
4688 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
4689 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
4690 zoomed
= IsZoomed(mdi_child
);
4691 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4693 ShowWindow(mdi_client
, SW_SHOW
);
4694 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
4696 DestroyWindow(mdi_child
);
4697 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
4699 /* end of test for maximization of MDI child with invisible parent */
4701 DestroyWindow(mdi_client
);
4702 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4704 DestroyWindow(mdi_frame
);
4705 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
4707 /************************* End of MDI test **********************************/
4709 static void test_WM_SETREDRAW(HWND hwnd
)
4711 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4716 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
4717 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
4719 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
4720 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
4723 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
4724 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
4726 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4727 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
4729 /* restore original WS_VISIBLE state */
4730 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4736 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4738 struct recvd_message msg
;
4740 if (ignore_message( message
)) return 0;
4746 case WM_NCMOUSEMOVE
:
4747 case WM_NCMOUSELEAVE
:
4755 msg
.message
= message
;
4756 msg
.flags
= sent
|wparam
|lparam
;
4757 msg
.wParam
= wParam
;
4758 msg
.lParam
= lParam
;
4759 msg
.descr
= "dialog";
4762 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
4763 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
4767 static INT_PTR CALLBACK
TestModalDlgProc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4769 struct recvd_message msg
;
4771 if (ignore_message( message
)) return 0;
4777 case WM_NCMOUSEMOVE
:
4778 case WM_NCMOUSELEAVE
:
4786 msg
.message
= message
;
4787 msg
.flags
= sent
|wparam
|lparam
;
4788 msg
.wParam
= wParam
;
4789 msg
.lParam
= lParam
;
4790 msg
.descr
= "dialog";
4793 if (message
== WM_INITDIALOG
) EndDialog( hwnd
, 0 );
4797 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4799 DWORD style
, exstyle
;
4803 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4804 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4805 /* do not be confused by WS_DLGFRAME set */
4806 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4808 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
4809 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
4811 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4812 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4813 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4814 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
4816 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
4818 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4819 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
4820 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
4822 /* a subsequent call should do nothing */
4823 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4824 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4825 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4829 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
4830 ok( ret
, "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4831 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4832 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
4833 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
4836 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4838 DWORD style
, exstyle
;
4842 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4843 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4844 /* do not be confused by WS_DLGFRAME set */
4845 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4847 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
4848 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
4850 si
.cbSize
= sizeof(si
);
4851 si
.fMask
= SIF_RANGE
;
4854 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4855 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4856 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4858 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4860 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4861 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
4862 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
4864 /* a subsequent call should do nothing */
4865 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4866 if (style
& WS_HSCROLL
)
4867 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4868 else if (style
& WS_VSCROLL
)
4869 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4871 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4873 si
.fMask
= SIF_PAGE
;
4875 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4876 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4880 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4881 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4883 si
.fMask
= SIF_RANGE
;
4884 si
.nMin
= 0xdeadbeef;
4885 si
.nMax
= 0xdeadbeef;
4886 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4887 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
4888 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4889 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4890 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4893 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4894 static void test_scroll_messages(HWND hwnd
)
4905 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4906 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
4907 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4908 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4909 /* values of min and max are undefined */
4912 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4913 ok( ret
, "SetScrollRange error %ld\n", GetLastError());
4914 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4915 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4920 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4921 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
4922 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4923 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4924 /* values of min and max are undefined */
4927 si
.cbSize
= sizeof(si
);
4928 si
.fMask
= SIF_RANGE
;
4931 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4932 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4933 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4936 si
.fMask
= SIF_PAGE
;
4938 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4939 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4940 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4945 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4946 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4947 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4950 si
.fMask
= SIF_RANGE
;
4951 si
.nMin
= 0xdeadbeef;
4952 si
.nMax
= 0xdeadbeef;
4953 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
4954 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
4955 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
4956 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4957 /* values of min and max are undefined */
4960 /* set WS_HSCROLL */
4961 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4962 /* clear WS_HSCROLL */
4963 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4965 /* set WS_HSCROLL */
4966 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4967 /* clear WS_HSCROLL */
4968 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4970 /* set WS_VSCROLL */
4971 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4972 /* clear WS_VSCROLL */
4973 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4975 /* set WS_VSCROLL */
4976 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4977 /* clear WS_VSCROLL */
4978 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4981 static void test_showwindow(void)
4983 HWND hwnd
, hwnd2
, hchild
;
4986 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4987 100, 100, 200, 200, 0, 0, 0, NULL
);
4988 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4989 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4990 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
4991 ok (hchild
!= 0, "Failed to create child\n");
4994 /* ShowWindow( SW_SHOWNA) for invisible top level window */
4995 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
4996 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4997 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
4999 /* ShowWindow( SW_SHOWNA) for now visible top level window */
5000 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
5001 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5002 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
5003 /* back to invisible */
5004 ShowWindow(hchild
, SW_HIDE
);
5005 ShowWindow(hwnd
, SW_HIDE
);
5007 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
5008 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
5009 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5010 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
5011 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
5012 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
5014 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
5015 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5016 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
5017 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
5018 ShowWindow( hwnd
, SW_SHOW
);
5020 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
5021 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5022 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
5024 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
5025 ShowWindow( hchild
, SW_HIDE
);
5027 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
5028 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5029 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
5032 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
5033 DestroyWindow(hchild
);
5034 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
5036 DestroyWindow(hwnd
);
5041 * 1. Create invisible maximized popup window.
5042 * 2. Move and resize it.
5043 * 3. Show it maximized.
5045 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5046 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
5047 100, 100, 200, 200, 0, 0, 0, NULL
);
5048 ok (hwnd
!= 0, "Failed to create popup window\n");
5049 ok(IsZoomed(hwnd
), "window should be maximized\n");
5050 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5052 GetWindowRect(hwnd
, &rc
);
5053 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
5054 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
5055 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc
));
5056 /* Reset window's size & position */
5057 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
5058 ok(IsZoomed(hwnd
), "window should be maximized\n");
5061 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5062 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5063 ok(IsZoomed(hwnd
), "window should be maximized\n");
5064 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
5066 GetWindowRect(hwnd
, &rc
);
5067 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
5068 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
5069 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc
));
5070 DestroyWindow(hwnd
);
5074 * 1. Create invisible maximized popup window.
5075 * 2. Show it maximized.
5077 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5078 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
5079 100, 100, 200, 200, 0, 0, 0, NULL
);
5080 ok (hwnd
!= 0, "Failed to create popup window\n");
5081 ok(IsZoomed(hwnd
), "window should be maximized\n");
5082 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5084 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5085 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5086 ok(IsZoomed(hwnd
), "window should be maximized\n");
5087 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
5088 DestroyWindow(hwnd
);
5092 * 1. Create visible maximized popup window.
5094 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
5095 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
5096 100, 100, 200, 200, 0, 0, 0, NULL
);
5097 ok (hwnd
!= 0, "Failed to create popup window\n");
5098 ok(IsZoomed(hwnd
), "window should be maximized\n");
5099 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5100 DestroyWindow(hwnd
);
5104 * 1. Create visible popup window.
5107 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
5108 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
5109 100, 100, 200, 200, 0, 0, 0, NULL
);
5110 ok (hwnd
!= 0, "Failed to create popup window\n");
5111 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
5112 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
5114 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
5115 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5116 ok(IsZoomed(hwnd
), "window should be maximized\n");
5117 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
5118 DestroyWindow(hwnd
);
5122 * 1. Restoring a minimized window.
5124 hwnd
= CreateWindowA("TestWindowClass", "window1", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5125 ok(hwnd
!= NULL
, "Failed to create window\n");
5127 hwnd2
= CreateWindowA("static", "window2", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5128 ok(hwnd2
!= NULL
, "Failed to create window\n");
5130 ShowWindow(hwnd
, SW_MINIMIZE
);
5131 SetActiveWindow(hwnd2
);
5132 ok(GetActiveWindow() == hwnd2
, "Unexpected active window\n");
5135 ShowWindow(hwnd
, SW_RESTORE
);
5137 ok_sequence(WmShowRestoreMinimizedOverlappedSeq
,
5138 "ShowWindow(hwnd, SW_RESTORE): minimized overlapped", TRUE
);
5140 ShowWindow(hwnd
, SW_MINIMIZE
);
5141 SetActiveWindow(hwnd2
);
5142 ok(GetActiveWindow() == hwnd2
, "Unexpected active window\n");
5145 ShowWindow(hwnd
, SW_SHOWNOACTIVATE
);
5147 ok_sequence(WmShowNoActivateMinimizedOverlappedSeq
,
5148 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): minimized overlapped", TRUE
);
5150 DestroyWindow(hwnd2
);
5151 DestroyWindow(hwnd
);
5155 * 1. Restoring a minimized but active window.
5157 hwnd
= CreateWindowA("TestWindowClass", "parent", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5158 ok(hwnd
!= NULL
, "Failed to create window\n");
5160 ShowWindow(hwnd
, SW_MINIMIZE
);
5161 SetActiveWindow(hwnd
);
5162 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
5165 ShowWindow(hwnd
, SW_RESTORE
);
5167 ok_sequence(WmShowRestoreActiveMinimizedOverlappedSeq
,
5168 "ShowWindow(hwnd, SW_RESTORE): active minimized overlapped", TRUE
);
5170 ShowWindow(hwnd
, SW_MINIMIZE
);
5171 SetActiveWindow(hwnd
);
5172 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
5175 ShowWindow(hwnd
, SW_SHOWNOACTIVATE
);
5177 ok_sequence(WmShowNoActivateActiveMinimizedOverlappedSeq
,
5178 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): active minimized overlapped", TRUE
);
5180 DestroyWindow(hwnd
);
5184 static void test_sys_menu(void)
5190 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5191 100, 100, 200, 200, 0, 0, 0, NULL
);
5192 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5196 /* test existing window without CS_NOCLOSE style */
5197 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5198 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5200 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5201 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5202 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
5204 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
5205 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
5207 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5208 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5209 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
5211 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
5212 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
5214 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5215 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5216 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
5218 /* test whether removing WS_SYSMENU destroys a system menu */
5219 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
5220 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5222 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5223 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5225 DestroyWindow(hwnd
);
5227 /* test new window with CS_NOCLOSE style */
5228 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5229 100, 100, 200, 200, 0, 0, 0, NULL
);
5230 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5232 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5233 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5235 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5236 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5238 DestroyWindow(hwnd
);
5240 /* test new window without WS_SYSMENU style */
5241 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
5242 100, 100, 200, 200, 0, 0, 0, NULL
);
5243 ok(hwnd
!= 0, "Failed to create overlapped window\n");
5245 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5246 ok(!hmenu
, "GetSystemMenu error %ld\n", GetLastError());
5248 DestroyWindow(hwnd
);
5251 /* For shown WS_OVERLAPPEDWINDOW */
5252 static const struct message WmSetIcon_1
[] = {
5253 { WM_SETICON
, sent
},
5254 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
5255 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5256 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
5260 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
5261 static const struct message WmSetIcon_2
[] = {
5262 { WM_SETICON
, sent
},
5266 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
5267 static const struct message WmInitEndSession
[] = {
5269 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
5273 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
5274 static const struct message WmInitEndSession_2
[] = {
5276 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
5280 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
5281 static const struct message WmInitEndSession_3
[] = {
5283 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
5287 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
5288 static const struct message WmInitEndSession_4
[] = {
5290 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
5294 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
5295 static const struct message WmInitEndSession_5
[] = {
5297 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
5301 static const struct message WmOptionalPaint
[] = {
5302 { WM_PAINT
, sent
|optional
},
5303 { WM_NCPAINT
, sent
|beginpaint
|optional
},
5304 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
5305 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
5309 static const struct message WmZOrder
[] = {
5310 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
5311 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
5312 { HCBT_ACTIVATE
, hook
},
5313 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
5314 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
5315 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
5316 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
5317 { WM_GETTEXT
, sent
|optional
},
5318 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
5319 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
5320 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
5321 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5322 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5323 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
5324 { HCBT_SETFOCUS
, hook
},
5325 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5326 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5327 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5328 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5329 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
5330 { WM_GETTEXT
, sent
|optional
},
5331 { WM_NCCALCSIZE
, sent
|optional
},
5332 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
5336 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
5341 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
5346 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5347 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5349 PostMessageA(hwnd
, WM_USER
, 0, 0);
5351 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5352 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5354 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5355 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5357 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5358 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5360 PostMessageA(hwnd
, WM_USER
, 0, 0);
5362 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5363 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5365 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5366 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5368 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
5369 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5370 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5372 PostMessageA(hwnd
, WM_USER
, 0, 0);
5374 /* new incoming message causes it to become signaled again */
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
);
5380 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5381 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5383 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
5384 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5385 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5386 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5388 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_INPUTAVAILABLE
);
5389 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5391 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5392 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5394 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
5395 ret
= QueueUserAPC( apc_test_proc
, GetCurrentThread(), 0 );
5396 ok(ret
, "QueueUserAPC failed %lu\n", GetLastError());
5398 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, 0 );
5399 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5401 /* but even with MWMO_ALERTABLE window events are preferred */
5402 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5404 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5405 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5407 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5408 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5410 /* the APC call is still queued */
5411 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5412 ok(ret
== WAIT_IO_COMPLETION
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5415 static void test_WM_DEVICECHANGE(HWND hwnd
)
5420 static const WPARAM wparams
[] = {0,
5421 DBT_DEVNODES_CHANGED
,
5422 DBT_QUERYCHANGECONFIG
,
5424 DBT_CONFIGCHANGECANCELED
,
5427 DBT_CONFIGMGPRIVATE
, /* 0x7fff */
5428 DBT_DEVICEARRIVAL
, /* 0x8000 */
5429 DBT_DEVICEQUERYREMOVE
,
5430 DBT_DEVICEQUERYREMOVEFAILED
,
5431 DBT_DEVICEREMOVEPENDING
,
5432 DBT_DEVICEREMOVECOMPLETE
,
5433 DBT_DEVICETYPESPECIFIC
,
5436 for (i
= 0; i
< ARRAY_SIZE(wparams
); i
++)
5438 SetLastError(0xdeadbeef);
5439 ret
= PostMessageA(hwnd
, WM_DEVICECHANGE
, wparams
[i
], 0);
5440 if (wparams
[i
] & 0x8000)
5442 ok(ret
== FALSE
, "PostMessage returned %ld\n", ret
);
5443 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY
, "PostMessage error %08lx\n", GetLastError());
5447 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5448 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5449 memset(&msg
, 0, sizeof(msg
));
5450 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5451 ok(msg
.message
== WM_DEVICECHANGE
, "got %04x instead of WM_DEVICECHANGE\n", msg
.message
);
5456 static DWORD CALLBACK
hide_window_thread( LPVOID arg
)
5460 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
5461 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5466 static DWORD CALLBACK
show_window_thread( LPVOID arg
)
5470 /* function will not return if ShowWindow(SW_SHOW) calls SendMessage() */
5471 ok( ShowWindow( hwnd
, SW_SHOW
), "ShowWindow(SW_SHOW) expected TRUE\n" ); /* actually it's 24... */
5476 /* Helper function to easier test SetWindowPos messages */
5477 #define test_msg_setpos( expected_list, flags, todo ) \
5478 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
5479 static void test_msg_setpos_(const struct message
*expected_list
, UINT flags
, BOOL todo
, const char *file
, int line
)
5485 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5486 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5487 ok (hwnd
!= 0, "Failed to create popup window\n");
5488 SetWindowPos(hwnd
, NULL
, 0, 0, 100, 100, flags
);
5489 ok_sequence_(expected_list
, "SetWindowPos:show_popup_first_show_window", todo
, file
, line
);
5490 DestroyWindow(hwnd
);
5493 /* test if we receive the right sequence of messages */
5494 static void test_messages(void)
5498 HWND hwnd
, hparent
, hchild
;
5499 HWND hchild2
, hbutton
;
5508 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5509 100, 100, 200, 200, 0, 0, 0, NULL
);
5510 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5511 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5513 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5514 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
5515 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
5517 /* test WM_SETREDRAW on a not visible top level window */
5518 test_WM_SETREDRAW(hwnd
);
5520 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5522 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
5523 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
5525 ok(GetActiveWindow() == hwnd
, "window should be active\n");
5526 ok(GetFocus() == hwnd
, "window should have input focus\n");
5527 ShowWindow(hwnd
, SW_HIDE
);
5529 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5531 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5532 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5534 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5536 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5537 hthread
= CreateThread( NULL
, 0, hide_window_thread
, hwnd
, 0, &tid
);
5538 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
5539 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5540 CloseHandle(hthread
);
5542 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5544 ShowWindow(hwnd
, SW_SHOW
);
5546 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
5548 /* test ShowWindow(SW_SHOW) on a visible window - multi-threaded */
5549 hthread
= CreateThread( NULL
, 0, show_window_thread
, hwnd
, 0, &tid
);
5550 ok( hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError() );
5551 ok( WaitForSingleObject( hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
5552 CloseHandle( hthread
);
5554 ok_sequence( WmEmptySeq
, "ShowWindow(SW_SHOW):overlapped", FALSE
);
5556 ShowWindow(hwnd
, SW_HIDE
);
5558 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5560 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5562 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
5565 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
5567 ShowWindow(hwnd
, SW_RESTORE
);
5569 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5573 ShowWindow(hwnd
, SW_MINIMIZE
);
5575 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE
);
5578 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
5580 ShowWindow(hwnd
, SW_RESTORE
);
5582 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", FALSE
);
5586 ShowWindow(hwnd
, SW_SHOW
);
5588 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
5590 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5591 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
5592 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
5593 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
5595 /* test WM_SETREDRAW on a visible top level window */
5596 ShowWindow(hwnd
, SW_SHOW
);
5598 test_WM_SETREDRAW(hwnd
);
5600 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
5601 test_scroll_messages(hwnd
);
5603 /* test resizing and moving */
5604 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
5605 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
5608 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
5609 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
5612 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
5613 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
5617 /* popups don't get WM_GETMINMAXINFO */
5618 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
5619 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5621 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
5622 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
5624 DestroyWindow(hwnd
);
5625 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
5627 /* Test if windows are correctly drawn when first shown */
5629 /* Visible, redraw */
5632 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5633 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5634 ok (hwnd
!= 0, "Failed to create popup window\n");
5635 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5636 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_visible", FALSE
);
5637 DestroyWindow(hwnd
);
5639 /* Invisible, show, message */
5642 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5643 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5644 ok (hwnd
!= 0, "Failed to create popup window\n");
5645 ShowWindow(hwnd
, SW_SHOW
);
5646 SendMessageW(hwnd
, WM_PAINT
, 0, 0);
5647 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_show", FALSE
);
5648 DestroyWindow(hwnd
);
5650 /* Invisible, show maximized, redraw */
5653 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5654 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5655 ok (hwnd
!= 0, "Failed to create popup window\n");
5656 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5657 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5658 ok_sequence(WmShowPopupFirstDrawSeq_2
, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE
);
5659 DestroyWindow(hwnd
);
5661 /* Test SetWindowPos */
5662 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
, FALSE
);
5663 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, 0, FALSE
);
5664 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
,
5665 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_NOZORDER
, FALSE
);
5667 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOSIZE
, FALSE
);
5668 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOMOVE
, FALSE
);
5669 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTSIZE
, FALSE
);
5670 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTMOVE
, FALSE
);
5671 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOZORDER
, FALSE
);
5673 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
, FALSE
);
5674 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTMOVE
, FALSE
);
5675 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTSIZE
, FALSE
);
5676 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOMOVE
, FALSE
);
5677 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOSIZE
, FALSE
);
5678 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOZORDER
, FALSE
);
5680 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
, FALSE
);
5681 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTMOVE
, FALSE
);
5682 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTSIZE
, FALSE
);
5683 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOMOVE
, FALSE
);
5684 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOSIZE
, FALSE
);
5685 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOZORDER
, FALSE
);
5687 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
, FALSE
);
5688 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTMOVE
, FALSE
);
5689 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTSIZE
, FALSE
);
5690 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOMOVE
, FALSE
);
5691 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOSIZE
, FALSE
);
5692 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOZORDER
, FALSE
);
5694 /* Test SetWindowPos with child windows */
5696 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5697 100, 100, 200, 200, 0, 0, 0, NULL
);
5698 ok (hparent
!= 0, "Failed to create parent window\n");
5700 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5701 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5702 ok (hchild
!= 0, "Failed to create child window\n");
5704 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5705 ok_sequence(WmFirstDrawChildSeq1
, /* Expect no messages for the child */
5706 "SetWindowPos:show_popup_first_show_window_child1", FALSE
);
5707 DestroyWindow(hchild
);
5708 DestroyWindow(hparent
);
5711 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
,
5712 100, 100, 200, 200, 0, 0, 0, NULL
);
5713 ok (hparent
!= 0, "Failed to create parent window\n");
5715 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5716 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5717 ok (hchild
!= 0, "Failed to create child window\n");
5719 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5720 ok_sequence(WmFirstDrawChildSeq2
, /* Expect child to be redrawn */
5721 "SetWindowPos:show_popup_first_show_window_child2", FALSE
);
5722 DestroyWindow(hchild
);
5723 DestroyWindow(hparent
);
5725 /* Test message sequence for extreme position and size */
5728 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5729 -10, -10, 10000, 10000, NULL
, 0, 0, NULL
);
5730 ok (hwnd
!= 0, "Failed to create popup window\n");
5731 ok_sequence(WmShowPopupExtremeLocationSeq
, "RedrawWindow:show_popup_extreme_location", FALSE
);
5732 DestroyWindow(hwnd
);
5735 /* Test child windows */
5737 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5738 100, 100, 200, 200, 0, 0, 0, NULL
);
5739 ok (hparent
!= 0, "Failed to create parent window\n");
5742 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
5743 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5744 ok (hchild
!= 0, "Failed to create child window\n");
5745 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
5746 DestroyWindow(hchild
);
5749 /* visible child window with a caption */
5750 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
5751 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
5752 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5753 ok (hchild
!= 0, "Failed to create child window\n");
5754 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
5756 trace("testing scroll APIs on a visible child window %p\n", hchild
);
5757 test_scroll_messages(hchild
);
5759 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5760 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
5762 DestroyWindow(hchild
);
5765 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5766 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5767 ok (hchild
!= 0, "Failed to create child window\n");
5768 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5770 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
5771 100, 100, 50, 50, hparent
, 0, 0, NULL
);
5772 ok (hchild2
!= 0, "Failed to create child2 window\n");
5775 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
5776 0, 100, 50, 50, hchild
, 0, 0, NULL
);
5777 ok (hbutton
!= 0, "Failed to create button window\n");
5779 /* test WM_SETREDRAW on a not visible child window */
5780 test_WM_SETREDRAW(hchild
);
5782 ShowWindow(hchild
, SW_SHOW
);
5783 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5785 /* check parent messages too */
5786 log_all_parent_messages
++;
5787 ShowWindow(hchild
, SW_HIDE
);
5788 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
5789 log_all_parent_messages
--;
5791 ShowWindow(hchild
, SW_SHOW
);
5792 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5794 ShowWindow(hchild
, SW_HIDE
);
5795 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
5797 ShowWindow(hchild
, SW_SHOW
);
5798 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5800 /* test WM_SETREDRAW on a visible child window */
5801 test_WM_SETREDRAW(hchild
);
5803 log_all_parent_messages
++;
5804 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
5805 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
5806 log_all_parent_messages
--;
5808 ShowWindow(hchild
, SW_HIDE
);
5810 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5811 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
5813 ShowWindow(hchild
, SW_HIDE
);
5815 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
5816 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
5818 /* DestroyWindow sequence below expects that a child has focus */
5822 DestroyWindow(hchild
);
5823 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
5824 DestroyWindow(hchild2
);
5825 DestroyWindow(hbutton
);
5828 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
5829 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5830 ok (hchild
!= 0, "Failed to create child popup window\n");
5831 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
5832 DestroyWindow(hchild
);
5834 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5836 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
5837 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5838 ok (hchild
!= 0, "Failed to create popup window\n");
5839 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5840 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5841 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5843 ShowWindow(hchild
, SW_SHOW
);
5844 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5846 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5847 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5849 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5850 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
5851 DestroyWindow(hchild
);
5853 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5854 * changes nothing in message sequences.
5857 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5858 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5859 ok (hchild
!= 0, "Failed to create popup window\n");
5860 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5861 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5862 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5864 ShowWindow(hchild
, SW_SHOW
);
5865 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5867 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5868 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5869 DestroyWindow(hchild
);
5872 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
5873 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5874 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5875 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
5878 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
5879 test_scroll_messages(hwnd
);
5885 SendMessageA(hwnd
, WM_NULL
, 0, 0);
5888 after_end_dialog
= TRUE
;
5889 EndDialog( hwnd
, 0 );
5890 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
5892 DestroyWindow(hwnd
);
5893 after_end_dialog
= FALSE
;
5894 test_def_id
= FALSE
;
5896 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
5897 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5899 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
5900 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
5901 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5903 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
5904 ShowWindow(hwnd
, SW_SHOW
);
5905 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
5909 ret
= DrawMenuBar(hwnd
);
5910 ok(ret
, "DrawMenuBar failed: %ld\n", GetLastError());
5912 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5913 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
5915 DestroyWindow(hwnd
);
5917 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_CHILD
|WS_VISIBLE
,
5918 0, 0, 100, 100, hparent
, 0, GetModuleHandleA(0), NULL
);
5919 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5922 ret
= DrawMenuBar(hwnd
);
5923 ok(ret
, "DrawMenuBar failed: %ld\n", GetLastError());
5925 ok_sequence(WmEmptySeq
, "DrawMenuBar for a child window", FALSE
);
5927 DestroyWindow(hwnd
);
5930 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
5931 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
5933 DestroyWindow(hparent
);
5936 /* Message sequence for SetMenu */
5937 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
5938 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %ld\n", GetLastError());
5939 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
5941 hmenu
= CreateMenu();
5942 ok (hmenu
!= 0, "Failed to create menu\n");
5943 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
5944 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5945 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
5946 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5947 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5948 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
5949 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5950 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
5951 ShowWindow(hwnd
, SW_SHOW
);
5952 UpdateWindow( hwnd
);
5955 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5956 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
5957 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
5958 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
5960 UpdateWindow( hwnd
);
5963 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
5965 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5967 DestroyWindow(hwnd
);
5970 /* Message sequence for EnableWindow */
5971 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5972 100, 100, 200, 200, 0, 0, 0, NULL
);
5973 ok (hparent
!= 0, "Failed to create parent window\n");
5974 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5975 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5976 ok (hchild
!= 0, "Failed to create child window\n");
5982 EnableWindow(hparent
, FALSE
);
5983 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
5985 EnableWindow(hparent
, FALSE
);
5986 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(FALSE)", FALSE
);
5988 EnableWindow(hparent
, TRUE
);
5989 ok_sequence(WmEnableWindowSeq_3
, "EnableWindow(TRUE)", FALSE
);
5991 EnableWindow(hparent
, TRUE
);
5992 ok_sequence(WmEnableWindowSeq_4
, "EnableWindow(TRUE)", FALSE
);
5997 test_MsgWaitForMultipleObjects(hparent
);
5998 test_WM_DEVICECHANGE(hparent
);
6000 /* the following test causes an exception in user.exe under win9x */
6001 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
6003 DestroyWindow(hparent
);
6007 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
6008 /* PeekMessage(NULL) fails, but still removes the message */
6009 SetLastError(0xdeadbeef);
6010 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
6011 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
6012 GetLastError() == 0xdeadbeef, /* NT4 */
6013 "last error is %ld\n", GetLastError() );
6014 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
6015 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
6017 DestroyWindow(hchild
);
6018 DestroyWindow(hparent
);
6021 /* Message sequences for WM_SETICON */
6022 trace("testing WM_SETICON\n");
6023 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
6024 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6026 ShowWindow(hwnd
, SW_SHOW
);
6030 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6031 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
6033 ShowWindow(hwnd
, SW_HIDE
);
6036 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6037 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
6038 DestroyWindow(hwnd
);
6041 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
6042 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6044 ShowWindow(hwnd
, SW_SHOW
);
6048 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6049 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
6051 ShowWindow(hwnd
, SW_HIDE
);
6054 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6055 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
6058 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
6061 todo_wine
win_skip( "Message 0x3b not supported\n" );
6064 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
6065 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %Id\n", res
);
6066 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
6067 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
6068 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %Id\n", res
);
6069 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
6070 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
6071 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %Id\n", res
);
6074 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
6075 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
6076 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %Id\n", res
);
6077 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
6078 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
6079 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %Id\n", res
);
6081 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
6082 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
6083 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %Id\n", res
);
6085 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
6086 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
6087 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %Id\n", res
);
6090 DestroyWindow(hwnd
);
6094 static const struct message WmFrameChanged
[] = {
6095 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
, 0 },
6096 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0xf },
6097 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
6098 |SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0xf },
6099 { WM_GETTEXT
, sent
|optional
},
6100 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6101 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
6105 static const struct message WmFrameChanged_move
[] = {
6106 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
, 0 },
6107 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0x3 },
6108 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
6109 |SWP_NOSIZE
|SWP_NOCLIENTSIZE
, 0x3 },
6110 { WM_MOVE
, sent
|defwinproc
, 0 },
6111 { WM_GETTEXT
, sent
|optional
},
6112 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6113 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
6117 static void test_setwindowpos(void)
6124 const INT winX
= 100;
6125 const INT winY
= 100;
6126 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
6128 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
6129 X
, Y
, winX
, winY
, 0,
6132 GetWindowRect(hwnd
, &rc
);
6133 expect(sysX
+ X
, rc
.right
);
6134 expect(winY
+ Y
, rc
.bottom
);
6138 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 50, 50, winX
, winY
, 0);
6139 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
6140 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id\n", res
);
6142 GetWindowRect(hwnd
, &rc
);
6143 expect(sysX
+ X
, rc
.right
);
6144 expect(winY
+ Y
, rc
.bottom
);
6146 res
= SetWindowPos( hwnd
, 0, 0, 0, 0, 0,
6147 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
6148 ok_sequence(WmFrameChanged
, "FrameChanged", FALSE
);
6149 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id.\n", res
);
6151 GetWindowRect(hwnd
, &rc
);
6152 expect(sysX
+ X
, rc
.right
);
6153 expect(winY
+ Y
, rc
.bottom
);
6155 res
= SetWindowPos( hwnd
, 0, 0, 0, 0, 0,
6156 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
6157 ok_sequence(WmFrameChanged_move
, "FrameChanged", FALSE
);
6158 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id.\n", res
);
6160 GetWindowRect(hwnd
, &rc
);
6161 expect(sysX
, rc
.right
);
6162 expect(winY
, rc
.bottom
);
6164 DestroyWindow(hwnd
);
6167 static void invisible_parent_tests(void)
6169 HWND hparent
, hchild
;
6171 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
6172 100, 100, 200, 200, 0, 0, 0, NULL
);
6173 ok (hparent
!= 0, "Failed to create parent window\n");
6176 /* test showing child with hidden parent */
6178 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6179 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6180 ok (hchild
!= 0, "Failed to create child window\n");
6181 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
6183 ShowWindow( hchild
, SW_MINIMIZE
);
6184 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
6185 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6186 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6191 ShowWindow( hchild
, SW_MINIMIZE
);
6192 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
6194 DestroyWindow(hchild
);
6195 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6196 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6199 ShowWindow( hchild
, SW_MAXIMIZE
);
6200 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
6201 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6202 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6207 ShowWindow( hchild
, SW_MAXIMIZE
);
6208 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
6210 DestroyWindow(hchild
);
6211 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6212 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6215 ShowWindow( hchild
, SW_RESTORE
);
6216 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
6217 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6218 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6220 DestroyWindow(hchild
);
6221 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6222 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6225 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
6226 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
6227 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6228 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6233 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
6234 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
6236 DestroyWindow(hchild
);
6237 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6238 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6241 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
6242 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
6243 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
6244 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6245 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6247 DestroyWindow(hchild
);
6248 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6249 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6252 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
6253 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
6254 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6255 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6260 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
6261 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
6263 DestroyWindow(hchild
);
6264 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6265 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6268 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
6269 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
6270 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
6272 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
6274 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6276 DestroyWindow(hchild
);
6277 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6278 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6281 ShowWindow( hchild
, SW_SHOWNA
);
6282 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
6283 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6284 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6289 ShowWindow( hchild
, SW_SHOWNA
);
6290 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
6292 DestroyWindow(hchild
);
6293 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6294 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6297 ShowWindow( hchild
, SW_SHOW
);
6298 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
6299 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6300 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6305 ShowWindow( hchild
, SW_SHOW
);
6306 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
6308 ShowWindow( hchild
, SW_HIDE
);
6309 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
6310 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
6311 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6313 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6314 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
6315 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6316 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6318 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6319 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
6320 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
6321 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6323 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6325 DestroyWindow(hchild
);
6326 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
6328 DestroyWindow(hparent
);
6332 /****************** button message test *************************/
6333 #define ID_BUTTON 0x000e
6335 static const struct message WmSetFocusButtonSeq
[] =
6337 { HCBT_SETFOCUS
, hook
},
6338 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6339 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6340 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6341 { WM_SETFOCUS
, sent
|wparam
, 0 },
6342 { WM_CTLCOLORBTN
, sent
|parent
},
6343 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6344 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6347 static const struct message WmKillFocusButtonSeq
[] =
6349 { HCBT_SETFOCUS
, hook
},
6350 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6351 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6352 { WM_CTLCOLORBTN
, sent
|parent
},
6353 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6354 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6355 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6356 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6358 { WM_CTLCOLORBTN
, sent
|parent
},
6361 static const struct message WmSetFocusStaticSeq
[] =
6363 { HCBT_SETFOCUS
, hook
},
6364 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6365 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6366 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6367 { WM_SETFOCUS
, sent
|wparam
, 0 },
6368 { WM_CTLCOLORSTATIC
, sent
|parent
},
6369 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6370 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
6371 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6374 static const struct message WmKillFocusStaticSeq
[] =
6376 { HCBT_SETFOCUS
, hook
},
6377 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6378 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6379 { WM_CTLCOLORSTATIC
, sent
|parent
},
6380 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6381 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6382 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6383 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6385 { WM_CTLCOLORSTATIC
, sent
|parent
},
6388 static const struct message WmSetFocusOwnerdrawSeq
[] =
6390 { HCBT_SETFOCUS
, hook
},
6391 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6392 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6393 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6394 { WM_SETFOCUS
, sent
|wparam
, 0 },
6395 { WM_CTLCOLORBTN
, sent
|parent
},
6396 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
6397 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6398 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6401 static const struct message WmKillFocusOwnerdrawSeq
[] =
6403 { HCBT_SETFOCUS
, hook
},
6404 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6405 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6406 { WM_CTLCOLORBTN
, sent
|parent
},
6407 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
6408 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6409 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6410 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6411 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6413 { WM_CTLCOLORBTN
, sent
|parent
},
6414 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6417 static const struct message WmLButtonDownSeq
[] =
6419 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6420 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6421 { HCBT_SETFOCUS
, hook
},
6422 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6423 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6424 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6425 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6426 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6427 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6428 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6429 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6432 static const struct message WmLButtonDownStaticSeq
[] =
6434 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6435 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6436 { HCBT_SETFOCUS
, hook
},
6437 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6438 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6439 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6440 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6441 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6442 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6443 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6444 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6447 static const struct message WmLButtonUpSeq
[] =
6449 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6450 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6451 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6452 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6453 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6454 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6457 static const struct message WmLButtonUpStaticSeq
[] =
6459 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6460 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6461 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6462 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6463 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6464 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6467 static const struct message WmLButtonUpAutoSeq
[] =
6469 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6470 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6471 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6472 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6473 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
6474 { BM_SETCHECK
, sent
|defwinproc
},
6475 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
, 0, 0 }, /* Sent here on Win7. */
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_CTLCOLORSTATIC
, sent
|defwinproc
|optional
, 0, 0 }, /* Sent here on Win8+. */
6479 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6482 static const struct message WmLButtonUpBrokenSeq
[] =
6484 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6487 static const struct message WmSetFontButtonSeq
[] =
6489 { WM_SETFONT
, sent
},
6491 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6492 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6493 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
6496 static const struct message WmSetFontStaticSeq
[] =
6498 { WM_SETFONT
, sent
},
6500 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6501 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6504 static const struct message WmSetTextButtonSeq
[] =
6506 { WM_SETTEXT
, sent
},
6507 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6508 { WM_CTLCOLORBTN
, sent
|parent
},
6509 { WM_CTLCOLORBTN
, sent
|parent
},
6510 { WM_COMMAND
, sent
|parent
|optional
},
6511 { WM_DRAWITEM
, sent
|parent
|optional
},
6514 static const struct message WmSetTextStaticSeq
[] =
6516 { WM_SETTEXT
, sent
},
6517 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6518 { WM_CTLCOLORSTATIC
, sent
|parent
},
6519 { WM_CTLCOLORSTATIC
, sent
|parent
},
6522 static const struct message WmSetTextGroupSeq
[] =
6524 { WM_SETTEXT
, sent
},
6525 { WM_CTLCOLORSTATIC
, sent
|parent
},
6526 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6527 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6528 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6531 static const struct message WmSetTextInvisibleSeq
[] =
6533 { WM_SETTEXT
, sent
},
6534 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6537 static const struct message WmSetStyleButtonSeq
[] =
6539 { BM_SETSTYLE
, sent
},
6540 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6541 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6543 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6544 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6545 { WM_CTLCOLORBTN
, sent
|parent
},
6548 static const struct message WmSetStyleStaticSeq
[] =
6550 { BM_SETSTYLE
, sent
},
6551 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6552 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6554 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6555 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6556 { WM_CTLCOLORSTATIC
, sent
|parent
},
6559 static const struct message WmSetStyleUserSeq
[] =
6561 { BM_SETSTYLE
, sent
},
6562 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6563 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6565 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6566 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6567 { WM_CTLCOLORBTN
, sent
|parent
},
6568 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
6571 static const struct message WmSetStyleOwnerdrawSeq
[] =
6573 { BM_SETSTYLE
, sent
},
6574 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6575 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6577 { WM_NCPAINT
, sent
|optional
}, /* FIXME: Wine sends it */
6578 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6579 { WM_CTLCOLORBTN
, sent
|parent
},
6580 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
6581 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6584 static const struct message WmSetStateButtonSeq
[] =
6586 { BM_SETSTATE
, sent
},
6587 { WM_CTLCOLORBTN
, sent
|parent
},
6588 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6589 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6592 static const struct message WmSetStateStaticSeq
[] =
6594 { BM_SETSTATE
, sent
},
6595 { WM_CTLCOLORSTATIC
, sent
|parent
},
6596 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6597 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6600 static const struct message WmSetStateUserSeq
[] =
6602 { BM_SETSTATE
, sent
},
6603 { WM_CTLCOLORBTN
, sent
|parent
},
6604 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
6605 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6606 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6609 static const struct message WmSetStateOwnerdrawSeq
[] =
6611 { BM_SETSTATE
, sent
},
6612 { WM_CTLCOLORBTN
, sent
|parent
},
6613 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
6614 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6615 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6618 static const struct message WmClearStateButtonSeq
[] =
6620 { BM_SETSTATE
, sent
},
6621 { WM_CTLCOLORBTN
, sent
|parent
},
6622 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
6623 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6624 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6627 static const struct message WmDisableButtonSeq
[] =
6629 { WM_LBUTTONDOWN
, sent
},
6630 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6631 { BM_SETSTATE
, sent
|defwinproc
},
6632 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6633 { WM_CTLCOLORBTN
, sent
|optional
},
6634 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6635 { WM_LBUTTONUP
, sent
},
6636 { BM_SETSTATE
, sent
|defwinproc
},
6637 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
},
6638 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6639 { BM_SETCHECK
, sent
|defwinproc
|optional
},
6640 { WM_CTLCOLORBTN
, sent
|optional
},
6641 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6642 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
6643 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6644 { WM_CAPTURECHANGED
, sent
|defwinproc
},
6645 { WM_COMMAND
, sent
},
6648 static const struct message WmClearStateOwnerdrawSeq
[] =
6650 { BM_SETSTATE
, sent
},
6651 { WM_CTLCOLORBTN
, sent
|parent
},
6652 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
6653 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
6654 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6657 static const struct message WmSetCheckIgnoredSeq
[] =
6659 { BM_SETCHECK
, sent
},
6660 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6663 static const struct message WmSetCheckStaticSeq
[] =
6665 { BM_SETCHECK
, sent
},
6666 { WM_CTLCOLORSTATIC
, sent
|parent
},
6667 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
6668 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6672 static WNDPROC old_button_proc
;
6674 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6676 static LONG defwndproc_counter
= 0;
6678 struct recvd_message msg
;
6680 if (ignore_message( message
)) return 0;
6688 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
6690 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6696 MSG
*msg
= (MSG
*)lParam
;
6697 lParam
= MAKELPARAM(msg
->message
, msg
->wParam
);
6699 wParam
= (ULONG_PTR
)GetMenu(hwnd
);
6704 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6709 msg
.message
= message
;
6710 msg
.flags
= sent
|wparam
|lparam
;
6711 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6712 msg
.wParam
= wParam
;
6713 msg
.lParam
= lParam
;
6714 msg
.descr
= "button";
6718 defwndproc_counter
++;
6719 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
6720 defwndproc_counter
--;
6725 static void subclass_button(void)
6729 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
6731 old_button_proc
= cls
.lpfnWndProc
;
6733 cls
.hInstance
= GetModuleHandleA(NULL
);
6734 cls
.lpfnWndProc
= button_hook_proc
;
6735 cls
.lpszClassName
= "my_button_class";
6736 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6737 if (!RegisterClassA(&cls
)) assert(0);
6740 static void test_button_messages(void)
6746 const struct message
*setfocus
;
6747 const struct message
*killfocus
;
6748 const struct message
*setstyle
;
6749 const struct message
*setstate
;
6750 const struct message
*clearstate
;
6751 const struct message
*setcheck
;
6752 const struct message
*lbuttondown
;
6753 const struct message
*lbuttonup
;
6754 const struct message
*setfont
;
6755 const struct message
*settext
;
6757 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6758 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6759 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6760 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6761 WmSetTextButtonSeq
},
6762 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
6763 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6764 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6765 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6766 WmSetTextButtonSeq
},
6767 { BS_CHECKBOX
, DLGC_BUTTON
,
6768 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6769 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6770 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6771 WmSetTextStaticSeq
},
6772 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
6773 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6774 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6775 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6776 WmSetTextStaticSeq
},
6777 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6778 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6779 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6780 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6781 WmSetTextStaticSeq
},
6782 { BS_3STATE
, DLGC_BUTTON
,
6783 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6784 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6785 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6786 WmSetTextStaticSeq
},
6787 { BS_AUTO3STATE
, DLGC_BUTTON
,
6788 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6789 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6790 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6791 WmSetTextStaticSeq
},
6792 { BS_GROUPBOX
, DLGC_STATIC
,
6793 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6794 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
,
6795 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6796 WmSetTextGroupSeq
},
6797 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6798 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
6799 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
,
6800 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6801 WmSetTextButtonSeq
},
6802 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6803 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6804 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6805 NULL
/* avoid infinite loop */, WmLButtonUpBrokenSeq
, WmSetFontStaticSeq
,
6806 WmSetTextStaticSeq
},
6807 { BS_OWNERDRAW
, DLGC_BUTTON
,
6808 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
6809 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
,
6810 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6811 WmSetTextButtonSeq
},
6813 LOGFONTA logfont
= { 0 };
6814 HFONT zfont
, hfont2
;
6819 /* selection with VK_SPACE should capture button window */
6820 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
6821 0, 0, 50, 14, 0, 0, 0, NULL
);
6822 ok(hwnd
!= 0, "Failed to create button window\n");
6825 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
6826 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6827 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
6828 DestroyWindow(hwnd
);
6832 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6833 100, 100, 200, 200, 0, 0, 0, NULL
);
6834 ok(parent
!= 0, "Failed to create parent window\n");
6836 memset(&logfont
, 0, sizeof(logfont
));
6837 logfont
.lfHeight
= -12;
6838 logfont
.lfWeight
= FW_NORMAL
;
6839 strcpy(logfont
.lfFaceName
, "Tahoma");
6841 hfont2
= CreateFontIndirectA(&logfont
);
6842 ok(hfont2
!= NULL
, "Failed to create Tahoma font\n");
6844 for (i
= 0; i
< ARRAY_SIZE(button
); i
++)
6852 trace("button style %08lx\n", button
[i
].style
);
6854 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
6855 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
6856 ok(hwnd
!= 0, "Failed to create button window\n");
6858 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6859 style
&= ~(WS_CHILD
| BS_NOTIFY
);
6860 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6861 if (button
[i
].style
== BS_USERBUTTON
)
6862 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %lx\n", style
);
6864 ok(style
== button
[i
].style
, "expected style %lx got %lx\n", button
[i
].style
, style
);
6866 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
6867 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08lx\n", i
, dlg_code
);
6869 ShowWindow(hwnd
, SW_SHOW
);
6876 log_all_parent_messages
++;
6878 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6880 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6881 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6882 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
6885 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6886 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6887 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
6889 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6891 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
6892 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6893 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6894 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
6896 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6897 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
6898 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
6899 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6901 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6902 ok(state
== 0, "expected state 0, got %04lx\n", state
);
6906 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
6907 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6908 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6909 ok_sequence(button
[i
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
6911 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6912 ok(state
== 0x0004, "expected state 0x0004, got %04lx\n", state
);
6914 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6915 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6916 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6920 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
6921 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6922 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6923 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
6925 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6926 ok(state
== 0, "expected state 0, got %04lx\n", state
);
6928 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6929 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6930 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6932 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6933 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04lx\n", state
);
6937 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
6938 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6939 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6940 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
6942 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6943 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04lx\n", state
);
6945 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6946 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6947 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6951 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
6952 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6953 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6954 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
6956 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 1");
6957 sprintf(desc
, "button[%i]: WM_SETTEXT on a visible button", i
);
6958 ok_sequence(button
[i
].settext
, desc
, FALSE
);
6960 ShowWindow(hwnd
, SW_HIDE
);
6964 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 2");
6965 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6966 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6968 ShowWindow(hwnd
, SW_SHOW
);
6969 ShowWindow(parent
, SW_HIDE
);
6973 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 3");
6974 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6975 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6977 ShowWindow(parent
, SW_SHOW
);
6980 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6981 if (button
[i
].style
== BS_PUSHBUTTON
||
6982 button
[i
].style
== BS_DEFPUSHBUTTON
||
6983 button
[i
].style
== BS_GROUPBOX
||
6984 button
[i
].style
== BS_USERBUTTON
||
6985 button
[i
].style
== BS_OWNERDRAW
)
6986 ok(state
== BST_UNCHECKED
, "expected check 0, got %04lx\n", state
);
6988 ok(state
== BST_CHECKED
, "expected check 1, got %04lx\n", state
);
6990 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6991 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6992 if (button
[i
].style
== BS_RADIOBUTTON
||
6993 button
[i
].style
== BS_AUTORADIOBUTTON
)
6994 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04lx | WS_TABSTOP got %04lx\n", button
[i
].style
, style
);
6996 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6998 log_all_parent_messages
--;
7000 DestroyWindow(hwnd
);
7002 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
7003 0, 0, 50, 14, 0, 0, 0, NULL
);
7004 ok(hwnd
!= 0, "Failed to create button window\n");
7006 SetForegroundWindow(hwnd
);
7009 SetActiveWindow(hwnd
);
7013 if (button
[i
].lbuttondown
)
7015 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
7016 sprintf(desc
, "button[%i]: WM_LBUTTONDOWN on a button", i
);
7017 ok_sequence(button
[i
].lbuttondown
, desc
, FALSE
);
7020 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
7021 sprintf(desc
, "button[%i]: WM_LBUTTONUP on a button", i
);
7022 ok_sequence(button
[i
].lbuttonup
, desc
, FALSE
);
7025 zfont
= GetStockObject(DEFAULT_GUI_FONT
);
7026 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
7028 sprintf(desc
, "button[%i]: WM_SETFONT on a button", i
);
7029 ok_sequence(button
[i
].setfont
, desc
, FALSE
);
7031 /* Test that original font is not selected back after painting */
7032 hdc
= CreateCompatibleDC(0);
7034 prevfont
= SelectObject(hdc
, hfont2
);
7035 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
7036 SendMessageA(hwnd
, WM_PRINTCLIENT
, (WPARAM
)hdc
, 0);
7037 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i
);
7038 SelectObject(hdc
, prevfont
);
7040 prevfont
= SelectObject(hdc
, hfont2
);
7041 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
7042 SendMessageA(hwnd
, WM_PAINT
, (WPARAM
)hdc
, 0);
7043 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PAINT\n", i
);
7044 SelectObject(hdc
, prevfont
);
7048 DestroyWindow(hwnd
);
7051 DeleteObject(hfont2
);
7052 DestroyWindow(parent
);
7054 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
7056 parent
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7057 100, 100, 200, 200, 0, 0, 0, NULL
);
7058 ok (hwnd
!= 0, "Failed to create overlapped window\n");
7060 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON
| WS_VISIBLE
| WS_CHILD
,
7061 0, 0, 50, 14, parent
, 0, 0, NULL
);
7063 EnableWindow(hwnd
, FALSE
);
7065 SendMessageA(hwnd
, WM_LBUTTONDOWN
, MK_LBUTTON
, 0);
7066 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
7067 ok_sequence(WmDisableButtonSeq
, "Mouseclick on a disabled button", FALSE
);
7069 DestroyWindow(hwnd
);
7070 DestroyWindow(parent
);
7073 static void test_button_bm_get_set_image(void)
7080 ICONINFO icon_info2x2
;
7086 DWORD default_style
= BS_PUSHBUTTON
| WS_TABSTOP
| WS_POPUP
| WS_VISIBLE
;
7090 hbmp1x1
= CreateCompatibleBitmap(hdc
, 1, 1);
7091 hbmp2x2
= CreateCompatibleBitmap(hdc
, 2, 2);
7092 ZeroMemory(&bm
, sizeof(bm
));
7093 ok(GetObjectW(hbmp1x1
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7094 ok(bm
.bmWidth
== 1 && bm
.bmHeight
== 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7095 bm
.bmWidth
, bm
.bmHeight
);
7096 ZeroMemory(&bm
, sizeof(bm
));
7097 ok(GetObjectW(hbmp2x2
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7098 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7099 bm
.bmWidth
, bm
.bmHeight
);
7101 hmask2x2
= CreateCompatibleBitmap(hdc
, 2, 2);
7102 ZeroMemory(&icon_info2x2
, sizeof(icon_info2x2
));
7103 icon_info2x2
.fIcon
= TRUE
;
7104 icon_info2x2
.hbmMask
= hmask2x2
;
7105 icon_info2x2
.hbmColor
= hbmp2x2
;
7106 hicon2x2
= CreateIconIndirect(&icon_info2x2
);
7108 ZeroMemory(&icon_info
, sizeof(icon_info
));
7109 ok(GetIconInfo(hicon2x2
, &icon_info
), "Expect GetIconInfo() success\n");
7110 ZeroMemory(&bm
, sizeof(bm
));
7111 ok(GetObjectW(icon_info
.hbmColor
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7112 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7113 bm
.bmWidth
, bm
.bmHeight
);
7114 DeleteObject(icon_info
.hbmColor
);
7115 DeleteObject(icon_info
.hbmMask
);
7117 /* Set bitmap with BS_BITMAP */
7118 hwnd
= CreateWindowA("Button", "test", default_style
| BS_BITMAP
, 0, 0, 100, 100, 0, 0, 0, 0);
7119 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7120 SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7121 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7122 ok(hbmp
!= 0, "Expect hbmp not 0\n");
7123 ZeroMemory(&bm
, sizeof(bm
));
7124 ok(GetObjectW(hbmp
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7125 ok(bm
.bmWidth
== 1 && bm
.bmHeight
== 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7126 bm
.bmWidth
, bm
.bmHeight
);
7127 DestroyWindow(hwnd
);
7129 /* Set bitmap without BS_BITMAP */
7130 hwnd
= CreateWindowA("Button", "test", default_style
, 0, 0, 100, 100, 0, 0, 0, 0);
7131 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7132 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7133 ok(ret
== 0, "Expect ret to be 0\n");
7134 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7135 ok(hbmp
== NULL
, "Expect hbmp to be NULL\n");
7136 DestroyWindow(hwnd
);
7138 /* Set icon with BS_ICON */
7139 hwnd
= CreateWindowA("Button", "test", default_style
| BS_ICON
, 0, 0, 100, 100, 0, 0, 0, 0);
7140 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7141 SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7142 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7143 ok(hicon
!= NULL
, "Expect hicon not NULL\n");
7144 ZeroMemory(&icon_info
, sizeof(icon_info
));
7145 ok(GetIconInfo(hicon
, &icon_info
), "Expect GetIconInfo() success\n");
7146 ZeroMemory(&bm
, sizeof(bm
));
7147 ok(GetObjectW(icon_info
.hbmColor
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7148 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7149 bm
.bmWidth
, bm
.bmHeight
);
7150 DeleteObject(icon_info
.hbmColor
);
7151 DeleteObject(icon_info
.hbmMask
);
7152 DestroyWindow(hwnd
);
7154 /* Set icon without BS_ICON */
7155 hwnd
= CreateWindowA("Button", "test", default_style
, 0, 0, 100, 100, 0, 0, 0, 0);
7156 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7157 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7158 ok(ret
== 0, "Expect ret to be 0\n");
7159 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7160 ok(hicon
== NULL
, "Expect hicon to be NULL\n");
7161 DestroyWindow(hwnd
);
7163 /* Set icon with BS_BITMAP */
7164 hwnd
= CreateWindowA("Button", "test", default_style
| BS_BITMAP
, 0, 0, 100, 100, 0, 0, 0, 0);
7165 ok(hwnd
!= NULL
, "Expect hwnd to be not NULL\n");
7166 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7167 ok(ret
== 0, "Expect ret to be 0\n");
7168 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7169 ok(hicon
== NULL
, "Expect hicon to be NULL\n");
7170 DestroyWindow(hwnd
);
7172 /* Set bitmap with BS_ICON */
7173 hwnd
= CreateWindowA("Button", "test", default_style
| BS_ICON
, 0, 0, 100, 100, 0, 0, 0, 0);
7174 ok(hwnd
!= NULL
, "Expect hwnd to be not NULL\n");
7175 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7176 ok(ret
== 0, "Expect ret to be 0\n");
7177 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7178 ok(hbmp
== NULL
, "Expect hbmp to be NULL\n");
7179 DestroyWindow(hwnd
);
7181 DestroyIcon(hicon2x2
);
7182 DeleteObject(hmask2x2
);
7183 DeleteObject(hbmp2x2
);
7184 DeleteObject(hbmp1x1
);
7188 #define ID_RADIO1 501
7189 #define ID_RADIO2 502
7190 #define ID_RADIO3 503
7193 static const struct message auto_radio_button_BM_CLICK
[] =
7195 { BM_CLICK
, sent
|wparam
|lparam
, 0, 0 },
7196 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7197 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7198 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
7199 { WM_CTLCOLORSTATIC
, sent
|parent
},
7200 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7201 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7202 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
7203 { WM_CTLCOLORSTATIC
, sent
|parent
},
7204 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7205 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
7206 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
7207 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
7208 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO1
},
7209 { WM_CTLCOLORSTATIC
, sent
|parent
},
7210 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7211 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
7212 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO3
},
7213 { WM_CTLCOLORSTATIC
, sent
|parent
},
7214 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7215 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
7216 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7217 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7218 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO2
, BN_CLICKED
) },
7219 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7220 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7221 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7225 static const struct message auto_radio_button_VK_UP_child
[] =
7227 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_UP
, 0 },
7228 { WM_KEYUP
, sent
|wparam
|lparam
, VK_UP
, 0 },
7232 static const struct message auto_radio_button_VK_UP_parent
[] =
7234 { WM_KEYDOWN
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
7235 { WM_KEYUP
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
7239 static const struct message auto_radio_button_VK_UP_dialog
[] =
7241 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7243 /* optional trailer seen on some windows setups */
7244 { WM_CHANGEUISTATE
, sent
|optional
},
7245 { WM_UPDATEUISTATE
, sent
|optional
},
7246 { WM_UPDATEUISTATE
, sent
|optional
},
7247 { WM_UPDATEUISTATE
, sent
|optional
},
7248 { WM_UPDATEUISTATE
, sent
|optional
},
7249 { WM_UPDATEUISTATE
, sent
|optional
},
7250 { WM_UPDATEUISTATE
, sent
|optional
},
7251 { WM_UPDATEUISTATE
, sent
|optional
},
7252 { WM_UPDATEUISTATE
, sent
|optional
},
7253 { WM_UPDATEUISTATE
, sent
|optional
},
7254 { WM_UPDATEUISTATE
, sent
|optional
},
7255 { WM_UPDATEUISTATE
, sent
|optional
},
7256 { WM_UPDATEUISTATE
, sent
|optional
},
7257 { WM_UPDATEUISTATE
, sent
|optional
},
7258 { WM_UPDATEUISTATE
, sent
|optional
},
7259 { WM_UPDATEUISTATE
, sent
|optional
},
7260 { WM_UPDATEUISTATE
, sent
|optional
},
7261 { WM_UPDATEUISTATE
, sent
|optional
},
7262 { WM_UPDATEUISTATE
, sent
|optional
},
7263 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7264 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7265 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7266 { WM_UPDATEUISTATE
, sent
|optional
},
7267 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7268 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7269 { WM_UPDATEUISTATE
, sent
|optional
},
7270 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
7271 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
7272 { WM_UPDATEUISTATE
, sent
|optional
},
7273 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7274 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7278 static const struct message auto_radio_button_VK_DOWN_dialog
[] =
7280 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7281 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
7282 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7283 { HCBT_SETFOCUS
, hook
},
7284 { WM_KILLFOCUS
, sent
, 0, 0 },
7285 { WM_CTLCOLORSTATIC
, sent
|parent
},
7286 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO3
, BN_KILLFOCUS
) },
7287 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
7288 { WM_SETFOCUS
, sent
, 0, 0 },
7289 { WM_CTLCOLORSTATIC
, sent
|parent
},
7290 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_SETFOCUS
) },
7291 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
7292 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7293 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7294 { DM_GETDEFID
, sent
|parent
, 0, 0 },
7295 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7296 { BM_CLICK
, sent
|wparam
|lparam
, 1, 0 },
7297 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7298 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7299 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
7300 { WM_CTLCOLORSTATIC
, sent
|parent
},
7301 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7302 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7303 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO1
},
7304 { WM_CTLCOLORSTATIC
, sent
|parent
},
7305 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7306 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
7307 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
7308 { WM_CTLCOLORSTATIC
, sent
|parent
},
7309 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7310 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
7311 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO3
},
7312 { WM_CTLCOLORSTATIC
, sent
|parent
},
7313 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7314 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
7315 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
7316 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
7317 { WM_CTLCOLORSTATIC
, sent
|parent
},
7318 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
7319 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
7320 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7321 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
7322 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7323 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7324 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
7326 { WM_CTLCOLORSTATIC
, sent
|parent
},
7330 static const struct message auto_radio_button_VK_DOWN_radio3
[] =
7332 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7333 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO2
},
7334 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO3
},
7335 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7336 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
7337 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7338 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7339 { WM_GETDLGCODE
, sent
|wparam
|lparam
|parent
, 0, 0 },
7340 { WM_USER
, sent
|parent
, 0, 0 },
7341 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7345 static const struct message auto_radio_button_VK_UP_radio1
[] =
7347 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7351 static INT_PTR WINAPI
radio_test_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
7353 ParentMsgCheckProcA(hwnd
, msg
, wp
, lp
);
7357 static void test_autoradio_BM_CLICK(void)
7359 HWND parent
, radio1
, radio2
, radio3
;
7366 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc
, 0);
7367 ok(parent
!= 0, "failed to create parent window\n");
7369 radio1
= GetDlgItem(parent
, ID_RADIO1
);
7370 radio2
= GetDlgItem(parent
, ID_RADIO2
);
7371 radio3
= GetDlgItem(parent
, ID_RADIO3
);
7373 /* this avoids focus messages in the generated sequence */
7379 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7380 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7381 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7382 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7383 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7384 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7386 SendMessageA(radio1
, BM_SETCHECK
, BST_CHECKED
, 0);
7388 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7389 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7390 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7391 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7392 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7393 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7395 SendMessageA(radio2
, BM_SETCHECK
, BST_CHECKED
, 0);
7397 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7398 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7399 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7400 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7401 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7402 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7404 SendMessageA(radio3
, BM_SETCHECK
, BST_CHECKED
, 0);
7406 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7407 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7408 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7409 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7410 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7411 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7413 GetWindowRect(radio2
, &rc
);
7414 SetCursorPos(rc
.left
+1, rc
.top
+1);
7419 log_all_parent_messages
++;
7421 SendMessageA(radio2
, BM_CLICK
, 0, 0);
7422 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7423 ok_sequence(auto_radio_button_BM_CLICK
, "BM_CLICK on auto-radio button", FALSE
);
7425 log_all_parent_messages
--;
7427 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7428 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7429 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7430 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7431 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7432 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7434 DestroyWindow(parent
);
7437 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)
7438 static void test_radio_dbg(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
, int line
)
7442 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7443 ok_(__FILE__
,line
)(ret
== state1
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7444 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7445 ok_(__FILE__
,line
)(ret
== state2
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7446 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7447 ok_(__FILE__
,line
)(ret
== state3
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7450 static void set_radio(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
)
7452 SendMessageA(radio1
, BM_SETCHECK
, state1
? BST_CHECKED
: BST_UNCHECKED
, 0);
7453 SendMessageA(radio2
, BM_SETCHECK
, state2
? BST_CHECKED
: BST_UNCHECKED
, 0);
7454 SendMessageA(radio3
, BM_SETCHECK
, state3
? BST_CHECKED
: BST_UNCHECKED
, 0);
7457 static void test_autoradio_kbd_move(void)
7459 HWND parent
, radio1
, radio2
, radio3
, hwnd
;
7466 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc
, 0);
7467 ok(parent
!= 0, "failed to create parent window\n");
7469 radio1
= GetDlgItem(parent
, ID_RADIO1
);
7470 radio2
= GetDlgItem(parent
, ID_RADIO2
);
7471 radio3
= GetDlgItem(parent
, ID_RADIO3
);
7476 test_radio(radio1
, 0, radio2
, 0, radio3
, 0);
7477 set_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7478 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7485 log_all_parent_messages
++;
7487 SendMessageA(radio3
, WM_KEYDOWN
, VK_UP
, 0);
7488 SendMessageA(radio3
, WM_KEYUP
, VK_UP
, 0);
7489 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7490 ok_sequence(auto_radio_button_VK_UP_child
, "press/release VK_UP on auto-radio button", FALSE
);
7492 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7497 DefDlgProcA(parent
, WM_KEYDOWN
, VK_UP
, 0);
7498 DefDlgProcA(parent
, WM_KEYUP
, VK_UP
, 0);
7499 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7500 ok_sequence(auto_radio_button_VK_UP_parent
, "press/release VK_UP on dialog", FALSE
);
7502 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7505 GetWindowRect(radio3
, &rc
);
7511 msg
.message
= WM_KEYDOWN
;
7514 msg
.pt
.x
= rc
.left
+ 1;
7515 msg
.pt
.y
= rc
.top
+ 1;
7516 ret
= IsDialogMessageA(parent
, &msg
);
7517 ok(ret
, "IsDialogMessage should return TRUE\n");
7518 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7519 if (0) /* actual message sequence is different on every run in some Windows setups */
7520 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #1", FALSE
);
7521 /* what really matters is that nothing has changed */
7522 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7524 set_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7525 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7530 ret
= IsDialogMessageA(parent
, &msg
);
7531 ok(ret
, "IsDialogMessage should return TRUE\n");
7532 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7533 if (0) /* actual message sequence is different on every run in some Windows setups */
7534 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #2", FALSE
);
7535 /* what really matters is that nothing has changed */
7536 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7538 /* switch from radio3 ro radio1 */
7540 GetWindowRect(radio3
, &rc
);
7546 msg
.message
= WM_KEYDOWN
;
7547 msg
.wParam
= VK_DOWN
;
7549 msg
.pt
.x
= rc
.left
+ 1;
7550 msg
.pt
.y
= rc
.top
+ 1;
7551 ret
= IsDialogMessageA(parent
, &msg
);
7552 ok(ret
, "IsDialogMessage should return TRUE\n");
7553 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7554 ok_sequence(auto_radio_button_VK_DOWN_dialog
, "IsDialogMessage(VK_DOWN)", TRUE
);
7556 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7559 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7560 GetWindowRect(radio1
, &rc
);
7563 msg
.message
= WM_KEYDOWN
;
7564 msg
.wParam
= VK_DOWN
;
7566 msg
.pt
.x
= rc
.left
+ 1;
7567 msg
.pt
.y
= rc
.top
+ 1;
7568 ret
= IsDialogMessageA(parent
, &msg
);
7569 ok(ret
, "IsDialogMessage should return TRUE\n");
7570 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7571 ok_sequence(auto_radio_button_VK_DOWN_radio3
, "down to radio3", TRUE
);
7573 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7576 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7582 msg
.message
= WM_KEYDOWN
;
7585 msg
.pt
.x
= rc
.left
+ 1;
7586 msg
.pt
.y
= rc
.top
+ 1;
7587 ret
= IsDialogMessageA(parent
, &msg
);
7588 ok(ret
, "IsDialogMessage should return TRUE\n");
7589 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7590 ok_sequence(auto_radio_button_VK_UP_radio1
, "up to radio1", TRUE
);
7592 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7595 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7601 msg
.message
= WM_KEYDOWN
;
7604 msg
.pt
.x
= rc
.left
+ 1;
7605 msg
.pt
.y
= rc
.top
+ 1;
7606 ret
= IsDialogMessageA(parent
, &msg
);
7607 ok(ret
, "IsDialogMessage should return TRUE\n");
7608 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7609 if (0) /* actual message sequence is different on every run in some Windows setups */
7610 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #3", FALSE
);
7611 /* what really matters is that nothing has changed */
7612 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7614 log_all_parent_messages
--;
7616 DestroyWindow(parent
);
7619 /****************** static message test *************************/
7620 static const struct message WmSetFontStaticSeq2
[] =
7622 { WM_SETFONT
, sent
},
7623 { WM_PAINT
, sent
|defwinproc
|optional
},
7624 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
7625 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
7629 static WNDPROC old_static_proc
;
7631 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7633 static LONG defwndproc_counter
= 0;
7635 struct recvd_message msg
;
7637 if (ignore_message( message
)) return 0;
7640 msg
.message
= message
;
7641 msg
.flags
= sent
|wparam
|lparam
;
7642 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7643 msg
.wParam
= wParam
;
7644 msg
.lParam
= lParam
;
7645 msg
.descr
= "static";
7648 defwndproc_counter
++;
7649 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
7650 defwndproc_counter
--;
7655 static void subclass_static(void)
7659 if (!GetClassInfoA(0, "static", &cls
)) assert(0);
7661 old_static_proc
= cls
.lpfnWndProc
;
7663 cls
.hInstance
= GetModuleHandleA(NULL
);
7664 cls
.lpfnWndProc
= static_hook_proc
;
7665 cls
.lpszClassName
= "my_static_class";
7666 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7667 if (!RegisterClassA(&cls
)) assert(0);
7670 static void test_static_messages(void)
7672 /* FIXME: make as comprehensive as the button message test */
7677 const struct message
*setfont
;
7679 { SS_LEFT
, DLGC_STATIC
,
7680 WmSetFontStaticSeq2
}
7688 for (i
= 0; i
< ARRAY_SIZE(static_ctrl
); i
++)
7690 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
7691 0, 0, 50, 14, 0, 0, 0, NULL
);
7692 ok(hwnd
!= 0, "Failed to create static window\n");
7694 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
7695 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08lx\n", i
, dlg_code
);
7697 ShowWindow(hwnd
, SW_SHOW
);
7702 trace("static style %08lx\n", static_ctrl
[i
].style
);
7703 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
7704 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
7706 DestroyWindow(hwnd
);
7710 /****************** ComboBox message test *************************/
7711 #define ID_COMBOBOX 0x000f
7713 static const struct message SetCurSelComboSeq
[] =
7715 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7716 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7717 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7718 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7719 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7720 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7721 { LB_GETTEXT
, sent
|wparam
, 0 },
7722 { WM_CTLCOLOREDIT
, sent
|parent
},
7723 { LB_GETITEMDATA
, sent
|wparam
|lparam
, 0, 0 },
7724 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_COMBOBOX
, 0x100010f3 },
7728 static const struct message SetCurSelComboSeq2
[] =
7730 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7731 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7732 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7733 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7734 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7735 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7736 { LB_GETTEXT
, sent
|wparam
, 0 },
7740 static const struct message SetCurSelComboSeq_edit
[] =
7742 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7743 { WM_SETTEXT
, sent
|wparam
, 0 },
7744 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
7748 static const struct message WmKeyDownComboSeq
[] =
7750 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7751 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
7752 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
7753 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
7754 { WM_CTLCOLOREDIT
, sent
|parent
},
7755 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7759 static const struct message WmSetPosComboSeq
[] =
7761 { WM_WINDOWPOSCHANGING
, sent
},
7762 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
7763 { WM_CHILDACTIVATE
, sent
},
7764 { WM_WINDOWPOSCHANGED
, sent
},
7765 { WM_MOVE
, sent
|defwinproc
},
7766 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7767 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
7768 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
7769 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
7770 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7774 static const struct message WMSetFocusComboBoxSeq
[] =
7776 { WM_SETFOCUS
, sent
},
7777 { WM_KILLFOCUS
, sent
|parent
},
7778 { WM_SETFOCUS
, sent
},
7779 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7780 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7781 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7782 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7783 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7787 static const struct message SetFocusButtonSeq
[] =
7789 { WM_KILLFOCUS
, sent
},
7790 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7791 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7792 { WM_LBUTTONUP
, sent
|defwinproc
},
7793 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7794 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7795 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7796 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7797 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7798 { WM_CTLCOLORBTN
, sent
|parent
},
7802 static const struct message SetFocusComboBoxSeq
[] =
7804 { WM_CTLCOLORBTN
, sent
|parent
},
7805 { WM_SETFOCUS
, sent
},
7806 { WM_KILLFOCUS
, sent
|defwinproc
},
7807 { WM_SETFOCUS
, sent
},
7808 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7809 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7810 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7811 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7812 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7816 static const struct message SetFocusButtonSeq2
[] =
7818 { WM_KILLFOCUS
, sent
},
7819 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7820 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7821 { WM_LBUTTONUP
, sent
|defwinproc
},
7822 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7823 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7824 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
7825 { WM_CTLCOLOREDIT
, sent
|parent
},
7826 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7827 { WM_CTLCOLORBTN
, sent
|parent
},
7831 static WNDPROC old_combobox_proc
, edit_window_proc
, lbox_window_proc
;
7833 static LRESULT CALLBACK
combobox_edit_subclass_proc(HWND hwnd
, UINT message
,
7834 WPARAM wParam
, LPARAM lParam
)
7836 static LONG defwndproc_counter
= 0;
7838 struct recvd_message msg
;
7840 /* do not log painting messages */
7841 if (message
!= WM_PAINT
&&
7842 message
!= WM_NCPAINT
&&
7843 message
!= WM_SYNCPAINT
&&
7844 message
!= WM_ERASEBKGND
&&
7845 message
!= WM_NCHITTEST
&&
7846 message
!= WM_GETTEXT
&&
7847 !ignore_message( message
))
7850 msg
.message
= message
;
7851 msg
.flags
= sent
|wparam
|lparam
;
7852 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7853 msg
.wParam
= wParam
;
7854 msg
.lParam
= lParam
;
7855 msg
.descr
= "combo edit";
7859 defwndproc_counter
++;
7860 ret
= CallWindowProcA(edit_window_proc
, hwnd
, message
, wParam
, lParam
);
7861 defwndproc_counter
--;
7866 static LRESULT CALLBACK
combobox_lbox_subclass_proc(HWND hwnd
, UINT message
,
7867 WPARAM wParam
, LPARAM lParam
)
7869 static LONG defwndproc_counter
= 0;
7871 struct recvd_message msg
;
7873 /* do not log painting messages */
7874 if (message
!= WM_PAINT
&&
7875 message
!= WM_NCPAINT
&&
7876 message
!= WM_SYNCPAINT
&&
7877 message
!= WM_ERASEBKGND
&&
7878 message
!= WM_NCHITTEST
&&
7879 !ignore_message( message
))
7882 msg
.message
= message
;
7883 msg
.flags
= sent
|wparam
|lparam
;
7884 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7885 msg
.wParam
= wParam
;
7886 msg
.lParam
= lParam
;
7887 msg
.descr
= "combo lbox";
7891 defwndproc_counter
++;
7892 ret
= CallWindowProcA(lbox_window_proc
, hwnd
, message
, wParam
, lParam
);
7893 defwndproc_counter
--;
7898 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7900 static LONG defwndproc_counter
= 0;
7902 struct recvd_message msg
;
7904 /* do not log painting messages */
7905 if (message
!= WM_PAINT
&&
7906 message
!= WM_NCPAINT
&&
7907 message
!= WM_SYNCPAINT
&&
7908 message
!= WM_ERASEBKGND
&&
7909 message
!= WM_NCHITTEST
&&
7910 message
!= WM_GETTEXT
&&
7911 !ignore_message( message
))
7914 msg
.message
= message
;
7915 msg
.flags
= sent
|wparam
|lparam
;
7916 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7917 msg
.wParam
= wParam
;
7918 msg
.lParam
= lParam
;
7919 msg
.descr
= "combo";
7923 defwndproc_counter
++;
7924 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
7925 defwndproc_counter
--;
7930 static void subclass_combobox(void)
7934 if (!GetClassInfoA(0, "ComboBox", &cls
)) assert(0);
7936 old_combobox_proc
= cls
.lpfnWndProc
;
7938 cls
.hInstance
= GetModuleHandleA(NULL
);
7939 cls
.lpfnWndProc
= combobox_hook_proc
;
7940 cls
.lpszClassName
= "my_combobox_class";
7941 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7942 if (!RegisterClassA(&cls
)) assert(0);
7945 static void test_combobox_messages(void)
7947 HWND parent
, combo
, button
, edit
, lbox
;
7949 COMBOBOXINFO cbInfo
;
7952 subclass_combobox();
7954 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7955 100, 100, 200, 200, 0, 0, 0, NULL
);
7956 ok(parent
!= 0, "Failed to create parent window\n");
7959 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
7960 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
7961 ok(combo
!= 0, "Failed to create combobox window\n");
7963 UpdateWindow(combo
);
7965 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
7966 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08Ix\n", ret
);
7968 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
7969 ok(ret
== 0, "expected 0, got %Id\n", ret
);
7970 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
7971 ok(ret
== 1, "expected 1, got %Id\n", ret
);
7972 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
7973 ok(ret
== 2, "expected 2, got %Id\n", ret
);
7975 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
7979 log_all_parent_messages
++;
7980 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
7981 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
7982 log_all_parent_messages
--;
7983 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
7986 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
7987 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
7989 DestroyWindow(combo
);
7990 DestroyWindow(parent
);
7992 /* Start again. Test combobox text selection when getting and losing focus */
7993 parent
= CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7994 10, 10, 300, 300, NULL
, NULL
, NULL
, NULL
);
7995 ok(parent
!= 0, "Failed to create parent window\n");
7997 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWN
,
7998 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
7999 ok(combo
!= 0, "Failed to create combobox window\n");
8001 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
8002 SetLastError(0xdeadbeef);
8003 res
= GetComboBoxInfo(combo
, &cbInfo
);
8004 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8005 edit
= cbInfo
.hwndItem
;
8007 edit_window_proc
= (WNDPROC
)SetWindowLongPtrA(edit
, GWLP_WNDPROC
,
8008 (ULONG_PTR
)combobox_edit_subclass_proc
);
8010 button
= CreateWindowExA(0, "Button", "OK", WS_CHILD
| WS_VISIBLE
| BS_DEFPUSHBUTTON
,
8011 5, 50, 100, 20, parent
, NULL
,
8012 (HINSTANCE
)GetWindowLongPtrA(parent
, GWLP_HINSTANCE
), NULL
);
8013 ok(button
!= 0, "Failed to create button window\n");
8016 log_all_parent_messages
++;
8017 SendMessageA(combo
, WM_SETFOCUS
, 0, (LPARAM
)edit
);
8018 log_all_parent_messages
--;
8019 ok_sequence(WMSetFocusComboBoxSeq
, "WM_SETFOCUS on a ComboBox", TRUE
);
8022 log_all_parent_messages
++;
8024 log_all_parent_messages
--;
8025 ok_sequence(SetFocusButtonSeq
, "SetFocus on a Button", TRUE
);
8027 SendMessageA(combo
, WM_SETTEXT
, 0, (LPARAM
)"Wine Test");
8030 log_all_parent_messages
++;
8032 log_all_parent_messages
--;
8033 ok_sequence(SetFocusComboBoxSeq
, "SetFocus on a ComboBox", TRUE
);
8036 log_all_parent_messages
++;
8038 log_all_parent_messages
--;
8039 ok_sequence(SetFocusButtonSeq2
, "SetFocus on a Button (2)", TRUE
);
8042 SendMessageA(combo
, WM_SETREDRAW
, FALSE
, 0);
8044 log_all_parent_messages
++;
8045 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8046 log_all_parent_messages
--;
8047 ok_sequence(SetCurSelComboSeq_edit
, "CB_SETCURSEL on a ComboBox with edit control", FALSE
);
8049 DestroyWindow(button
);
8050 DestroyWindow(combo
);
8052 combo
= CreateWindowExA(0, "my_combobox_class", "test",
8053 WS_CHILD
| WS_VISIBLE
| CBS_OWNERDRAWFIXED
| CBS_DROPDOWNLIST
,
8054 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
8055 ok(combo
!= 0, "Failed to create combobox window\n");
8057 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
8058 ok(ret
== 0, "expected 0, got %Id\n", ret
);
8060 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
8061 SetLastError(0xdeadbeef);
8062 res
= GetComboBoxInfo(combo
, &cbInfo
);
8063 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8064 lbox
= cbInfo
.hwndList
;
8065 lbox_window_proc
= (WNDPROC
)SetWindowLongPtrA(lbox
, GWLP_WNDPROC
,
8066 (ULONG_PTR
)combobox_lbox_subclass_proc
);
8069 log_all_parent_messages
++;
8070 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8071 log_all_parent_messages
--;
8072 ok_sequence(SetCurSelComboSeq
, "CB_SETCURSEL on a ComboBox", FALSE
);
8074 ShowWindow(combo
, SW_HIDE
);
8076 log_all_parent_messages
++;
8077 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8078 log_all_parent_messages
--;
8079 ok_sequence(SetCurSelComboSeq2
, "CB_SETCURSEL on a ComboBox", FALSE
);
8081 DestroyWindow(combo
);
8082 DestroyWindow(parent
);
8085 /****************** WM_IME_KEYDOWN message test *******************/
8087 static const struct message WmImeKeydownMsgSeq_0
[] =
8089 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
8090 { WM_CHAR
, wparam
, 'A' },
8094 static const struct message WmImeKeydownMsgSeq_1
[] =
8096 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
8097 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
8101 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8103 struct recvd_message msg
;
8106 msg
.message
= message
;
8107 msg
.flags
= wparam
|lparam
;
8108 msg
.wParam
= wParam
;
8109 msg
.lParam
= lParam
;
8110 msg
.descr
= "wmime_keydown";
8113 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8116 static void register_wmime_keydown_class(void)
8120 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
8121 cls
.lpfnWndProc
= wmime_keydown_procA
;
8122 cls
.hInstance
= GetModuleHandleA(0);
8123 cls
.lpszClassName
= "wmime_keydown_class";
8124 if (!RegisterClassA(&cls
)) assert(0);
8127 static void test_wmime_keydown_message(void)
8132 trace("Message sequences by WM_IME_KEYDOWN\n");
8134 register_wmime_keydown_class();
8135 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
8136 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
8141 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
8142 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
8143 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
8145 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
8147 TranslateMessage(&msg
);
8148 DispatchMessageA(&msg
);
8150 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
8152 DestroyWindow(hwnd
);
8155 /************* painting message test ********************/
8157 void dump_region(HRGN hrgn
)
8160 RGNDATA
*data
= NULL
;
8165 printf( "null region\n" );
8168 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
8169 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
8170 GetRegionData( hrgn
, size
, data
);
8171 printf("%ld rects:", data
->rdh
.nCount
);
8172 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
8173 printf( " %s", wine_dbgstr_rect( rect
));
8175 HeapFree( GetProcessHeap(), 0, data
);
8178 #define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn )
8179 static void check_update_rgn_( int line
, HWND hwnd
, HRGN hrgn
)
8183 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
8184 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
8186 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
8187 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
8188 if (ret
== NULLREGION
)
8190 ok_(__FILE__
,line
)( !hrgn
, "Update region shouldn't be empty\n" );
8194 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
8196 ok_(__FILE__
,line
)( 0, "Regions are different\n" );
8197 if (winetest_debug
> 0)
8199 printf( "Update region: " );
8200 dump_region( update
);
8201 printf( "Wanted region: " );
8202 dump_region( hrgn
);
8206 GetRgnBox( update
, &r1
);
8207 GetUpdateRect( hwnd
, &r2
, FALSE
);
8208 ok_(__FILE__
,line
)( EqualRect( &r1
, &r2
), "Rectangles are different: %s / %s\n",
8209 wine_dbgstr_rect( &r1
), wine_dbgstr_rect( &r2
));
8211 DeleteObject( tmp
);
8212 DeleteObject( update
);
8215 static const struct message WmInvalidateRgn
[] = {
8216 { WM_NCPAINT
, sent
},
8217 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8221 static const struct message WmGetUpdateRect
[] = {
8222 { WM_NCPAINT
, sent
},
8223 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8228 static const struct message WmInvalidateFull
[] = {
8229 { WM_NCPAINT
, sent
|wparam
, 1 },
8230 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8234 static const struct message WmInvalidateErase
[] = {
8235 { WM_NCPAINT
, sent
|wparam
, 1 },
8236 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8237 { WM_ERASEBKGND
, sent
},
8241 static const struct message WmInvalidatePaint
[] = {
8243 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
8244 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8248 static const struct message WmInvalidateErasePaint
[] = {
8250 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
8251 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8252 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8256 static const struct message WmInvalidateErasePaint2
[] = {
8258 { WM_NCPAINT
, sent
|beginpaint
},
8259 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8260 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8264 static const struct message WmErase
[] = {
8265 { WM_ERASEBKGND
, sent
},
8269 static const struct message WmPaint
[] = {
8274 static const struct message WmParentOnlyPaint
[] = {
8275 { WM_PAINT
, sent
|parent
},
8279 static const struct message WmInvalidateParent
[] = {
8280 { WM_NCPAINT
, sent
|parent
},
8281 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
8282 { WM_ERASEBKGND
, sent
|parent
},
8286 static const struct message WmInvalidateParentChild
[] = {
8287 { WM_NCPAINT
, sent
|parent
},
8288 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
8289 { WM_ERASEBKGND
, sent
|parent
},
8290 { WM_NCPAINT
, sent
},
8291 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8292 { WM_ERASEBKGND
, sent
},
8296 static const struct message WmInvalidateParentChild2
[] = {
8297 { WM_ERASEBKGND
, sent
|parent
},
8298 { WM_NCPAINT
, sent
},
8299 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8300 { WM_ERASEBKGND
, sent
},
8304 static const struct message WmParentPaint
[] = {
8305 { WM_PAINT
, sent
|parent
},
8310 static const struct message WmParentPaintNc
[] = {
8311 { WM_PAINT
, sent
|parent
},
8313 { WM_NCPAINT
, sent
|beginpaint
},
8314 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8315 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8316 { WM_GETMINMAXINFO
, sent
|optional
},
8320 static const struct message WmChildPaintNc
[] = {
8322 { WM_NCPAINT
, sent
|beginpaint
},
8323 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8324 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8328 static const struct message WmParentErasePaint
[] = {
8329 { WM_PAINT
, sent
|parent
},
8330 { WM_NCPAINT
, sent
|parent
|beginpaint
},
8331 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
8332 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
8334 { WM_NCPAINT
, sent
|beginpaint
},
8335 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8336 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8340 static const struct message WmParentOnlyNcPaint
[] = {
8341 { WM_PAINT
, sent
|parent
},
8342 { WM_NCPAINT
, sent
|parent
|beginpaint
},
8343 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
8347 static const struct message WmSetParentStyle
[] = {
8348 { WM_STYLECHANGING
, sent
|parent
},
8349 { WM_STYLECHANGED
, sent
|parent
},
8353 static void test_paint_messages(void)
8359 HWND hparent
, hchild
;
8360 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
8361 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
8362 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
8363 100, 100, 200, 200, 0, 0, 0, NULL
);
8364 ok (hwnd
!= 0, "Failed to create overlapped window\n");
8366 ShowWindow( hwnd
, SW_SHOW
);
8367 UpdateWindow( hwnd
);
8371 check_update_rgn( hwnd
, 0 );
8372 SetRectRgn( hrgn
, 10, 10, 20, 20 );
8373 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8374 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8375 check_update_rgn( hwnd
, hrgn
);
8376 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
8377 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
8378 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8379 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
8380 check_update_rgn( hwnd
, hrgn
);
8381 /* validate everything */
8382 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8383 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8384 check_update_rgn( hwnd
, 0 );
8386 /* test empty region */
8387 SetRectRgn( hrgn
, 10, 10, 10, 15 );
8388 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8389 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8390 check_update_rgn( hwnd
, 0 );
8391 /* test empty rect */
8392 SetRect( &rect
, 10, 10, 10, 15 );
8393 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8394 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8395 check_update_rgn( hwnd
, 0 );
8397 /* test a zeroed rectangle */
8398 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8399 SetRect( &rect
, 0, 0, 0, 0 );
8400 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8401 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8402 check_update_rgn( hwnd
, 0 );
8404 /* a well ordered rectangle */
8405 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8406 SetRect( &rect
, 10, 5, 17, 21 );
8407 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8408 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8409 SetRectRgn( hrgn
, 10, 5, 17, 21 );
8410 check_update_rgn( hwnd
, hrgn
);
8412 /* empty rectangle, top and bottom are swapped but left and right have
8414 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8415 SetRect( &rect
, 5, 30, 5, 10 );
8416 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8417 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8418 check_update_rgn( hwnd
, 0 );
8420 /* empty rectangle, left and right are swapped but top and bottom have
8422 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8423 SetRect( &rect
, 17, 10, 5, 10 );
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 /* Left and right are swapped */
8429 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8430 SetRect( &rect
, 21, 12, 7, 30 );
8431 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8432 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8433 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8434 check_update_rgn( hwnd
, hrgn
);
8436 /* Top and bottom are swapped */
8437 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8438 SetRect( &rect
, 7, 30, 21, 12 );
8439 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8440 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8441 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8442 check_update_rgn( hwnd
, hrgn
);
8444 /* both reference points are swapped */
8445 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8446 SetRect( &rect
, 21, 30, 7, 12 );
8447 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8448 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8449 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8450 check_update_rgn( hwnd
, hrgn
);
8452 /* flush pending messages */
8456 GetClientRect( hwnd
, &rect
);
8457 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
8458 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
8459 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8461 SetRectEmpty( &rect
);
8462 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) failed\n");
8463 check_update_rgn( hwnd
, hrgn
);
8464 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8466 ok_sequence( WmPaint
, "Paint", FALSE
);
8467 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8468 check_update_rgn( hwnd
, 0 );
8470 SetRectEmpty( &rect
);
8471 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8472 "RedrawWindow failed\n");
8473 check_update_rgn( hwnd
, 0 );
8475 SetRectEmpty( &rect
);
8476 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_VALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8477 "RedrawWindow failed\n");
8478 check_update_rgn( hwnd
, 0 );
8480 GetWindowRect( hwnd
, &rect
);
8481 ok(RedrawWindow(0, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8482 "RedrawWindow failed\n");
8483 check_update_rgn( hwnd
, 0 );
8486 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8487 "RedrawWindow failed\n");
8488 check_update_rgn( hwnd
, hrgn
);
8489 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8491 ok_sequence( WmPaint
, "Paint", FALSE
);
8492 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8493 check_update_rgn( hwnd
, 0 );
8495 ok(RedrawWindow(GetDesktopWindow(), &rect
, 0,
8496 RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8497 "RedrawWindow failed\n");
8498 ret
= GetUpdateRgn( hwnd
, hrgn2
, FALSE
);
8499 ok( ret
== NULLREGION
|| broken(ret
== SIMPLEREGION
), /* <= win7 */
8500 "region should be null (%d)\n", ret
);
8501 if (ret
== SIMPLEREGION
) ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8502 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8505 ok(RedrawWindow(GetDesktopWindow(), NULL
, 0,
8506 RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8507 "RedrawWindow failed\n");
8508 ret
= GetUpdateRgn( hwnd
, hrgn2
, FALSE
);
8509 ok( ret
== NULLREGION
|| broken(ret
== SIMPLEREGION
), /* <= win7 */
8510 "region should be null (%d)\n", ret
);
8511 if (ret
== SIMPLEREGION
) ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8512 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8515 SetRectRgn( hrgn2
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8516 ok(RedrawWindow(0, NULL
, hrgn2
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8517 "RedrawWindow failed\n");
8518 check_update_rgn( hwnd
, hrgn
);
8519 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8521 ok_sequence( WmPaint
, "Paint", FALSE
);
8522 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8523 check_update_rgn( hwnd
, 0 );
8525 ok(RedrawWindow(0, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
),
8526 "RedrawWindow failed\n");
8527 check_update_rgn( hwnd
, 0 );
8529 ok(RedrawWindow(0, NULL
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
),
8530 "RedrawWindow failed\n");
8531 check_update_rgn( hwnd
, hrgn
);
8532 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8534 ok_sequence( WmPaint
, "Paint", FALSE
);
8535 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8536 check_update_rgn( hwnd
, 0 );
8538 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
8539 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8541 SetRectEmpty( &rect
);
8542 if (ValidateRect(0, &rect
) && /* not supported on Win9x */
8543 GetUpdateRect(hwnd
, NULL
, FALSE
)) /* or >= Win 8 */
8545 check_update_rgn( hwnd
, hrgn
);
8546 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8548 ok_sequence( WmPaint
, "Paint", FALSE
);
8549 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8550 check_update_rgn( hwnd
, 0 );
8553 SetLastError(0xdeadbeef);
8554 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
8555 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
8556 "wrong error code %ld\n", GetLastError());
8557 check_update_rgn( hwnd
, 0 );
8559 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8561 SetLastError(0xdeadbeef);
8562 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
8563 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
8564 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8565 "wrong error code %ld\n", GetLastError());
8566 check_update_rgn( hwnd
, 0 );
8568 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8570 SetLastError(0xdeadbeef);
8571 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
8572 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
8573 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8574 "wrong error code %ld\n", GetLastError());
8575 check_update_rgn( hwnd
, 0 );
8577 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8579 /* now with frame */
8580 SetRectRgn( hrgn
, -5, -5, 20, 20 );
8582 /* flush pending messages */
8585 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8586 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
8588 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
8589 check_update_rgn( hwnd
, hrgn
);
8592 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
8593 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
8596 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
8597 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
8599 GetClientRect( hwnd
, &rect
);
8600 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8601 check_update_rgn( hwnd
, hrgn
);
8604 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
8605 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8608 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
8609 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
8610 check_update_rgn( hwnd
, 0 );
8613 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
8614 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
8615 check_update_rgn( hwnd
, 0 );
8618 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8619 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8620 SetRectRgn( hrgn
, 0, 0, 50, 100 );
8621 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
8622 SetRectRgn( hrgn
, 50, 0, 100, 100 );
8623 check_update_rgn( hwnd
, hrgn
);
8624 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
8625 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
8626 check_update_rgn( hwnd
, 0 );
8629 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8630 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
8631 SetRectRgn( hrgn
, 0, 0, 100, 50 );
8632 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
8633 ok_sequence( WmErase
, "Erase", FALSE
);
8634 SetRectRgn( hrgn
, 0, 50, 100, 100 );
8635 check_update_rgn( hwnd
, hrgn
);
8638 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8639 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
8640 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8641 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
8642 ok_sequence( WmPaint
, "Paint", FALSE
);
8645 SetRectRgn( hrgn
, -4, -4, -2, -2 );
8646 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8647 SetRectRgn( hrgn
, -200, -200, -198, -198 );
8648 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
8649 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
8652 SetRectRgn( hrgn
, -4, -4, -2, -2 );
8653 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8654 SetRectRgn( hrgn
, -4, -4, -3, -3 );
8655 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
8656 SetRectRgn( hrgn
, 0, 0, 1, 1 );
8657 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
8658 ok_sequence( WmPaint
, "Paint", FALSE
);
8661 SetRectRgn( hrgn
, -4, -4, -1, -1 );
8662 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8663 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
8664 /* make sure no WM_PAINT was generated */
8666 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
8669 SetRectRgn( hrgn
, -4, -4, -1, -1 );
8670 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8671 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
8673 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
8675 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
8676 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
8677 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
8678 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
8679 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
8680 /* this will send WM_NCPAINT and validate the non client area */
8681 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
8682 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
8684 DispatchMessageA( &msg
);
8686 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
8688 DestroyWindow( hwnd
);
8690 /* now test with a child window */
8692 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
8693 100, 100, 200, 200, 0, 0, 0, NULL
);
8694 ok (hparent
!= 0, "Failed to create parent window\n");
8696 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
8697 10, 10, 100, 100, hparent
, 0, 0, NULL
);
8698 ok (hchild
!= 0, "Failed to create child window\n");
8700 ShowWindow( hparent
, SW_SHOW
);
8701 UpdateWindow( hparent
);
8702 UpdateWindow( hchild
);
8705 log_all_parent_messages
++;
8707 SetRect( &rect
, 0, 0, 50, 50 );
8708 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8709 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8710 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
8712 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8714 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
8715 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
8716 check_update_rgn( hchild
, hrgn
);
8717 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8718 check_update_rgn( hparent
, hrgn
);
8719 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8720 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
8721 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8722 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8725 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
8727 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8728 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8729 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
8730 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8731 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8733 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8734 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8735 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
8737 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8739 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8740 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8741 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
8743 /* flush all paint messages */
8747 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
8748 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8749 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8750 check_update_rgn( hparent
, hrgn
);
8751 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8752 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8753 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8754 check_update_rgn( hparent
, hrgn
);
8756 /* flush all paint messages */
8758 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8761 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
8762 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8763 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8764 check_update_rgn( hparent
, hrgn
);
8765 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8766 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8767 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
8768 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
8769 check_update_rgn( hparent
, hrgn
);
8770 /* flush all paint messages */
8774 /* same as above but parent gets completely validated */
8775 SetRect( &rect
, 20, 20, 30, 30 );
8776 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8777 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8778 check_update_rgn( hparent
, hrgn
);
8779 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8780 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8781 check_update_rgn( hparent
, 0 ); /* no update region */
8783 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
8785 /* make sure RDW_VALIDATE on child doesn't have the same effect */
8787 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8788 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8789 check_update_rgn( hparent
, hrgn
);
8790 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
8791 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8792 check_update_rgn( hparent
, hrgn
);
8794 /* same as above but normal WM_PAINT doesn't validate parent */
8796 SetRect( &rect
, 20, 20, 30, 30 );
8797 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8798 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8799 check_update_rgn( hparent
, hrgn
);
8800 /* no WM_PAINT in child while parent still pending */
8801 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8802 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8803 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8804 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
8807 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8808 /* no WM_PAINT in child while parent still pending */
8809 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8810 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8811 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
8812 /* now that parent is valid child should get WM_PAINT */
8813 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8814 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8815 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8816 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
8818 /* same thing with WS_CLIPCHILDREN in parent */
8820 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8821 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8822 /* changing style invalidates non client area, but we need to invalidate something else to see it */
8823 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
8824 ok_sequence( WmEmptySeq
, "No message", FALSE
);
8825 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
8826 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
8829 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8830 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8831 check_update_rgn( hparent
, hrgn
);
8832 /* no WM_PAINT in child while parent still pending */
8833 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8834 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8835 /* WM_PAINT in parent first */
8836 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8837 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
8839 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
8841 SetRect( &rect
, 0, 0, 30, 30 );
8842 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
8843 SetRectRgn( hrgn
, 0, 0, 30, 30 );
8844 check_update_rgn( hparent
, hrgn
);
8846 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
8848 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8850 SetRect( &rect
, -10, 0, 30, 30 );
8851 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8852 SetRect( &rect
, 0, 0, 20, 20 );
8853 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8854 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8855 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
8857 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8859 SetRect( &rect
, -10, 0, 30, 30 );
8860 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8861 SetRect( &rect
, 0, 0, 100, 100 );
8862 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8863 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8864 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
8865 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8866 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
8868 /* WS_CLIPCHILDREN doesn't exclude children from update region */
8870 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
8871 GetClientRect( hparent
, &rect
);
8872 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8873 check_update_rgn( hparent
, hrgn
);
8876 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8877 GetClientRect( hparent
, &rect
);
8878 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8879 check_update_rgn( hparent
, hrgn
);
8882 /* test RDW_INTERNALPAINT behavior */
8885 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
8887 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8889 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
8891 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8893 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8895 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8897 assert( GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
);
8898 UpdateWindow( hparent
);
8901 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
8902 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8903 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8904 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8906 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
8908 UpdateWindow( hparent
);
8911 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
8912 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8913 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8914 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8916 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8918 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8919 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8920 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8922 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8924 assert( !(GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
) );
8925 UpdateWindow( hparent
);
8928 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
8929 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8930 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8931 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8933 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
8935 UpdateWindow( hparent
);
8938 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
8939 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8940 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8941 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8943 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8945 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
8946 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
8948 UpdateWindow( hparent
);
8951 trace("testing SetWindowPos(-10000, -10000) on child\n");
8952 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
8953 check_update_rgn( hchild
, 0 );
8956 #if 0 /* this one doesn't pass under Wine yet */
8957 UpdateWindow( hparent
);
8960 trace("testing ShowWindow(SW_MINIMIZE) on child\n");
8961 ShowWindow( hchild
, SW_MINIMIZE
);
8962 check_update_rgn( hchild
, 0 );
8966 UpdateWindow( hparent
);
8969 trace("testing SetWindowPos(-10000, -10000) on parent\n");
8970 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
8971 check_update_rgn( hparent
, 0 );
8974 log_all_parent_messages
--;
8975 DestroyWindow( hparent
);
8976 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
8978 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
8980 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
8981 100, 100, 200, 200, 0, 0, 0, NULL
);
8982 ok (hparent
!= 0, "Failed to create parent window\n");
8984 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
8985 10, 10, 100, 100, hparent
, 0, 0, NULL
);
8986 ok (hchild
!= 0, "Failed to create child window\n");
8988 ShowWindow( hparent
, SW_SHOW
);
8989 UpdateWindow( hparent
);
8990 UpdateWindow( hchild
);
8994 /* moving child outside of parent boundaries changes update region */
8995 SetRect( &rect
, 0, 0, 40, 40 );
8996 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8997 SetRectRgn( hrgn
, 0, 0, 40, 40 );
8998 check_update_rgn( hchild
, hrgn
);
8999 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
9000 SetRectRgn( hrgn
, 10, 0, 40, 40 );
9001 check_update_rgn( hchild
, hrgn
);
9002 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
9003 SetRectRgn( hrgn
, 10, 10, 40, 40 );
9004 check_update_rgn( hchild
, hrgn
);
9006 /* moving parent off-screen does too */
9007 SetRect( &rect
, 0, 0, 100, 100 );
9008 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
9009 SetRectRgn( hrgn
, 0, 0, 100, 100 );
9010 check_update_rgn( hparent
, hrgn
);
9011 SetRectRgn( hrgn
, 10, 10, 40, 40 );
9012 check_update_rgn( hchild
, hrgn
);
9013 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
9014 GetUpdateRect( hparent
, &rect2
, FALSE
);
9015 if (!EqualRect( &rect2
, &rect
)) /* Win 8 and later don't crop update to screen */
9020 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
9021 check_update_rgn( hparent
, hrgn
);
9022 SetRectRgn( hrgn
, rect
.left
+ 10, rect
.top
+ 10, 40, 40 );
9023 check_update_rgn( hchild
, hrgn
);
9025 /* invalidated region is cropped by the parent rects */
9026 SetRect( &rect
, 0, 0, 50, 50 );
9027 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
9028 SetRectRgn( hrgn
, rect2
.left
+ 10, rect2
.top
+ 10, 50, 50 );
9029 check_update_rgn( hchild
, hrgn
);
9031 DestroyWindow( hparent
);
9032 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
9035 DeleteObject( hrgn
);
9036 DeleteObject( hrgn2
);
9047 static DWORD WINAPI
thread_proc(void *param
)
9050 struct wnd_event
*wnd_event
= param
;
9052 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
9053 100, 100, 200, 200, 0, 0, 0, NULL
);
9054 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
9056 SetEvent(wnd_event
->start_event
);
9058 while (GetMessageA(&msg
, 0, 0, 0))
9060 TranslateMessage(&msg
);
9061 DispatchMessageA(&msg
);
9064 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
9069 static DWORD CALLBACK
create_grand_child_thread( void *param
)
9071 struct wnd_event
*wnd_event
= param
;
9075 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
9076 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
9077 ok (hchild
!= 0, "Failed to create child window\n");
9080 SetEvent( wnd_event
->start_event
);
9084 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
9085 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
9086 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9091 static DWORD CALLBACK
create_child_thread( void *param
)
9093 struct wnd_event
*wnd_event
= param
;
9094 struct wnd_event child_event
;
9098 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
9099 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
9100 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
9101 SetFocus( child_event
.hwnd
);
9104 child_event
.start_event
= wnd_event
->start_event
;
9105 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
9108 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
9109 if (ret
!= 1) break;
9110 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9112 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
9113 ok( !ret
, "WaitForSingleObject failed %lx\n", ret
);
9117 static const char manifest_dep
[] =
9118 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
9119 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
9120 " <file name=\"testdep.dll\" />"
9123 static const char manifest_main
[] =
9124 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
9125 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
9127 " <dependentAssembly>"
9128 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
9129 " </dependentAssembly>"
9133 static void create_manifest_file(const char *filename
, const char *manifest
)
9135 WCHAR path
[MAX_PATH
];
9139 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
9140 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
9141 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError());
9142 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
9146 static HANDLE
test_create(const char *file
)
9148 WCHAR path
[MAX_PATH
];
9152 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
9153 memset(&actctx
, 0, sizeof(ACTCTXW
));
9154 actctx
.cbSize
= sizeof(ACTCTXW
);
9155 actctx
.lpSource
= path
;
9157 handle
= CreateActCtxW(&actctx
);
9158 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %lu\n", GetLastError());
9160 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%ld\n", actctx
.cbSize
);
9161 ok(actctx
.dwFlags
== 0, "dwFlags=%ld\n", actctx
.dwFlags
);
9162 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
9163 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
9164 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
9165 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
9166 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
9167 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
9168 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
9173 static void test_interthread_messages(void)
9175 HANDLE hThread
, context
, handle
, event
;
9181 int len
, expected_len
;
9182 struct wnd_event wnd_event
;
9185 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
9186 if (!wnd_event
.start_event
)
9188 win_skip("skipping interthread message test under win9x\n");
9192 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
9193 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
9195 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9197 CloseHandle(wnd_event
.start_event
);
9199 SetLastError(0xdeadbeef);
9200 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
9201 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
9202 "wrong error code %ld\n", GetLastError());
9204 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
9205 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
9207 expected_len
= lstrlenA("window caption text");
9208 memset(buf
, 0, sizeof(buf
));
9209 SetLastError(0xdeadbeef);
9210 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
9211 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
9212 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
9214 msg
.hwnd
= wnd_event
.hwnd
;
9215 msg
.message
= WM_GETTEXT
;
9216 msg
.wParam
= sizeof(buf
);
9217 msg
.lParam
= (LPARAM
)buf
;
9218 memset(buf
, 0, sizeof(buf
));
9219 SetLastError(0xdeadbeef);
9220 len
= DispatchMessageA(&msg
);
9221 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
9222 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %ld\n", len
, GetLastError());
9224 /* the following test causes an exception in user.exe under win9x */
9225 msg
.hwnd
= wnd_event
.hwnd
;
9226 msg
.message
= WM_TIMER
;
9228 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
9229 SetLastError(0xdeadbeef);
9230 len
= DispatchMessageA(&msg
);
9231 ok(!len
&& GetLastError() == 0xdeadbeef,
9232 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len
, GetLastError());
9234 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
9235 ok( ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
9237 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9238 CloseHandle(hThread
);
9240 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
9242 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9243 100, 100, 200, 200, 0, 0, 0, NULL
);
9244 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
9247 log_all_parent_messages
++;
9248 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
9249 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
9250 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
9253 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
9254 if (ret
!= 1) break;
9255 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9257 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
9258 /* now wait for the thread without processing messages; this shouldn't deadlock */
9259 SetEvent( wnd_event
.stop_event
);
9260 ret
= WaitForSingleObject( hThread
, 5000 );
9261 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
9262 CloseHandle( hThread
);
9264 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
9265 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
9266 CloseHandle( wnd_event
.grand_child
);
9268 CloseHandle( wnd_event
.start_event
);
9269 CloseHandle( wnd_event
.stop_event
);
9271 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
9272 log_all_parent_messages
--;
9273 DestroyWindow( wnd_event
.hwnd
);
9275 /* Activation context tests */
9276 create_manifest_file("testdep1.manifest", manifest_dep
);
9277 create_manifest_file("main.manifest", manifest_main
);
9279 context
= test_create("main.manifest");
9280 DeleteFileA("testdep1.manifest");
9281 DeleteFileA("main.manifest");
9283 handle
= (void*)0xdeadbeef;
9284 ret
= GetCurrentActCtx(&handle
);
9285 ok(ret
, "GetCurrentActCtx failed: %lu\n", GetLastError());
9286 ok(handle
== 0, "active context %p\n", handle
);
9288 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
9289 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
9290 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
9291 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9292 CloseHandle(wnd_event
.start_event
);
9294 /* context is activated after thread creation, so it doesn't inherit it by default */
9295 ret
= ActivateActCtx(context
, &cookie
);
9296 ok(ret
, "activation failed: %lu\n", GetLastError());
9299 ret
= GetCurrentActCtx(&handle
);
9300 ok(ret
, "GetCurrentActCtx failed: %lu\n", GetLastError());
9301 ok(handle
!= 0, "active context %p\n", handle
);
9302 ReleaseActCtx(handle
);
9304 /* destination window will test for active context */
9305 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
9306 ok(ret
, "thread window returned %d\n", ret
);
9308 event
= CreateEventW(NULL
, 0, 0, NULL
);
9309 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
9310 ok(ret
, "thread window returned %d\n", ret
);
9311 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9314 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
9315 ok(ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
9317 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9318 CloseHandle(hThread
);
9320 ret
= DeactivateActCtx(0, cookie
);
9321 ok(ret
, "DeactivateActCtx failed: %lu\n", GetLastError());
9322 ReleaseActCtx(context
);
9326 static const struct message WmVkN
[] = {
9327 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
9328 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
9329 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
9330 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
9331 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
9332 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9333 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
9334 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
9337 static const struct message WmShiftVkN
[] = {
9338 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
9339 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
9340 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
9341 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
9342 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
9343 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
9344 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
9345 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
9346 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9347 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
9348 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
9349 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
9350 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
9351 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
9354 static const struct message WmCtrlVkN
[] = {
9355 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
9356 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
9357 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
9358 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
9359 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
9360 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
9361 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
9362 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
9363 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9364 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
9365 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
9366 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
9367 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9368 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9371 static const struct message WmCtrlVkN_2
[] = {
9372 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
9373 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
9374 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
9375 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
9376 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
9377 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
9378 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9379 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
9380 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
9381 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
9382 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9383 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9386 static const struct message WmAltVkN
[] = {
9387 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
9388 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
9389 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
9390 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
9391 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
9392 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
9393 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
9394 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
9395 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
9396 { HCBT_SYSCOMMAND
, hook
},
9397 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
9398 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
9399 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
9400 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
9401 { WM_INITMENU
, sent
|defwinproc
},
9402 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9403 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
9404 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
9405 { WM_CAPTURECHANGED
, sent
|defwinproc
},
9406 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
9407 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9408 { WM_EXITMENULOOP
, sent
|defwinproc
},
9409 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
9410 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
9411 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
9412 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
9413 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
9414 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
9415 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
9416 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
9419 static const struct message WmAltVkN_2
[] = {
9420 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
9421 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
9422 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
9423 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
9424 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
9425 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
9426 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
9427 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
9428 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
9429 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
9430 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
9431 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
9434 static const struct message WmCtrlAltVkN
[] = {
9435 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
9436 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
9437 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
9438 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
9439 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
9440 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
9441 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
9442 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
9443 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
9444 { WM_CHAR
, optional
},
9445 { WM_CHAR
, sent
|optional
},
9446 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
9447 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
9448 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
9449 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
9450 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
9451 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
9452 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
9453 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9454 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9457 static const struct message WmCtrlShiftVkN
[] = {
9458 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
9459 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
9460 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
9461 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
9462 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
9463 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
9464 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
9465 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
9466 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
9467 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9468 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
9469 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
9470 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
9471 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
9472 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
9473 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
9474 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9475 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9478 static const struct message WmCtrlAltShiftVkN
[] = {
9479 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
9480 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
9481 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
9482 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
9483 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
9484 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
9485 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
9486 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
9487 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
9488 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
9489 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
9490 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
9491 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
9492 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
9493 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
9494 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
9495 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
9496 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
9497 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
9498 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
9499 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
9500 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
9501 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9502 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
9505 static const struct message WmAltPressRelease
[] = {
9506 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
9507 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
9508 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
9509 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
9510 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
9511 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
9512 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
9513 { HCBT_SYSCOMMAND
, hook
},
9514 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
9515 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
9516 { WM_INITMENU
, sent
|defwinproc
},
9517 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9518 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
9519 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 1 },
9521 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
9523 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9524 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0, },
9525 { WM_CAPTURECHANGED
, sent
|defwinproc
},
9526 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
9527 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9528 { WM_EXITMENULOOP
, sent
|defwinproc
},
9529 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
9530 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
9531 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
9534 static const struct message WmShiftMouseButton
[] = {
9535 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
9536 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
9537 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
9538 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
9539 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
9540 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
9541 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
9542 { WM_LBUTTONUP
, wparam
|optional
, MK_SHIFT
, 0 }, /* < w1064v1809 */
9543 { WM_LBUTTONUP
, sent
|wparam
|optional
, MK_SHIFT
, 0 }, /* < w1064v1809 */
9544 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
9545 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
9546 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
9547 { WM_LBUTTONUP
, optional
, 0, 0 }, /* >= w1064v1809 */
9548 { WM_LBUTTONUP
, sent
|optional
, 0, 0 }, /* >= w1064v1809 */
9551 static const struct message WmF1Seq
[] = {
9552 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
9553 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
9554 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
9555 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
9556 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
9557 { WM_HELP
, sent
|defwinproc
},
9558 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
9559 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
9560 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
9563 static const struct message WmVkAppsSeq
[] = {
9564 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
9565 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
9566 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
9567 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
9568 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
9569 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
9570 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
9571 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
9574 static const struct message WmVkF10Seq
[] = {
9575 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
9576 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
9577 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
9578 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
9579 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
9580 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
9581 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
9582 { HCBT_SYSCOMMAND
, hook
},
9583 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
9584 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
9585 { WM_INITMENU
, sent
|defwinproc
},
9586 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9587 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
9588 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 1 },
9590 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
9592 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
9593 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9594 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0, },
9595 { WM_CAPTURECHANGED
, sent
|defwinproc
},
9596 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
9597 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9598 { WM_EXITMENULOOP
, sent
|defwinproc
},
9599 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
9600 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
9601 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
9604 static const struct message WmShiftF10Seq
[] = {
9605 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
9606 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
9607 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
9608 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
9609 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
9610 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
9611 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
9612 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
9613 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
9614 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
9615 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
9616 { HCBT_SYSCOMMAND
, hook
},
9617 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
9618 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
9619 { WM_INITMENU
, sent
|defwinproc
},
9620 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9621 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
9622 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 1 },
9623 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
9624 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
9625 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9626 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
9627 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
9628 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
9629 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_SYSMENU
, 0 },
9630 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
9631 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
9632 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
9633 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
9637 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
9641 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
9643 struct recvd_message log_msg
;
9645 /* ignore some unwanted messages */
9646 if (msg
.message
== WM_MOUSEMOVE
||
9647 msg
.message
== WM_TIMER
||
9648 ignore_message( msg
.message
))
9651 log_msg
.hwnd
= msg
.hwnd
;
9652 log_msg
.message
= msg
.message
;
9653 log_msg
.flags
= wparam
|lparam
;
9654 log_msg
.wParam
= msg
.wParam
;
9655 log_msg
.lParam
= msg
.lParam
;
9656 log_msg
.descr
= "accel";
9657 add_message(&log_msg
);
9659 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
9661 TranslateMessage(&msg
);
9662 DispatchMessageA(&msg
);
9667 static void test_accelerators(void)
9673 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9674 100, 100, 200, 200, 0, 0, 0, NULL
);
9675 BOOL us_kbd
= (GetKeyboardLayout(0) == (HKL
)(ULONG_PTR
)0x04090409);
9684 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
9686 state
= GetKeyState(VK_SHIFT
);
9687 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
9688 state
= GetKeyState(VK_CAPITAL
);
9689 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
9691 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
9692 assert(hAccel
!= 0);
9695 pump_msg_loop(hwnd
, 0);
9700 skip("skipping ascii VK events on non-us keyboard\n");
9704 trace("testing VK_N press/release\n");
9706 keybd_event('N', 0, 0, 0);
9707 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9708 pump_msg_loop(hwnd
, hAccel
);
9709 if (!sequence_cnt
) /* we didn't get any message */
9711 skip( "queuing key events not supported\n" );
9714 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
9716 trace("testing Shift+VK_N press/release\n");
9718 keybd_event(VK_SHIFT
, 0, 0, 0);
9719 keybd_event('N', 0, 0, 0);
9720 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9721 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9722 pump_msg_loop(hwnd
, hAccel
);
9723 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
9725 trace("testing Ctrl+VK_N press/release\n");
9727 keybd_event(VK_CONTROL
, 0, 0, 0);
9728 keybd_event('N', 0, 0, 0);
9729 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9730 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9731 pump_msg_loop(hwnd
, hAccel
);
9732 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
9734 trace("testing Alt+VK_N press/release\n");
9736 keybd_event(VK_MENU
, 0, 0, 0);
9737 keybd_event('N', 0, 0, 0);
9738 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9739 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9740 pump_msg_loop(hwnd
, hAccel
);
9741 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
9743 trace("testing Ctrl+Alt+VK_N press/release 1\n");
9745 keybd_event(VK_CONTROL
, 0, 0, 0);
9746 keybd_event(VK_MENU
, 0, 0, 0);
9747 keybd_event('N', 0, 0, 0);
9748 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9749 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9750 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9751 pump_msg_loop(hwnd
, hAccel
);
9752 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
9754 ret
= DestroyAcceleratorTable(hAccel
);
9755 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
9757 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
9758 assert(hAccel
!= 0);
9760 trace("testing VK_N press/release\n");
9762 keybd_event('N', 0, 0, 0);
9763 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9764 pump_msg_loop(hwnd
, hAccel
);
9765 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
9767 trace("testing Shift+VK_N press/release\n");
9769 keybd_event(VK_SHIFT
, 0, 0, 0);
9770 keybd_event('N', 0, 0, 0);
9771 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9772 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9773 pump_msg_loop(hwnd
, hAccel
);
9774 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
9776 trace("testing Ctrl+VK_N press/release 2\n");
9778 keybd_event(VK_CONTROL
, 0, 0, 0);
9779 keybd_event('N', 0, 0, 0);
9780 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9781 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9782 pump_msg_loop(hwnd
, hAccel
);
9783 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
9785 trace("testing Alt+VK_N press/release 2\n");
9787 keybd_event(VK_MENU
, 0, 0, 0);
9788 keybd_event('N', 0, 0, 0);
9789 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9790 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9791 pump_msg_loop(hwnd
, hAccel
);
9792 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
9794 trace("testing Ctrl+Alt+VK_N press/release 2\n");
9796 keybd_event(VK_CONTROL
, 0, 0, 0);
9797 keybd_event(VK_MENU
, 0, 0, 0);
9798 keybd_event('N', 0, 0, 0);
9799 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9800 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9801 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9802 pump_msg_loop(hwnd
, hAccel
);
9803 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
9805 trace("testing Ctrl+Shift+VK_N press/release\n");
9807 keybd_event(VK_CONTROL
, 0, 0, 0);
9808 keybd_event(VK_SHIFT
, 0, 0, 0);
9809 keybd_event('N', 0, 0, 0);
9810 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9811 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9812 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9813 pump_msg_loop(hwnd
, hAccel
);
9814 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
9816 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
9818 keybd_event(VK_CONTROL
, 0, 0, 0);
9819 keybd_event(VK_MENU
, 0, 0, 0);
9820 keybd_event(VK_SHIFT
, 0, 0, 0);
9821 keybd_event('N', 0, 0, 0);
9822 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9823 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9824 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9825 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9826 pump_msg_loop(hwnd
, hAccel
);
9827 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
9829 ret
= DestroyAcceleratorTable(hAccel
);
9830 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
9833 trace("testing Alt press/release\n");
9835 keybd_event(VK_MENU
, 0, 0, 0);
9836 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9837 keybd_event(VK_MENU
, 0, 0, 0);
9838 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9839 pump_msg_loop(hwnd
, 0);
9840 /* this test doesn't pass in Wine for managed windows */
9841 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
9843 trace("testing VK_F1 press/release\n");
9844 keybd_event(VK_F1
, 0, 0, 0);
9845 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
9846 pump_msg_loop(hwnd
, 0);
9847 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
9849 trace("testing VK_APPS press/release\n");
9850 keybd_event(VK_APPS
, 0, 0, 0);
9851 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
9852 pump_msg_loop(hwnd
, 0);
9853 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
9855 trace("testing VK_F10 press/release\n");
9856 keybd_event(VK_F10
, 0, 0, 0);
9857 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9858 keybd_event(VK_F10
, 0, 0, 0);
9859 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9860 pump_msg_loop(hwnd
, 0);
9861 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", TRUE
);
9863 trace("testing SHIFT+F10 press/release\n");
9864 keybd_event(VK_SHIFT
, 0, 0, 0);
9865 keybd_event(VK_F10
, 0, 0, 0);
9866 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9867 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9868 keybd_event(VK_ESCAPE
, 0, 0, 0);
9869 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
9870 pump_msg_loop(hwnd
, 0);
9871 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
9873 trace("testing Shift+MouseButton press/release\n");
9874 /* first, move mouse pointer inside of the window client area */
9875 GetClientRect(hwnd
, &rc
);
9876 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
9877 rc
.left
+= (rc
.right
- rc
.left
)/2;
9878 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
9879 SetCursorPos(rc
.left
, rc
.top
);
9880 SetActiveWindow(hwnd
);
9885 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
9888 keybd_event(VK_SHIFT
, 0, 0, 0);
9889 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
9890 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
9891 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9892 pump_msg_loop(hwnd
, 0);
9893 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
9894 if (i
< sequence_cnt
)
9895 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
9897 skip( "Shift+MouseButton event didn't get to the window\n" );
9901 if (hAccel
) DestroyAcceleratorTable(hAccel
);
9902 DestroyWindow(hwnd
);
9905 /************* window procedures ********************/
9907 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
9908 WPARAM wParam
, LPARAM lParam
)
9910 static LONG defwndproc_counter
= 0;
9911 static LONG beginpaint_counter
= 0;
9913 struct recvd_message msg
;
9915 if (ignore_message( message
)) return 0;
9921 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9922 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
9923 "wrong WS_DISABLED state: %Id != %d\n", wParam
, !(style
& WS_DISABLED
));
9927 case WM_CAPTURECHANGED
:
9928 if (test_DestroyWindow_flag
)
9930 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9931 if (style
& WS_CHILD
)
9932 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
9933 else if (style
& WS_POPUP
)
9934 lParam
= WND_POPUP_ID
;
9936 lParam
= WND_PARENT_ID
;
9944 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
9945 capture
= GetCapture();
9948 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
9949 trace("current capture %p, releasing...\n", capture
);
9955 ok(GetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
9956 if (test_DestroyWindow_flag
)
9958 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9959 if (style
& WS_CHILD
)
9960 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
9961 else if (style
& WS_POPUP
)
9962 lParam
= WND_POPUP_ID
;
9964 lParam
= WND_PARENT_ID
;
9968 /* test_accelerators() depends on this */
9974 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo
;
9975 HANDLE handle
, event
= (HANDLE
)lParam
;
9978 handle
= (void*)0xdeadbeef;
9979 ret
= GetCurrentActCtx(&handle
);
9980 ok(ret
, "failed to get current context, %lu\n", GetLastError());
9981 ok(handle
== 0, "got active context %p\n", handle
);
9983 memset(&basicinfo
, 0xff, sizeof(basicinfo
));
9984 ret
= QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
, handle
, 0, ActivationContextBasicInformation
,
9985 &basicinfo
, sizeof(basicinfo
), NULL
);
9986 ok(ret
, "got %d, error %ld\n", ret
, GetLastError());
9987 ok(basicinfo
.hActCtx
== NULL
, "got %p\n", basicinfo
.hActCtx
);
9988 ok(basicinfo
.dwFlags
== 0, "got %lx\n", basicinfo
.dwFlags
);
9990 if (event
) SetEvent(event
);
9996 case WM_MOUSEACTIVATE
:
9997 case WM_NCMOUSEMOVE
:
10004 msg
.message
= message
;
10005 msg
.flags
= sent
|wparam
|lparam
;
10006 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10007 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
10008 msg
.wParam
= wParam
;
10009 msg
.lParam
= lParam
;
10010 msg
.descr
= "MsgCheckProc";
10013 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
10015 HWND parent
= GetParent(hwnd
);
10017 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
10019 GetClientRect(parent
, &rc
);
10020 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
10021 trace("Reserved=%ld,%ld MaxSize=%ld,%ld MaxPos=%ld,%ld MinTrack=%ld,%ld MaxTrack=%ld,%ld\n",
10022 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
10023 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
10024 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
10025 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
10026 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
10028 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
10029 minmax
->ptMaxSize
.x
, rc
.right
);
10030 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
10031 minmax
->ptMaxSize
.y
, rc
.bottom
);
10034 if (message
== WM_PAINT
)
10037 beginpaint_counter
++;
10038 BeginPaint( hwnd
, &ps
);
10039 beginpaint_counter
--;
10040 EndPaint( hwnd
, &ps
);
10044 if (!test_context_menu
&& message
== WM_CONTEXTMENU
)
10046 /* don't create context menu */
10050 defwndproc_counter
++;
10051 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
10052 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10053 defwndproc_counter
--;
10058 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10060 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
10063 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10065 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
10068 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10070 static LONG defwndproc_counter
= 0;
10072 struct recvd_message msg
;
10074 if (ignore_message( message
)) return 0;
10078 case WM_QUERYENDSESSION
:
10079 case WM_ENDSESSION
:
10080 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
10085 msg
.message
= message
;
10086 msg
.flags
= sent
|wparam
|lparam
;
10087 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10088 msg
.wParam
= wParam
;
10089 msg
.lParam
= lParam
;
10090 msg
.descr
= "popup";
10093 if (message
== WM_CREATE
)
10095 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
10096 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
10099 defwndproc_counter
++;
10100 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10101 defwndproc_counter
--;
10106 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10108 static LONG defwndproc_counter
= 0;
10109 static LONG beginpaint_counter
= 0;
10111 struct recvd_message msg
;
10113 if (ignore_message( message
)) return 0;
10115 if (log_all_parent_messages
||
10116 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
10117 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
10118 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
10119 message
== WM_DRAWITEM
|| message
== WM_MEASUREITEM
|| message
== WM_COMPAREITEM
||
10120 message
== WM_COMMAND
|| message
== WM_IME_SETCONTEXT
)
10129 case WM_NCMOUSEMOVE
:
10132 case WM_ERASEBKGND
:
10135 INT ret
= GetClipBox((HDC
)wParam
, &rc
);
10137 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret
, wine_dbgstr_rect(&rc
));
10143 msg
.message
= message
;
10144 msg
.flags
= sent
|parent
|wparam
|lparam
;
10145 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10146 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
10147 msg
.wParam
= wParam
;
10148 msg
.lParam
= lParam
;
10149 msg
.descr
= "parent";
10153 if (message
== WM_PAINT
)
10156 beginpaint_counter
++;
10157 BeginPaint( hwnd
, &ps
);
10158 beginpaint_counter
--;
10159 EndPaint( hwnd
, &ps
);
10163 defwndproc_counter
++;
10164 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10165 defwndproc_counter
--;
10167 return message
== WM_COMPAREITEM
? -1 : ret
;
10170 static LRESULT CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
10172 if (message
== WM_CREATE
)
10173 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
10174 else if (message
== WM_CLOSE
)
10176 /* Only the first WM_QUIT will survive the window destruction */
10177 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
10178 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
10179 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
10182 return DefWindowProcA(hwnd
, message
, wp
, lp
);
10185 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10187 static LONG defwndproc_counter
= 0;
10189 struct recvd_message msg
;
10191 if (ignore_message( message
)) return 0;
10195 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
10196 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
10197 if (after_end_dialog
)
10198 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %Ix\n", ret
);
10200 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %Ix\n", ret
);
10204 msg
.message
= message
;
10205 msg
.flags
= sent
|wparam
|lparam
;
10206 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10207 msg
.wParam
= wParam
;
10208 msg
.lParam
= lParam
;
10209 msg
.descr
= "dialog";
10212 defwndproc_counter
++;
10213 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
10214 defwndproc_counter
--;
10219 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10221 static LONG defwndproc_counter
= 0;
10223 struct recvd_message msg
;
10225 /* log only specific messages we are interested in */
10228 #if 0 /* probably log these as well */
10233 case WM_SHOWWINDOW
:
10236 case WM_GETMINMAXINFO
:
10237 case WM_WINDOWPOSCHANGING
:
10238 case WM_WINDOWPOSCHANGED
:
10241 default: /* ignore */
10242 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
10243 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10247 msg
.message
= message
;
10248 msg
.flags
= sent
|wparam
|lparam
;
10249 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10250 msg
.wParam
= wParam
;
10251 msg
.lParam
= lParam
;
10252 msg
.descr
= "show";
10255 defwndproc_counter
++;
10256 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10257 defwndproc_counter
--;
10262 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
10266 case WM_CREATE
: return 0;
10275 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
10277 TranslateMessage(&msg2
);
10278 DispatchMessageA(&msg2
);
10282 else ok(broken(1), "infinite loop\n");
10284 paint_loop_done
= TRUE
;
10285 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
10288 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
10291 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10293 static LONG defwndproc_counter
= 0;
10295 struct recvd_message msg
;
10296 DWORD queue_status
;
10298 if (ignore_message( message
)) return 0;
10300 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
10301 message
== WM_HOTKEY
|| message
>= WM_APP
)
10304 msg
.message
= message
;
10305 msg
.flags
= sent
|wparam
|lparam
;
10306 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10307 msg
.wParam
= wParam
;
10308 msg
.lParam
= lParam
;
10309 msg
.descr
= "HotkeyMsgCheckProcA";
10313 defwndproc_counter
++;
10314 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10315 defwndproc_counter
--;
10317 if (message
== WM_APP
)
10319 queue_status
= GetQueueStatus(QS_HOTKEY
);
10320 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
10321 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
10322 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %lx\n", queue_status
);
10323 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
10325 else if (message
== WM_APP
+1)
10327 queue_status
= GetQueueStatus(QS_HOTKEY
);
10328 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %lx\n", queue_status
);
10334 static BOOL
RegisterWindowClasses(void)
10340 cls
.lpfnWndProc
= MsgCheckProcA
;
10341 cls
.cbClsExtra
= 0;
10342 cls
.cbWndExtra
= 0;
10343 cls
.hInstance
= GetModuleHandleA(0);
10345 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
10346 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
10347 cls
.lpszMenuName
= NULL
;
10348 cls
.lpszClassName
= "TestWindowClass";
10349 if(!RegisterClassA(&cls
)) return FALSE
;
10351 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
10352 cls
.lpszClassName
= "HotkeyWindowClass";
10353 if(!RegisterClassA(&cls
)) return FALSE
;
10355 cls
.lpfnWndProc
= ShowWindowProcA
;
10356 cls
.lpszClassName
= "ShowWindowClass";
10357 if(!RegisterClassA(&cls
)) return FALSE
;
10359 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
10360 cls
.lpszClassName
= "TestPopupClass";
10361 if(!RegisterClassA(&cls
)) return FALSE
;
10363 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
10364 cls
.lpszClassName
= "TestParentClass";
10365 if(!RegisterClassA(&cls
)) return FALSE
;
10367 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
10368 cls
.lpszClassName
= "StopQuitClass";
10369 if(!RegisterClassA(&cls
)) return FALSE
;
10371 cls
.lpfnWndProc
= DefWindowProcA
;
10372 cls
.lpszClassName
= "SimpleWindowClass";
10373 if(!RegisterClassA(&cls
)) return FALSE
;
10375 cls
.lpfnWndProc
= PaintLoopProcA
;
10376 cls
.lpszClassName
= "PaintLoopWindowClass";
10377 if(!RegisterClassA(&cls
)) return FALSE
;
10379 cls
.style
= CS_NOCLOSE
;
10380 cls
.lpszClassName
= "NoCloseWindowClass";
10381 if(!RegisterClassA(&cls
)) return FALSE
;
10383 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
10385 cls
.hInstance
= GetModuleHandleA(0);
10386 cls
.hbrBackground
= 0;
10387 cls
.lpfnWndProc
= TestDlgProcA
;
10388 cls
.lpszClassName
= "TestDialogClass";
10389 if(!RegisterClassA(&cls
)) return FALSE
;
10392 clsW
.lpfnWndProc
= MsgCheckProcW
;
10393 clsW
.cbClsExtra
= 0;
10394 clsW
.cbWndExtra
= 0;
10395 clsW
.hInstance
= GetModuleHandleW(0);
10397 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
10398 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
10399 clsW
.lpszMenuName
= NULL
;
10400 clsW
.lpszClassName
= testWindowClassW
;
10401 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
10406 static BOOL
is_our_logged_class(HWND hwnd
)
10410 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
10412 if (!lstrcmpiA(buf
, "TestWindowClass") ||
10413 !lstrcmpiA(buf
, "ShowWindowClass") ||
10414 !lstrcmpiA(buf
, "TestParentClass") ||
10415 !lstrcmpiA(buf
, "TestPopupClass") ||
10416 !lstrcmpiA(buf
, "SimpleWindowClass") ||
10417 !lstrcmpiA(buf
, "TestDialogClass") ||
10418 !lstrcmpiA(buf
, "MDI_frame_class") ||
10419 !lstrcmpiA(buf
, "MDI_client_class") ||
10420 !lstrcmpiA(buf
, "MDI_child_class") ||
10421 !lstrcmpiA(buf
, "my_button_class") ||
10422 !lstrcmpiA(buf
, "my_edit_class") ||
10423 !lstrcmpiA(buf
, "static") ||
10424 !lstrcmpiA(buf
, "ListBox") ||
10425 !lstrcmpiA(buf
, "ComboBox") ||
10426 !lstrcmpiA(buf
, "MyDialogClass") ||
10427 !lstrcmpiA(buf
, "#32770") ||
10428 !lstrcmpiA(buf
, "#32768"))
10434 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
10438 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
10440 if (nCode
== HCBT_CLICKSKIPPED
)
10442 /* ignore this event, XP sends it a lot when switching focus between windows */
10443 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
10446 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
10448 struct recvd_message msg
;
10451 msg
.message
= nCode
;
10452 msg
.flags
= hook
|wparam
|lparam
;
10453 msg
.wParam
= wParam
;
10454 msg
.lParam
= lParam
;
10458 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
10461 if (nCode
== HCBT_DESTROYWND
)
10463 if (test_DestroyWindow_flag
)
10465 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
10466 if (style
& WS_CHILD
)
10467 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
10468 else if (style
& WS_POPUP
)
10469 lParam
= WND_POPUP_ID
;
10471 lParam
= WND_PARENT_ID
;
10475 /* Log also SetFocus(0) calls */
10476 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
10478 if (is_our_logged_class(hwnd
))
10480 struct recvd_message msg
;
10483 msg
.message
= nCode
;
10484 msg
.flags
= hook
|wparam
|lparam
;
10485 msg
.wParam
= wParam
;
10486 msg
.lParam
= lParam
;
10490 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
10493 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
10501 ok(thread_id
== winevent_hook_thread_id
, "we didn't ask for events from other threads\n");
10503 /* ignore mouse cursor events */
10504 if (object_id
== OBJID_CURSOR
) return;
10506 if (!hwnd
|| is_our_logged_class(hwnd
))
10508 struct recvd_message msg
;
10511 msg
.message
= event
;
10512 msg
.flags
= winevent_hook
|wparam
|lparam
;
10513 msg
.wParam
= object_id
;
10514 msg
.lParam
= child_id
;
10520 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
10521 static const WCHAR wszAnsi
[] = {'U',0};
10523 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
10527 case CB_FINDSTRINGEXACT
:
10528 trace("String: %p\n", (LPCWSTR
)lParam
);
10529 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
10531 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
10535 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
10538 static const struct message WmGetTextLengthAfromW
[] = {
10539 { WM_GETTEXTLENGTH
, sent
},
10540 { WM_GETTEXT
, sent
|optional
},
10544 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
10546 /* dummy window proc for WM_GETTEXTLENGTH test */
10547 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
10551 case WM_GETTEXTLENGTH
:
10552 return lstrlenW(dummy_window_text
) + 37; /* some random length */
10554 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
10555 return lstrlenW( (LPWSTR
)lp
);
10557 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
10561 static void test_message_conversion(void)
10563 static const WCHAR wszMsgConversionClass
[] =
10564 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
10568 WNDPROC wndproc
, newproc
;
10572 cls
.lpfnWndProc
= MsgConversionProcW
;
10573 cls
.cbClsExtra
= 0;
10574 cls
.cbWndExtra
= 0;
10575 cls
.hInstance
= GetModuleHandleW(NULL
);
10577 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
10578 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
10579 cls
.lpszMenuName
= NULL
;
10580 cls
.lpszClassName
= wszMsgConversionClass
;
10581 /* this call will fail on Win9x, but that doesn't matter as this test is
10582 * meaningless on those platforms */
10583 if(!RegisterClassW(&cls
)) return;
10585 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
10586 100, 100, 200, 200, 0, 0, 0, NULL
);
10587 ok(hwnd
!= NULL
, "Window creation failed\n");
10591 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
10592 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10593 ok(lRes
== 0, "String should have been converted\n");
10594 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10595 ok(lRes
== 1, "String shouldn't have been converted\n");
10599 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
10600 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10601 ok(lRes
== 1, "String shouldn't have been converted\n");
10602 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10603 ok(lRes
== 1, "String shouldn't have been converted\n");
10605 /* Synchronous messages */
10607 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10608 ok(lRes
== 0, "String should have been converted\n");
10609 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10610 ok(lRes
== 1, "String shouldn't have been converted\n");
10612 /* Asynchronous messages */
10615 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10616 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10617 "PostMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10619 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10620 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10621 "PostMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10623 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10624 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10625 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10627 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10628 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10629 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10631 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10632 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10633 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10635 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
10636 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10637 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10639 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
10640 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10641 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10643 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
10644 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
10645 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
10647 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
10649 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
10650 WS_OVERLAPPEDWINDOW
,
10651 100, 100, 200, 200, 0, 0, 0, NULL
);
10654 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
10655 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
10656 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
10657 "got bad length %Id\n", lRes
);
10660 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
10661 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
10662 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
10663 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
10664 "got bad length %Id\n", lRes
);
10666 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
10667 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
10668 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
10669 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
10670 NULL
, 0, NULL
, NULL
) ||
10671 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
10672 "got bad length %Id\n", lRes
);
10674 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
10675 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
10676 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
10677 NULL
, 0, NULL
, NULL
) ||
10678 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
10679 "got bad length %Id\n", lRes
);
10681 ret
= DestroyWindow(hwnd
);
10682 ok( ret
, "DestroyWindow() error %ld\n", GetLastError());
10692 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
10696 #define TIMER_ID 0x19
10697 #define TIMER_COUNT_EXPECTED 100
10698 #define TIMER_COUNT_TOLERANCE 10
10700 static int count
= 0;
10701 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
10706 static DWORD exception
;
10707 static void CALLBACK
callback_exception(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
10710 RaiseException(exception
, 0, 0, NULL
);
10713 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
10715 struct timer_info
*info
= x
;
10718 r
= KillTimer(info
->hWnd
, 0x19);
10719 ok(r
,"KillTimer failed in thread\n");
10720 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
10721 ok(r
,"SetTimer failed in thread\n");
10722 ok(r
==TIMER_ID
,"SetTimer id different\n");
10723 r
= SetEvent(info
->handles
[0]);
10724 ok(r
,"SetEvent failed in thread\n");
10728 static void test_timers(void)
10730 struct timer_info info
;
10735 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
10736 WS_OVERLAPPEDWINDOW
,
10737 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
10740 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
10741 ok(info
.id
, "SetTimer failed\n");
10742 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
10743 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
10744 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
10746 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
10748 WaitForSingleObject(info
.handles
[1], INFINITE
);
10750 CloseHandle(info
.handles
[0]);
10751 CloseHandle(info
.handles
[1]);
10753 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
10755 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
10756 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
10757 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
10758 * ±9 counts (~4 ms) around the expected value.
10761 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
10762 ok(id
!= 0, "did not get id from SetTimer.\n");
10763 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
10764 start
= GetTickCount();
10765 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
10766 DispatchMessageA(&msg
);
10767 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
10768 || broken(abs(count
-64) <= TIMER_COUNT_TOLERANCE
) /* most common */
10769 || broken(abs(count
-43) <= TIMER_COUNT_TOLERANCE
) /* w2k3, win8 */,
10770 "did not get expected count for minimum timeout (%d != ~%d).\n",
10771 count
, TIMER_COUNT_EXPECTED
);
10772 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
10773 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
10774 if (pSetSystemTimer
)
10779 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
10780 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
10781 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
10782 start
= GetTickCount();
10783 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
10785 if (msg
.message
== WM_SYSTIMER
)
10787 DispatchMessageA(&msg
);
10789 ok(abs(syscount
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
10790 || broken(abs(syscount
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
10791 || broken(syscount
> 4000 && syscount
< 12000) /* win2k3sp0 */,
10792 "did not get expected count for minimum timeout (%d != ~%d).\n",
10793 syscount
, TIMER_COUNT_EXPECTED
);
10794 ok(count
== 0, "did not get expected count for callback timeout (%d != 0).\n", count
);
10795 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
10798 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
10801 static void test_timers_no_wnd(void)
10803 static UINT_PTR ids
[0xffff];
10810 id
= SetTimer(NULL
, 0, 100, callback_count
);
10811 ok(id
!= 0, "did not get id from SetTimer.\n");
10812 id2
= SetTimer(NULL
, id
, 200, callback_count
);
10813 ok(id2
== id
, "did not get same id from SetTimer when replacing (%Ii expected %Ii).\n", id2
, id
);
10815 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10816 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
10818 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10819 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
10820 KillTimer(NULL
, id
);
10822 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10823 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
10825 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
10826 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
10827 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
10828 * ±9 counts (~4 ms) around the expected value.
10831 id
= SetTimer(NULL
, 0, 0, callback_count
);
10832 ok(id
!= 0, "did not get id from SetTimer.\n");
10833 start
= GetTickCount();
10834 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, NULL
, 0, 0))
10835 DispatchMessageA(&msg
);
10836 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
10837 || broken(abs(count
-64) <= TIMER_COUNT_TOLERANCE
) /* most common */
10838 || broken(abs(count
-43) <= TIMER_COUNT_TOLERANCE
) /* w1064v1809 */,
10839 "did not get expected count for minimum timeout (%d != ~%d).\n",
10840 count
, TIMER_COUNT_EXPECTED
);
10841 KillTimer(NULL
, id
);
10842 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
10844 if (pSetCoalescableTimer
)
10847 id
= pSetCoalescableTimer(NULL
, 0, 0, callback_count
, 0);
10848 ok(id
!= 0, "SetCoalescableTimer failed with %lu.\n", GetLastError());
10849 start
= GetTickCount();
10850 while (GetTickCount()-start
< 100 && GetMessageA(&msg
, NULL
, 0, 0))
10851 DispatchMessageA(&msg
);
10852 ok(count
> 1, "expected count > 1, got %d.\n", count
);
10853 KillTimer(NULL
, id
);
10856 win_skip("SetCoalescableTimer not available.\n");
10858 /* Check what happens when we're running out of timers */
10859 for (i
= 0; i
< ARRAY_SIZE(ids
); i
++)
10861 SetLastError(0xdeadbeef);
10862 ids
[i
] = SetTimer(NULL
, 0, USER_TIMER_MAXIMUM
, tfunc
);
10863 if (!ids
[i
]) break;
10865 ok(i
!= ARRAY_SIZE(ids
), "all timers were created successfully\n");
10866 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES
|| broken(GetLastError()==0xdeadbeef),
10867 "GetLastError() = %ld\n", GetLastError());
10868 while (i
> 0) KillTimer(NULL
, ids
[--i
]);
10871 static void test_timers_exception(DWORD code
)
10877 id
= SetTimer(NULL
, 0, 1000, callback_exception
);
10878 ok(id
!= 0, "did not get id from SetTimer.\n");
10880 memset(&msg
, 0, sizeof(msg
));
10881 msg
.message
= WM_TIMER
;
10883 msg
.lParam
= (LPARAM
)callback_exception
;
10886 DispatchMessageA(&msg
);
10887 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
10889 KillTimer(NULL
, id
);
10892 static void test_timers_exceptions(void)
10894 test_timers_exception(EXCEPTION_ACCESS_VIOLATION
);
10895 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT
);
10896 test_timers_exception(EXCEPTION_BREAKPOINT
);
10897 test_timers_exception(EXCEPTION_SINGLE_STEP
);
10898 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED
);
10899 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND
);
10900 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO
);
10901 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT
);
10902 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION
);
10903 test_timers_exception(0xE000BEEF); /* customer exception */
10906 /* Various win events with arbitrary parameters */
10907 static const struct message WmWinEventsSeq
[] = {
10908 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
10909 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
10910 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
10911 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
10912 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
10913 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
10914 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
10915 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
10916 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
10917 /* our win event hook ignores OBJID_CURSOR events */
10918 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
10919 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
10920 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
10921 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
10922 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
10923 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
10924 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
10925 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
10926 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
10927 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
10928 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
10929 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
10930 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
10931 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
10934 static const struct message WmWinEventCaretSeq
[] = {
10935 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10936 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10937 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
10938 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10941 static const struct message WmWinEventCaretSeq_2
[] = {
10942 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10943 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10944 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10947 static const struct message WmWinEventAlertSeq
[] = {
10948 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
10951 static const struct message WmWinEventAlertSeq_2
[] = {
10952 /* create window in the thread proc */
10953 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
10954 /* our test event */
10955 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
10958 static const struct message WmGlobalHookSeq_1
[] = {
10959 /* create window in the thread proc */
10960 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
10961 /* our test events */
10962 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
10963 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
10966 static const struct message WmGlobalHookSeq_2
[] = {
10967 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
10968 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
10969 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
10970 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
10974 static const struct message WmMouseLLHookSeq
[] = {
10975 { WM_MOUSEMOVE
, hook
},
10976 { WM_LBUTTONUP
, hook
},
10977 { WM_MOUSEMOVE
, hook
},
10981 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
10991 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
10993 if (!lstrcmpiA(buf
, "TestWindowClass") ||
10994 !lstrcmpiA(buf
, "static"))
10996 struct recvd_message msg
;
10999 msg
.message
= event
;
11000 msg
.flags
= winevent_hook
|wparam
|lparam
;
11001 msg
.wParam
= object_id
;
11002 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
11003 msg
.descr
= "WEH_2";
11009 static HHOOK hCBT_global_hook
;
11010 static DWORD cbt_global_hook_thread_id
;
11012 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
11017 if (nCode
== HCBT_SYSCOMMAND
)
11019 struct recvd_message msg
;
11022 msg
.message
= nCode
;
11023 msg
.flags
= hook
|wparam
|lparam
;
11024 msg
.wParam
= wParam
;
11025 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
11026 msg
.descr
= "CBT_2";
11029 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11031 /* WH_MOUSE_LL hook */
11032 if (nCode
== HC_ACTION
)
11034 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
11036 /* we can't test for real mouse events */
11037 if (mhll
->flags
& LLMHF_INJECTED
)
11039 struct recvd_message msg
;
11041 memset (&msg
, 0, sizeof (msg
));
11042 msg
.message
= wParam
;
11044 msg
.descr
= "CBT_2";
11047 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11050 /* Log also SetFocus(0) calls */
11051 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
11053 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
11055 if (!lstrcmpiA(buf
, "TestWindowClass") ||
11056 !lstrcmpiA(buf
, "static"))
11058 struct recvd_message msg
;
11061 msg
.message
= nCode
;
11062 msg
.flags
= hook
|wparam
|lparam
;
11063 msg
.wParam
= wParam
;
11064 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
11065 msg
.descr
= "CBT_2";
11069 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11072 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
11076 HANDLE hevent
= *(HANDLE
*)param
;
11078 assert(pNotifyWinEvent
);
11080 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
11082 trace("created thread window %p\n", hwnd
);
11084 *(HWND
*)param
= hwnd
;
11087 /* this event should be received only by our new hook proc,
11088 * an old one does not expect an event from another thread.
11090 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
11093 while (GetMessageA(&msg
, 0, 0, 0))
11095 TranslateMessage(&msg
);
11096 DispatchMessageA(&msg
);
11101 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
11105 HANDLE hevent
= *(HANDLE
*)param
;
11108 /* these events should be received only by our new hook proc,
11109 * an old one does not expect an event from another thread.
11112 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
11114 trace("created thread window %p\n", hwnd
);
11116 *(HWND
*)param
= hwnd
;
11118 /* Windows doesn't like when a thread plays games with the focus,
11119 that leads to all kinds of misbehaviours and failures to activate
11120 a window. So, better keep next lines commented out.
11124 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
11125 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
11129 while (GetMessageA(&msg
, 0, 0, 0))
11131 TranslateMessage(&msg
);
11132 DispatchMessageA(&msg
);
11137 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
11141 HANDLE hevent
= *(HANDLE
*)param
;
11143 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
11145 trace("created thread window %p\n", hwnd
);
11147 *(HWND
*)param
= hwnd
;
11151 /* Windows doesn't like when a thread plays games with the focus,
11152 * that leads to all kinds of misbehaviours and failures to activate
11153 * a window. So, better don't generate a mouse click message below.
11155 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
11156 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
11157 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
11160 while (GetMessageA(&msg
, 0, 0, 0))
11162 TranslateMessage(&msg
);
11163 DispatchMessageA(&msg
);
11168 static void test_winevents(void)
11174 HANDLE hthread
, hevent
;
11176 HWINEVENTHOOK hhook
;
11177 const struct message
*events
= WmWinEventsSeq
;
11179 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
11180 WS_OVERLAPPEDWINDOW
,
11181 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
11185 /****** start of global hook test *************/
11186 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
11187 if (!hCBT_global_hook
)
11189 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
11190 skip( "cannot set global hook\n" );
11194 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
11198 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
11199 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
11201 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
11203 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
11206 /* this one should be received only by old hook proc */
11207 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
11208 /* this one should be received only by old hook proc */
11209 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
11211 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
11213 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
11214 ok( ret
, "UnhookWindowsHookEx error %ld\n", GetLastError());
11216 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
11217 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
11218 CloseHandle(hthread
);
11219 CloseHandle(hevent
);
11220 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
11221 /****** end of global hook test *************/
11223 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
11225 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
11233 /* this test doesn't pass under Win9x */
11234 /* win2k ignores events with hwnd == 0 */
11235 SetLastError(0xdeadbeef);
11236 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
11237 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
11238 GetLastError() == 0xdeadbeef, /* Win9x */
11239 "unexpected error %ld\n", GetLastError());
11240 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
11243 for (i
= 0; i
< ARRAY_SIZE(WmWinEventsSeq
); i
++)
11244 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
11246 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
11248 /****** start of event filtering test *************/
11249 hhook
= pSetWinEventHook(
11250 EVENT_OBJECT_SHOW
, /* 0x8002 */
11251 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
11252 GetModuleHandleA(0), win_event_global_hook_proc
,
11253 GetCurrentProcessId(), 0,
11254 WINEVENT_INCONTEXT
);
11255 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
11257 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
11261 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
11262 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
11264 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
11266 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
11269 /* this one should be received only by old hook proc */
11270 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
11271 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
11272 /* this one should be received only by old hook proc */
11273 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
11275 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
11277 ret
= pUnhookWinEvent(hhook
);
11278 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
11280 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
11281 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
11282 CloseHandle(hthread
);
11283 CloseHandle(hevent
);
11284 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
11285 /****** end of event filtering test *************/
11287 /****** start of out of context event test *************/
11288 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
11289 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
11290 WINEVENT_OUTOFCONTEXT
);
11291 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
11293 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
11299 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
11300 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
11302 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
11304 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
11305 /* process pending winevent messages */
11306 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
11307 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
11310 /* this one should be received only by old hook proc */
11311 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
11312 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
11313 /* this one should be received only by old hook proc */
11314 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
11316 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
11317 /* process pending winevent messages */
11318 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
11319 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
11321 ret
= pUnhookWinEvent(hhook
);
11322 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
11324 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
11325 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
11326 CloseHandle(hthread
);
11327 CloseHandle(hevent
);
11328 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
11329 /****** end of out of context event test *************/
11331 /****** start of MOUSE_LL hook test *************/
11332 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
11333 /* WH_MOUSE_LL is not supported on Win9x platforms */
11334 if (!hCBT_global_hook
)
11336 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
11337 goto skip_mouse_ll_hook_test
;
11340 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
11344 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
11345 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
11347 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
11348 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
11350 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
11353 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
11354 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
11355 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
11357 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
11359 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
11360 ok( ret
, "UnhookWindowsHookEx error %ld\n", GetLastError());
11362 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
11363 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
11364 CloseHandle(hthread
);
11365 CloseHandle(hevent
);
11366 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
11367 /****** end of MOUSE_LL hook test *************/
11368 skip_mouse_ll_hook_test
:
11370 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
11373 static void test_set_hook(void)
11377 HWINEVENTHOOK hwinevent_hook
;
11379 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
11380 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
11381 UnhookWindowsHookEx(hhook
);
11385 /* this test doesn't pass under Win9x: BUG! */
11386 SetLastError(0xdeadbeef);
11387 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
11388 ok(!hhook
, "global hook requires hModule != 0\n");
11389 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
11392 SetLastError(0xdeadbeef);
11393 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
11394 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
11395 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
|| /* Win2k */
11396 GetLastError() == 0xdeadbeef, /* Win9x */
11397 "unexpected error %ld\n", GetLastError());
11399 SetLastError(0xdeadbeef);
11400 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
11401 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
|| /* Win2k */
11402 GetLastError() == 0xdeadbeef, /* Win9x */
11403 "unexpected error %ld\n", GetLastError());
11405 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
11407 /* even process local incontext hooks require hmodule */
11408 SetLastError(0xdeadbeef);
11409 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
11410 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
11411 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
11412 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
11413 GetLastError() == 0xdeadbeef, /* Win9x */
11414 "unexpected error %ld\n", GetLastError());
11416 /* even thread local incontext hooks require hmodule */
11417 SetLastError(0xdeadbeef);
11418 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
11419 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
11420 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
11421 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
11422 GetLastError() == 0xdeadbeef, /* Win9x */
11423 "unexpected error %ld\n", GetLastError());
11427 /* these 3 tests don't pass under Win9x */
11428 SetLastError(0xdeadbeef);
11429 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
11430 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
11431 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
11432 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
11434 SetLastError(0xdeadbeef);
11435 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
11436 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
11437 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
11438 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
11440 SetLastError(0xdeadbeef);
11441 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
11442 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
11443 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
11444 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %ld\n", GetLastError());
11447 SetLastError(0xdeadbeef);
11448 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
11449 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
11450 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
11451 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
11452 ret
= pUnhookWinEvent(hwinevent_hook
);
11453 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
11456 /* This call succeeds under win2k SP4, but fails under Wine.
11457 Does win2k test/use passed process id? */
11458 SetLastError(0xdeadbeef);
11459 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
11460 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
11461 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
11462 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
11463 ret
= pUnhookWinEvent(hwinevent_hook
);
11464 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
11467 SetLastError(0xdeadbeef);
11468 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
11469 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
11470 GetLastError() == 0xdeadbeef, /* Win9x */
11471 "unexpected error %ld\n", GetLastError());
11474 static HWND hook_hwnd
;
11475 static HHOOK recursive_hook
;
11476 static int hook_depth
, max_hook_depth
;
11478 static LRESULT WINAPI
rec_get_message_hook(int code
, WPARAM w
, LPARAM l
)
11485 if(hook_depth
> max_hook_depth
)
11486 max_hook_depth
= hook_depth
;
11488 b
= PeekMessageW(&msg
, hook_hwnd
, 0, 0, PM_NOREMOVE
);
11489 ok(b
, "PeekMessage failed\n");
11491 res
= CallNextHookEx(recursive_hook
, code
, w
, l
);
11497 static void test_recursive_hook(void)
11502 hook_hwnd
= CreateWindowA("Static", NULL
, WS_POPUP
, 0, 0, 200, 60, NULL
, NULL
, NULL
, NULL
);
11503 ok(hook_hwnd
!= NULL
, "CreateWindow failed\n");
11505 recursive_hook
= SetWindowsHookExW(WH_GETMESSAGE
, rec_get_message_hook
, NULL
, GetCurrentThreadId());
11506 ok(recursive_hook
!= NULL
, "SetWindowsHookEx failed\n");
11508 PostMessageW(hook_hwnd
, WM_USER
, 0, 0);
11509 PostMessageW(hook_hwnd
, WM_USER
+1, 0, 0);
11512 GetMessageW(&msg
, hook_hwnd
, 0, 0);
11513 ok(15 <= max_hook_depth
&& max_hook_depth
< 45, "max_hook_depth = %d\n", max_hook_depth
);
11514 trace("max_hook_depth = %d\n", max_hook_depth
);
11516 b
= UnhookWindowsHookEx(recursive_hook
);
11517 ok(b
, "UnhokWindowsHookEx failed\n");
11519 DestroyWindow(hook_hwnd
);
11522 static const struct message ScrollWindowPaint1
[] = {
11523 { WM_PAINT
, sent
},
11524 { WM_ERASEBKGND
, sent
|beginpaint
},
11525 { WM_GETTEXTLENGTH
, sent
|optional
},
11526 { WM_PAINT
, sent
|optional
},
11527 { WM_NCPAINT
, sent
|beginpaint
|optional
},
11528 { WM_GETTEXT
, sent
|beginpaint
|optional
},
11529 { WM_GETTEXT
, sent
|beginpaint
|optional
},
11530 { WM_GETTEXT
, sent
|beginpaint
|optional
},
11531 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
11532 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
11536 static const struct message ScrollWindowPaint2
[] = {
11537 { WM_PAINT
, sent
},
11541 static void test_scrollwindowex(void)
11544 RECT rect
={0,0,130,130};
11546 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
11547 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
11548 100, 100, 200, 200, 0, 0, 0, NULL
);
11549 ok (hwnd
!= 0, "Failed to create overlapped window\n");
11550 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
11551 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
11552 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
11553 ok (hchild
!= 0, "Failed to create child\n");
11554 UpdateWindow(hwnd
);
11558 /* scroll without the child window */
11559 trace("start scroll\n");
11560 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
11561 SW_ERASE
|SW_INVALIDATE
);
11562 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
11563 trace("end scroll\n");
11566 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
11570 /* Now without the SW_ERASE flag */
11571 trace("start scroll\n");
11572 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
11573 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
11574 trace("end scroll\n");
11577 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
11581 /* now scroll the child window as well */
11582 trace("start scroll\n");
11583 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
11584 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
11585 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
11586 /* windows sometimes a WM_MOVE */
11587 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
11588 trace("end scroll\n");
11591 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
11595 /* now scroll with ScrollWindow() */
11596 trace("start scroll with ScrollWindow\n");
11597 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
11598 trace("end scroll\n");
11601 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
11603 ok(DestroyWindow(hchild
), "failed to destroy window\n");
11604 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
11608 static const struct message destroy_window_with_children
[] = {
11609 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* popup */
11610 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
11611 { 0x0090, sent
|optional
},
11612 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
11613 { 0x0090, sent
|optional
},
11614 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* popup */
11615 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
11616 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
11617 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
11618 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 }, /* parent */
11619 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
11620 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
11621 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
11622 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
11623 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
11624 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
11625 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
11626 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
11630 static void test_DestroyWindow(void)
11633 HWND parent
, child1
, child2
, child3
, child4
, test
;
11634 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
11636 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11637 100, 100, 200, 200, 0, 0, 0, NULL
);
11638 assert(parent
!= 0);
11639 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
11640 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
11641 assert(child1
!= 0);
11642 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
11643 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
11644 assert(child2
!= 0);
11645 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
11646 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
11647 assert(child3
!= 0);
11648 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
11649 0, 0, 50, 50, parent
, 0, 0, NULL
);
11650 assert(child4
!= 0);
11652 /* test owner/parent of child2 */
11653 test
= GetParent(child2
);
11654 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
11655 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
11656 test
= GetAncestor(child2
, GA_PARENT
);
11657 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
11658 test
= GetWindow(child2
, GW_OWNER
);
11659 ok(!test
, "wrong owner %p\n", test
);
11661 test
= SetParent(child2
, parent
);
11662 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
11664 /* test owner/parent of the parent */
11665 test
= GetParent(parent
);
11666 ok(!test
, "wrong parent %p\n", test
);
11667 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
11668 test
= GetAncestor(parent
, GA_PARENT
);
11669 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
11670 test
= GetWindow(parent
, GW_OWNER
);
11671 ok(!test
, "wrong owner %p\n", test
);
11673 /* test owner/parent of child1 */
11674 test
= GetParent(child1
);
11675 ok(test
== parent
, "wrong parent %p\n", test
);
11676 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
11677 test
= GetAncestor(child1
, GA_PARENT
);
11678 ok(test
== parent
, "wrong parent %p\n", test
);
11679 test
= GetWindow(child1
, GW_OWNER
);
11680 ok(!test
, "wrong owner %p\n", test
);
11682 /* test owner/parent of child2 */
11683 test
= GetParent(child2
);
11684 ok(test
== parent
, "wrong parent %p\n", test
);
11685 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
11686 test
= GetAncestor(child2
, GA_PARENT
);
11687 ok(test
== parent
, "wrong parent %p\n", test
);
11688 test
= GetWindow(child2
, GW_OWNER
);
11689 ok(!test
, "wrong owner %p\n", test
);
11691 /* test owner/parent of child3 */
11692 test
= GetParent(child3
);
11693 ok(test
== child1
, "wrong parent %p\n", test
);
11694 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
11695 test
= GetAncestor(child3
, GA_PARENT
);
11696 ok(test
== child1
, "wrong parent %p\n", test
);
11697 test
= GetWindow(child3
, GW_OWNER
);
11698 ok(!test
, "wrong owner %p\n", test
);
11700 /* test owner/parent of child4 */
11701 test
= GetParent(child4
);
11702 ok(test
== parent
, "wrong parent %p\n", test
);
11703 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
11704 test
= GetAncestor(child4
, GA_PARENT
);
11705 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
11706 test
= GetWindow(child4
, GW_OWNER
);
11707 ok(test
== parent
, "wrong owner %p\n", test
);
11711 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
11712 parent
, child1
, child2
, child3
, child4
);
11714 SetCapture(child4
);
11715 test
= GetCapture();
11716 ok(test
== child4
, "wrong capture window %p\n", test
);
11718 test_DestroyWindow_flag
= TRUE
;
11719 ret
= DestroyWindow(parent
);
11720 ok( ret
, "DestroyWindow() error %ld\n", GetLastError());
11721 test_DestroyWindow_flag
= FALSE
;
11722 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
11724 ok(!IsWindow(parent
), "parent still exists\n");
11725 ok(!IsWindow(child1
), "child1 still exists\n");
11726 ok(!IsWindow(child2
), "child2 still exists\n");
11727 ok(!IsWindow(child3
), "child3 still exists\n");
11728 ok(!IsWindow(child4
), "child4 still exists\n");
11730 test
= GetCapture();
11731 ok(!test
, "wrong capture window %p\n", test
);
11735 static const struct message WmDispatchPaint
[] = {
11736 { WM_NCPAINT
, sent
},
11737 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11738 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11739 { WM_ERASEBKGND
, sent
},
11743 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11745 if (message
== WM_PAINT
) return 0;
11746 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
11749 static void test_DispatchMessage(void)
11754 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11755 100, 100, 200, 200, 0, 0, 0, NULL
);
11756 ShowWindow( hwnd
, SW_SHOW
);
11757 UpdateWindow( hwnd
);
11760 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
11762 SetRect( &rect
, -5, -5, 5, 5 );
11763 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11765 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11767 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11771 DispatchMessageA( &msg
);
11772 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
11773 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11774 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
11775 if (++count
> 10) break;
11778 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
11780 trace("now without DispatchMessage\n");
11782 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11784 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11786 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11789 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
11791 /* this will send WM_NCCPAINT just like DispatchMessage does */
11792 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
11793 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11794 DeleteObject( hrgn
);
11795 GetClientRect( hwnd
, &rect
);
11796 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
11797 ok( !count
, "Got multiple WM_PAINTs\n" );
11798 if (++count
> 10) break;
11803 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11805 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11807 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11813 hdc
= BeginPaint( hwnd
, NULL
);
11814 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
11815 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
11816 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11817 ok( !count
, "Got multiple WM_PAINTs\n" );
11818 if (++count
> 10) break;
11821 DestroyWindow(hwnd
);
11825 static const struct message WmUser
[] = {
11830 struct sendmsg_info
11838 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
11840 struct sendmsg_info
*info
= arg
;
11841 SetLastError( 0xdeadbeef );
11842 SetEvent( info
->ready
);
11843 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
11844 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
11845 broken(GetLastError() == 0), /* win9x */
11846 "unexpected error %ld\n", GetLastError());
11850 static void wait_for_thread( HANDLE thread
)
11852 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
11855 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11859 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11861 if (message
== WM_USER
) Sleep(200);
11862 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
11865 static void test_SendMessageTimeout(void)
11868 struct sendmsg_info info
;
11872 info
.ready
= CreateEventA( NULL
, 0, 0, NULL
);
11873 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11874 100, 100, 200, 200, 0, 0, 0, NULL
);
11878 info
.timeout
= 1000;
11879 info
.ret
= 0xdeadbeef;
11880 ResetEvent( info
.ready
);
11881 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11882 WaitForSingleObject( info
.ready
, INFINITE
);
11883 wait_for_thread( thread
);
11884 CloseHandle( thread
);
11885 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11886 ok_sequence( WmUser
, "WmUser", FALSE
);
11889 info
.ret
= 0xdeadbeef;
11890 ResetEvent( info
.ready
);
11891 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11892 WaitForSingleObject( info
.ready
, INFINITE
);
11893 Sleep(100); /* SendMessageTimeout should time out here */
11894 wait_for_thread( thread
);
11895 CloseHandle( thread
);
11896 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
11897 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11899 /* 0 means infinite timeout (but not on win9x) */
11901 info
.ret
= 0xdeadbeef;
11902 ResetEvent( info
.ready
);
11903 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11904 WaitForSingleObject( info
.ready
, INFINITE
);
11906 wait_for_thread( thread
);
11907 CloseHandle( thread
);
11908 is_win9x
= !info
.ret
;
11909 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11910 else ok_sequence( WmUser
, "WmUser", FALSE
);
11912 /* timeout is treated as signed despite the prototype (but not on win9x) */
11913 info
.timeout
= 0x7fffffff;
11914 info
.ret
= 0xdeadbeef;
11915 ResetEvent( info
.ready
);
11916 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11917 WaitForSingleObject( info
.ready
, INFINITE
);
11919 wait_for_thread( thread
);
11920 CloseHandle( thread
);
11921 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11922 ok_sequence( WmUser
, "WmUser", FALSE
);
11924 info
.timeout
= 0x80000000;
11925 info
.ret
= 0xdeadbeef;
11926 ResetEvent( info
.ready
);
11927 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11928 WaitForSingleObject( info
.ready
, INFINITE
);
11930 wait_for_thread( thread
);
11931 CloseHandle( thread
);
11934 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11935 ok_sequence( WmUser
, "WmUser", FALSE
);
11939 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
11940 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11943 /* now check for timeout during message processing */
11944 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
11945 info
.timeout
= 100;
11946 info
.ret
= 0xdeadbeef;
11947 ResetEvent( info
.ready
);
11948 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11949 WaitForSingleObject( info
.ready
, INFINITE
);
11950 wait_for_thread( thread
);
11951 CloseHandle( thread
);
11952 /* we should time out but still get the message */
11953 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
11954 ok_sequence( WmUser
, "WmUser", FALSE
);
11956 DestroyWindow( info
.hwnd
);
11957 CloseHandle( info
.ready
);
11961 /****************** edit message test *************************/
11962 #define ID_EDIT 0x1234
11963 static const struct message sl_edit_setfocus
[] =
11965 { HCBT_SETFOCUS
, hook
},
11966 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11967 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11968 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
11969 { WM_SETFOCUS
, sent
|wparam
, 0 },
11970 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11971 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
11972 { WM_CTLCOLOREDIT
, sent
|parent
},
11973 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11974 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
11975 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
11976 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11979 static const struct message sl_edit_invisible
[] =
11981 { HCBT_SETFOCUS
, hook
},
11982 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11983 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11984 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Sent for IME. */
11985 { WM_KILLFOCUS
, sent
|parent
},
11986 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11987 { WM_SETFOCUS
, sent
},
11988 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
11989 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
11990 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11993 static const struct message ml_edit_setfocus
[] =
11995 { HCBT_SETFOCUS
, hook
},
11996 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11997 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11998 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
11999 { WM_SETFOCUS
, sent
|wparam
, 0 },
12000 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
12001 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12002 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12003 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12004 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
12005 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
12008 static const struct message sl_edit_killfocus
[] =
12010 { HCBT_SETFOCUS
, hook
},
12011 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
12012 { WM_KILLFOCUS
, sent
|wparam
, 0 },
12013 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12014 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12015 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
12016 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
12017 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
12020 static const struct message sl_edit_lbutton_dblclk
[] =
12022 { WM_LBUTTONDBLCLK
, sent
},
12023 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
12026 static const struct message sl_edit_lbutton_down
[] =
12028 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
12029 { HCBT_SETFOCUS
, hook
},
12030 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
12031 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
12032 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
12033 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
12034 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
12035 { WM_CTLCOLOREDIT
, sent
|parent
},
12036 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12037 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12038 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
12039 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12040 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
12041 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
12042 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12043 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
12044 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12045 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
12046 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12049 static const struct message ml_edit_lbutton_down
[] =
12051 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
12052 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
12053 { HCBT_SETFOCUS
, hook
},
12054 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
12055 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
12056 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
12057 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
12058 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
12059 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12060 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12061 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12062 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
12065 static const struct message sl_edit_lbutton_up
[] =
12067 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
12068 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12069 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
12070 { WM_CAPTURECHANGED
, sent
|defwinproc
},
12071 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
12074 static const struct message ml_edit_lbutton_up
[] =
12076 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
12077 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
12078 { WM_CAPTURECHANGED
, sent
|defwinproc
},
12082 static WNDPROC old_edit_proc
;
12084 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12086 static LONG defwndproc_counter
= 0;
12088 struct recvd_message msg
;
12090 if (ignore_message( message
)) return 0;
12093 msg
.message
= message
;
12094 msg
.flags
= sent
|wparam
|lparam
;
12095 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
12096 msg
.wParam
= wParam
;
12097 msg
.lParam
= lParam
;
12098 msg
.descr
= "edit";
12101 defwndproc_counter
++;
12102 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
12103 defwndproc_counter
--;
12108 static const struct message edit_wm_ime_composition_seq
[] =
12110 {WM_IME_STARTCOMPOSITION
, sent
},
12111 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
12112 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'W'},
12113 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'i'},
12114 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'n'},
12115 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'e'},
12116 {WM_IME_ENDCOMPOSITION
, sent
},
12117 {WM_CHAR
, sent
| wparam
, 'W'},
12118 {WM_CHAR
, sent
| wparam
, 'i'},
12119 {WM_CHAR
, sent
| wparam
, 'n'},
12120 {WM_CHAR
, sent
| wparam
, 'e'},
12124 static const struct message edit_wm_ime_char_seq
[] =
12126 {WM_IME_CHAR
, sent
| wparam
, '0'},
12127 {WM_CHAR
, sent
| wparam
, '0'},
12131 static const struct message edit_eimes_getcompstratonce_seq
[] =
12133 {WM_IME_STARTCOMPOSITION
, sent
},
12134 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
12135 {WM_IME_ENDCOMPOSITION
, sent
},
12139 static LRESULT CALLBACK
edit_ime_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12141 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
12142 static LONG defwndproc_counter
= 0;
12143 struct recvd_message msg
= {0};
12146 msg
.message
= message
;
12147 msg
.flags
= sent
| wparam
;
12148 if (defwndproc_counter
)
12149 msg
.flags
|= defwinproc
;
12150 msg
.wParam
= wParam
;
12152 if (message
< 0xc000 &&
12153 message
!= WM_GETTEXTLENGTH
&&
12154 message
!= WM_GETTEXT
&&
12155 message
!= WM_GETFONT
&&
12156 message
!= WM_GETICON
&&
12157 message
!= WM_IME_SETCONTEXT
&&
12158 message
!= WM_IME_NOTIFY
&&
12159 message
!= WM_CTLCOLOREDIT
&&
12160 message
!= WM_PAINT
&&
12161 message
!= WM_ERASEBKGND
&&
12162 message
!= WM_NCHITTEST
&&
12163 message
!= WM_SETCURSOR
&&
12164 message
!= WM_MOUSEMOVE
&&
12165 message
!= WM_MOUSEACTIVATE
&&
12166 message
!= WM_KEYUP
&&
12167 (message
< EM_GETSEL
|| message
> EM_GETIMESTATUS
))
12172 defwndproc_counter
++;
12173 if (IsWindowUnicode(hwnd
))
12174 ret
= CallWindowProcW(oldproc
, hwnd
, message
, wParam
, lParam
);
12176 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
12177 defwndproc_counter
--;
12182 static DWORD WINAPI
test_edit_ime_messages(void *unused_arg
)
12191 hwnd
= CreateWindowA(WC_EDITA
, "Test", WS_POPUP
| WS_VISIBLE
, 10, 10, 300, 300, NULL
, NULL
,
12193 ok(hwnd
!= NULL
, "CreateWindowA failed.\n");
12195 /* Test EM_{GET|SET}IMESTATUS */
12196 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12197 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
12199 /* Note that EM_SETIMESTATUS always return 1, which is contrary to what MSDN says about
12200 * returning the previous LPARAM value */
12201 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
12202 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12203 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12204 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
12206 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_CANCELCOMPSTRINFOCUS
);
12207 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12208 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12209 ok(lr
== EIMES_CANCELCOMPSTRINFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
12211 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_COMPLETECOMPSTRKILLFOCUS
);
12212 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12213 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12214 ok(lr
== EIMES_COMPLETECOMPSTRKILLFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
12216 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
12217 | EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
);
12218 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12219 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12220 ok(lr
== (EIMES_GETCOMPSTRATONCE
| EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
),
12221 "Got unexpected lr %#Ix.\n", lr
);
12223 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12224 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12225 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12226 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
12228 /* Invalid EM_{GET|SET}IMESTATUS status types and flags */
12229 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, 0, 0);
12230 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12232 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, 0);
12233 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12235 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, 0, EIMES_GETCOMPSTRATONCE
);
12236 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12237 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12238 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
12240 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, EIMES_GETCOMPSTRATONCE
);
12241 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12242 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12243 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
12245 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0xFFFFFFFF);
12246 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12247 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12248 ok(lr
== 0xFFFF, "Got unexpected lr %#Ix.\n", lr
);
12250 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12251 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12252 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12253 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
12255 /* Test IME messages when EIMES_GETCOMPSTRATONCE is not set */
12256 old_proc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)edit_ime_subclass_proc
);
12257 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)old_proc
);
12259 himc
= ImmGetContext(hwnd
);
12260 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
12261 ok(ret
, "ImmSetCompositionStringA failed.\n");
12263 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
12264 ok(ret
, "ImmNotifyIME failed.\n");
12265 /* Note that the following message loop is necessary to get the WM_CHAR messages because they
12266 * are posted. Same for the later message loops in this function. */
12267 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
12268 ok_sequence(edit_wm_ime_composition_seq
, "WM_IME_COMPOSITION", TRUE
);
12270 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR */
12272 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
12273 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
12274 ok_sequence(edit_wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
12276 /* Test IME messages when EIMES_GETCOMPSTRATONCE is set */
12277 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
12278 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
12279 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
12280 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
12282 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
12283 ok(ret
, "ImmSetCompositionStringA failed.\n");
12285 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
12286 ok(ret
, "ImmNotifyIME failed.\n");
12287 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
12288 ok_sequence(edit_eimes_getcompstratonce_seq
,
12289 "WM_IME_COMPOSITION with EIMES_GETCOMPSTRATONCE", TRUE
);
12291 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR with EIMES_GETCOMPSTRATONCE */
12293 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
12294 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
12295 ok_sequence(edit_wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
12297 ImmReleaseContext(hwnd
, himc
);
12298 DestroyWindow(hwnd
);
12302 static void subclass_edit(void)
12306 if (!GetClassInfoA(0, "edit", &cls
)) assert(0);
12308 old_edit_proc
= cls
.lpfnWndProc
;
12310 cls
.hInstance
= GetModuleHandleA(NULL
);
12311 cls
.lpfnWndProc
= edit_hook_proc
;
12312 cls
.lpszClassName
= "my_edit_class";
12313 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
12314 if (!RegisterClassA(&cls
)) assert(0);
12317 static void test_edit_messages(void)
12324 log_all_parent_messages
++;
12326 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12327 100, 100, 200, 200, 0, 0, 0, NULL
);
12328 ok (parent
!= 0, "Failed to create parent window\n");
12330 /* test single line edit */
12331 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
12332 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
12333 ok(hwnd
!= 0, "Failed to create edit window\n");
12335 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
12336 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", dlg_code
);
12340 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
12342 ShowWindow(hwnd
, SW_SHOW
);
12343 UpdateWindow(hwnd
);
12348 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
12351 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
12357 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
12358 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
12364 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
12365 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
12367 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
12368 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
12370 DestroyWindow(hwnd
);
12372 /* test multiline edit */
12373 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
12374 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
12375 ok(hwnd
!= 0, "Failed to create edit window\n");
12377 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
12378 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
12379 "wrong dlg_code %08lx\n", dlg_code
);
12381 ShowWindow(hwnd
, SW_SHOW
);
12382 UpdateWindow(hwnd
);
12387 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
12390 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
12396 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
12397 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
12403 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
12404 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
12406 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
12407 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
12409 DestroyWindow(hwnd
);
12410 DestroyWindow(parent
);
12412 log_all_parent_messages
--;
12414 /* Test IME messages in another thread because IME is disabled in the current thread */
12415 thread
= CreateThread(NULL
, 0, test_edit_ime_messages
, NULL
, 0, NULL
);
12416 WaitForSingleObject(thread
, INFINITE
);
12417 CloseHandle(thread
);
12420 /**************************** End of Edit test ******************************/
12422 static const struct message WmKeyDownSkippedSeq
[] =
12424 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
12427 static const struct message WmKeyDownWasDownSkippedSeq
[] =
12429 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
12432 static const struct message WmKeyUpSkippedSeq
[] =
12434 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
12437 static const struct message WmUserKeyUpSkippedSeq
[] =
12440 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
12445 #define EV_SENDMSG 1
12448 struct peekmsg_info
12451 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
12454 static DWORD CALLBACK
send_msg_thread_2(void *param
)
12457 struct peekmsg_info
*info
= param
;
12459 trace("thread: looping\n");
12460 SetEvent(info
->hevent
[EV_ACK
]);
12464 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
12468 case WAIT_OBJECT_0
+ EV_STOP
:
12469 trace("thread: exiting\n");
12472 case WAIT_OBJECT_0
+ EV_SENDMSG
:
12473 trace("thread: sending message\n");
12474 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
12475 ok(ret
, "SendNotifyMessageA failed error %lu\n", GetLastError());
12476 SetEvent(info
->hevent
[EV_ACK
]);
12480 trace("unexpected return: %04lx\n", ret
);
12488 static void test_PeekMessage(void)
12492 DWORD tid
, qstatus
;
12493 UINT qs_all_input
= QS_ALLINPUT
;
12494 UINT qs_input
= QS_INPUT
;
12496 struct peekmsg_info info
;
12498 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12499 100, 100, 200, 200, 0, 0, 0, NULL
);
12501 ShowWindow(info
.hwnd
, SW_SHOW
);
12502 UpdateWindow(info
.hwnd
);
12503 SetFocus(info
.hwnd
);
12505 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
12506 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
12507 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
12509 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
12510 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
12515 SetLastError(0xdeadbeef);
12516 qstatus
= GetQueueStatus(qs_all_input
);
12517 if (GetLastError() == ERROR_INVALID_FLAGS
)
12519 trace("QS_RAWINPUT not supported on this platform\n");
12520 qs_all_input
&= ~QS_RAWINPUT
;
12521 qs_input
&= ~QS_RAWINPUT
;
12523 if (qstatus
& QS_POSTMESSAGE
)
12525 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
12526 qstatus
= GetQueueStatus(qs_all_input
);
12528 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
12530 trace("signalling to send message\n");
12531 SetEvent(info
.hevent
[EV_SENDMSG
]);
12532 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
12534 /* pass invalid QS_xxxx flags */
12535 SetLastError(0xdeadbeef);
12536 qstatus
= GetQueueStatus(0xffffffff);
12537 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08lx\n", qstatus
);
12540 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %ld\n", GetLastError());
12541 qstatus
= GetQueueStatus(qs_all_input
);
12543 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
12544 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
),
12545 "wrong qstatus %08lx\n", qstatus
);
12548 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
12550 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12552 ok_sequence(WmUser
, "WmUser", FALSE
);
12554 qstatus
= GetQueueStatus(qs_all_input
);
12555 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
12557 keybd_event('N', 0, 0, 0);
12558 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
12559 qstatus
= GetQueueStatus(qs_all_input
);
12560 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
12562 skip( "queuing key events not supported\n" );
12565 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
12566 /* keybd_event seems to trigger a sent message on NT4 */
12567 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
12568 "wrong qstatus %08lx\n", qstatus
);
12570 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
12571 qstatus
= GetQueueStatus(qs_all_input
);
12572 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
12573 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
12574 "wrong qstatus %08lx\n", qstatus
);
12576 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
12577 qstatus
= GetQueueStatus(qs_all_input
);
12578 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
12579 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
12580 "wrong qstatus %08lx\n", qstatus
);
12582 trace("signalling to send message\n");
12583 SetEvent(info
.hevent
[EV_SENDMSG
]);
12584 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
12586 qstatus
= GetQueueStatus(qs_all_input
);
12587 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
12588 "wrong qstatus %08lx\n", qstatus
);
12591 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
12592 if (ret
&& msg
.message
== WM_CHAR
)
12594 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
12598 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12600 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
12602 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
12605 ok_sequence(WmUser
, "WmUser", FALSE
);
12607 qstatus
= GetQueueStatus(qs_all_input
);
12608 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
12609 "wrong qstatus %08lx\n", qstatus
);
12611 trace("signalling to send message\n");
12612 SetEvent(info
.hevent
[EV_SENDMSG
]);
12613 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
12615 qstatus
= GetQueueStatus(qs_all_input
);
12616 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
12617 "wrong qstatus %08lx\n", qstatus
);
12620 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
12622 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12624 ok_sequence(WmUser
, "WmUser", FALSE
);
12626 qstatus
= GetQueueStatus(qs_all_input
);
12627 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
12628 "wrong qstatus %08lx\n", qstatus
);
12631 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
12632 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12633 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
12634 ret
, msg
.message
, msg
.wParam
);
12635 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12637 qstatus
= GetQueueStatus(qs_all_input
);
12638 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
12639 "wrong qstatus %08lx\n", qstatus
);
12642 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
12644 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12646 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12648 qstatus
= GetQueueStatus(qs_all_input
);
12649 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
12650 "wrong qstatus %08lx\n", qstatus
);
12653 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
12654 ok(ret
&& msg
.message
== WM_PAINT
,
12655 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
12656 DispatchMessageA(&msg
);
12657 ok_sequence(WmPaint
, "WmPaint", FALSE
);
12659 qstatus
= GetQueueStatus(qs_all_input
);
12660 ok(qstatus
== MAKELONG(0, QS_KEY
),
12661 "wrong qstatus %08lx\n", qstatus
);
12664 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
12666 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12668 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12670 qstatus
= GetQueueStatus(qs_all_input
);
12671 ok(qstatus
== MAKELONG(0, QS_KEY
),
12672 "wrong qstatus %08lx\n", qstatus
);
12674 trace("signalling to send message\n");
12675 SetEvent(info
.hevent
[EV_SENDMSG
]);
12676 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
12678 qstatus
= GetQueueStatus(qs_all_input
);
12679 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
12680 "wrong qstatus %08lx\n", qstatus
);
12682 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
12684 qstatus
= GetQueueStatus(qs_all_input
);
12685 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
12686 "wrong qstatus %08lx\n", qstatus
);
12689 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
12690 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12691 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
12692 ret
, msg
.message
, msg
.wParam
);
12693 ok_sequence(WmUser
, "WmUser", FALSE
);
12695 qstatus
= GetQueueStatus(qs_all_input
);
12696 ok(qstatus
== MAKELONG(0, QS_KEY
),
12697 "wrong qstatus %08lx\n", qstatus
);
12700 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
12702 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12704 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12706 qstatus
= GetQueueStatus(qs_all_input
);
12707 ok(qstatus
== MAKELONG(0, QS_KEY
),
12708 "wrong qstatus %08lx\n", qstatus
);
12710 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
12712 qstatus
= GetQueueStatus(qs_all_input
);
12713 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
12714 "wrong qstatus %08lx\n", qstatus
);
12716 trace("signalling to send message\n");
12717 SetEvent(info
.hevent
[EV_SENDMSG
]);
12718 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
12720 qstatus
= GetQueueStatus(qs_all_input
);
12721 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
12722 "wrong qstatus %08lx\n", qstatus
);
12725 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
12727 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12729 ok_sequence(WmUser
, "WmUser", FALSE
);
12731 qstatus
= GetQueueStatus(qs_all_input
);
12732 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
12733 "wrong qstatus %08lx\n", qstatus
);
12736 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
12737 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
12738 else /* workaround for a missing QS_RAWINPUT support */
12739 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
12740 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
12741 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12742 ret
, msg
.message
, msg
.wParam
);
12743 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
12745 qstatus
= GetQueueStatus(qs_all_input
);
12746 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
12747 "wrong qstatus %08lx\n", qstatus
);
12750 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
12751 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
12752 else /* workaround for a missing QS_RAWINPUT support */
12753 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
12754 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
12755 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYUP wParam 'N'\n",
12756 ret
, msg
.message
, msg
.wParam
);
12757 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
12759 qstatus
= GetQueueStatus(qs_all_input
);
12760 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
12761 "wrong qstatus %08lx\n", qstatus
);
12764 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
12766 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12768 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12770 qstatus
= GetQueueStatus(qs_all_input
);
12771 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
12772 "wrong qstatus %08lx\n", qstatus
);
12775 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
12776 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12777 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
12778 ret
, msg
.message
, msg
.wParam
);
12779 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12781 qstatus
= GetQueueStatus(qs_all_input
);
12783 "wrong qstatus %08lx\n", qstatus
);
12786 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
12788 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12790 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12792 qstatus
= GetQueueStatus(qs_all_input
);
12794 "wrong qstatus %08lx\n", qstatus
);
12796 /* test whether presence of the quit flag in the queue affects
12799 PostQuitMessage(0x1234abcd);
12801 qstatus
= GetQueueStatus(qs_all_input
);
12802 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
12803 "wrong qstatus %08lx\n", qstatus
);
12805 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
12807 qstatus
= GetQueueStatus(qs_all_input
);
12808 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
12809 "wrong qstatus %08lx\n", qstatus
);
12812 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
12813 ok(ret
&& msg
.message
== WM_USER
,
12814 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
12815 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12817 qstatus
= GetQueueStatus(qs_all_input
);
12818 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
12819 "wrong qstatus %08lx\n", qstatus
);
12822 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
12823 ok(ret
&& msg
.message
== WM_QUIT
,
12824 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
12825 ok(msg
.wParam
== 0x1234abcd, "got wParam %08Ix instead of 0x1234abcd\n", msg
.wParam
);
12826 ok(msg
.lParam
== 0, "got lParam %08Ix instead of 0\n", msg
.lParam
);
12827 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12829 qstatus
= GetQueueStatus(qs_all_input
);
12831 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
12832 "wrong qstatus %08lx\n", qstatus
);
12836 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
12838 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12840 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
12842 qstatus
= GetQueueStatus(qs_all_input
);
12844 "wrong qstatus %08lx\n", qstatus
);
12846 /* some GetMessage tests */
12848 keybd_event('N', 0, 0, 0);
12849 qstatus
= GetQueueStatus(qs_all_input
);
12850 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
12852 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
12853 qstatus
= GetQueueStatus(qs_all_input
);
12854 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
12858 ret
= GetMessageA( &msg
, 0, 0, 0 );
12859 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12860 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
12861 ret
, msg
.message
, msg
.wParam
);
12862 qstatus
= GetQueueStatus(qs_all_input
);
12863 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
12868 ret
= GetMessageA( &msg
, 0, 0, 0 );
12869 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
12870 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12871 ret
, msg
.message
, msg
.wParam
);
12872 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
12873 qstatus
= GetQueueStatus(qs_all_input
);
12874 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
12877 keybd_event('N', 0, 0, 0);
12878 qstatus
= GetQueueStatus(qs_all_input
);
12879 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
12881 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
12882 qstatus
= GetQueueStatus(qs_all_input
);
12883 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
12885 if (qstatus
& (QS_KEY
<< 16))
12887 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
12888 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
12889 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12890 ret
, msg
.message
, msg
.wParam
);
12891 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
12892 qstatus
= GetQueueStatus(qs_all_input
);
12893 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08lx\n", qstatus
);
12898 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
12899 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12900 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
12901 ret
, msg
.message
, msg
.wParam
);
12902 qstatus
= GetQueueStatus(qs_all_input
);
12903 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
12906 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
12907 qstatus
= GetQueueStatus(qs_all_input
);
12908 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
12910 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
12911 qstatus
= GetQueueStatus(qs_all_input
);
12912 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
12914 trace("signalling to send message\n");
12915 SetEvent(info
.hevent
[EV_SENDMSG
]);
12916 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
12917 qstatus
= GetQueueStatus(qs_all_input
);
12918 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
12919 "wrong qstatus %08lx\n", qstatus
);
12921 if (qstatus
& (QS_KEY
<< 16))
12923 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
12924 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
12925 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12926 ret
, msg
.message
, msg
.wParam
);
12927 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
12928 qstatus
= GetQueueStatus(qs_all_input
);
12929 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08lx\n", qstatus
);
12934 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
12935 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12936 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
12937 ret
, msg
.message
, msg
.wParam
);
12938 qstatus
= GetQueueStatus(qs_all_input
);
12939 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
12942 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
12943 ret
= PeekMessageA(&msg
, (HWND
)-1, 0, 0, PM_NOREMOVE
);
12944 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
12945 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
12946 ret
= GetMessageA(&msg
, (HWND
)-1, 0, 0);
12947 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
12948 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
12950 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
12951 ret
= PeekMessageA(&msg
, (HWND
)1, 0, 0, PM_NOREMOVE
);
12952 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
12953 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
12954 ret
= GetMessageA(&msg
, (HWND
)1, 0, 0);
12955 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
12956 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
12958 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
12959 ret
= PeekMessageA(&msg
, (HWND
)0xffff, 0, 0, PM_NOREMOVE
);
12960 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
12961 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
12962 ret
= GetMessageA(&msg
, (HWND
)0xffff, 0, 0);
12963 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
12964 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
12967 trace("signalling to exit\n");
12968 SetEvent(info
.hevent
[EV_STOP
]);
12970 WaitForSingleObject(hthread
, INFINITE
);
12972 CloseHandle(hthread
);
12973 CloseHandle(info
.hevent
[0]);
12974 CloseHandle(info
.hevent
[1]);
12975 CloseHandle(info
.hevent
[2]);
12977 DestroyWindow(info
.hwnd
);
12980 static void wait_move_event(HWND hwnd
, int x
, int y
)
12983 DWORD timeout
= GetTickCount() + 500;
12987 while ((delay
= timeout
- GetTickCount()) > 0)
12989 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12990 if (ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
) break;
12991 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, delay
, QS_ALLINPUT
);
12992 else Sleep( delay
);
12997 static void test_PeekMessage2(void)
13003 DWORD time1
, time2
, time3
;
13004 int x1
, y1
, x2
, y2
, x3
, y3
;
13007 time1
= time2
= time3
= 0;
13008 x1
= y1
= x2
= y2
= x3
= y3
= 0;
13010 /* Initialise window and make sure it is ready for events */
13011 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
13012 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
13014 trace("Window for test_PeekMessage2 %p\n", hwnd
);
13015 ShowWindow(hwnd
, SW_SHOW
);
13016 UpdateWindow(hwnd
);
13018 GetCursorPos(&pos
);
13019 SetCursorPos(100, 100);
13020 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
13023 /* Do initial mousemove, wait until we can see it
13024 and then do our test peek with PM_NOREMOVE. */
13025 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
13026 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
13028 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
13031 skip( "queuing mouse events not supported\n" );
13036 trace("1st move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
13037 message
= msg
.message
;
13041 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
13044 /* Allow time to advance a bit, and then simulate the user moving their
13045 * mouse around. After that we peek again with PM_NOREMOVE.
13046 * Although the previous mousemove message was never removed, the
13047 * mousemove we now peek should reflect the recent mouse movements
13048 * because the input queue will merge the move events. */
13050 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
13051 wait_move_event(hwnd
, x1
, y1
);
13053 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
13054 ok(ret
, "no message available\n");
13056 trace("2nd move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
13057 message
= msg
.message
;
13061 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
13062 ok(time2
> time1
, "message time not advanced: %lx %lx\n", time1
, time2
);
13063 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
13066 /* Have another go, to drive the point home */
13068 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
13069 wait_move_event(hwnd
, x2
, y2
);
13071 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
13072 ok(ret
, "no message available\n");
13074 trace("3rd move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
13075 message
= msg
.message
;
13079 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
13080 ok(time3
> time2
, "message time not advanced: %lx %lx\n", time2
, time3
);
13081 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
13085 DestroyWindow(hwnd
);
13086 SetCursorPos(pos
.x
, pos
.y
);
13090 static void test_PeekMessage3(void)
13096 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW
,
13097 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
13098 ok(hwnd
!= NULL
, "expected hwnd != NULL\n");
13101 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
13102 * were already seen. */
13104 SetTimer(hwnd
, 1, 100, NULL
);
13105 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
13106 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13107 PostMessageA(hwnd
, WM_USER
, 0, 0);
13108 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
13110 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13111 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13113 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13114 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13116 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
13117 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
13118 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
13120 SetTimer(hwnd
, 1, 100, NULL
);
13121 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
13122 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13123 PostMessageA(hwnd
, WM_USER
, 0, 0);
13124 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
13126 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13127 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
13129 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
13130 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
13131 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
13133 /* It doesn't matter if a message range is specified or not. */
13135 SetTimer(hwnd
, 1, 100, NULL
);
13136 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
13137 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13138 PostMessageA(hwnd
, WM_USER
, 0, 0);
13139 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13141 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13142 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13144 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
13145 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
13146 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
13148 /* But not if the post messages were added before the PeekMessage() call. */
13150 PostMessageA(hwnd
, WM_USER
, 0, 0);
13151 SetTimer(hwnd
, 1, 100, NULL
);
13152 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
13153 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13154 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13155 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
13156 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13157 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13158 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
13159 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
13161 /* More complicated test with multiple messages. */
13163 PostMessageA(hwnd
, WM_USER
, 0, 0);
13164 SetTimer(hwnd
, 1, 100, NULL
);
13165 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
13166 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13167 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
13168 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13169 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
13170 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13172 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13173 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13175 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
13176 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
13177 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
13179 /* Also works for posted messages, but the situation is a bit different,
13180 * because both messages are in the same queue. */
13182 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
13183 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
13184 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13185 PostMessageA(hwnd
, WM_USER
, 0, 0);
13186 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13187 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13188 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13189 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
13190 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
13191 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
13193 PostMessageA(hwnd
, WM_USER
, 0, 0);
13194 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
13195 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
13196 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13197 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13198 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
13199 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13200 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
13201 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
13202 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
13204 DestroyWindow(hwnd
);
13208 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
13210 struct recvd_message msg
;
13212 if (ignore_message( message
)) return 0;
13215 msg
.message
= message
;
13216 msg
.flags
= sent
|wparam
|lparam
;
13219 msg
.descr
= "dialog";
13224 case WM_INITDIALOG
:
13225 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
13226 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
13229 case WM_GETDLGCODE
:
13233 EndDialog(hwnd
, 0);
13240 static const struct message WmQuitDialogSeq
[] = {
13241 { HCBT_CREATEWND
, hook
},
13242 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13243 { WM_SETFONT
, sent
},
13244 { WM_INITDIALOG
, sent
},
13245 { WM_CHANGEUISTATE
, sent
|optional
},
13246 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13247 { HCBT_DESTROYWND
, hook
},
13248 { 0x0090, sent
|optional
}, /* Vista */
13249 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13250 { WM_DESTROY
, sent
},
13251 { WM_NCDESTROY
, sent
},
13255 static const struct message WmStopQuitSeq
[] = {
13256 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
13257 { WM_CLOSE
, posted
},
13258 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
13262 static void test_quit_message(void)
13267 /* test using PostQuitMessage */
13269 PostQuitMessage(0xbeef);
13272 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_QS_SENDMESSAGE
);
13273 ok(!ret
, "got %x message\n", msg
.message
);
13275 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
13276 ok(ret
, "PeekMessage failed with error %ld\n", GetLastError());
13277 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
13278 ok(msg
.wParam
== 0xbeef, "wParam was 0x%Ix instead of 0xbeef\n", msg
.wParam
);
13280 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
13281 ok(ret
, "PostMessage failed with error %ld\n", GetLastError());
13283 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13284 ok(ret
> 0, "GetMessage failed with error %ld\n", GetLastError());
13285 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
13287 /* note: WM_QUIT message received after WM_USER message */
13288 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13289 ok(!ret
, "GetMessage return %d with error %ld instead of FALSE\n", ret
, GetLastError());
13290 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
13291 ok(msg
.wParam
== 0xbeef, "wParam was 0x%Ix instead of 0xbeef\n", msg
.wParam
);
13293 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
13294 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
13296 /* now test with PostThreadMessage - different behaviour! */
13297 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
13299 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
13300 ok(ret
, "PeekMessage failed with error %ld\n", GetLastError());
13301 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
13302 ok(msg
.wParam
== 0xdead, "wParam was 0x%Ix instead of 0xdead\n", msg
.wParam
);
13304 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
13305 ok(ret
, "PostMessage failed with error %ld\n", GetLastError());
13307 /* note: we receive the WM_QUIT message first this time */
13308 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13309 ok(!ret
, "GetMessage return %d with error %ld instead of FALSE\n", ret
, GetLastError());
13310 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
13311 ok(msg
.wParam
== 0xdead, "wParam was 0x%Ix instead of 0xdead\n", msg
.wParam
);
13313 ret
= GetMessageA(&msg
, NULL
, 0, 0);
13314 ok(ret
> 0, "GetMessage failed with error %ld\n", GetLastError());
13315 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
13319 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
13320 ok(ret
== 1, "expected 1, got %d\n", ret
);
13321 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
13322 memset(&msg
, 0xab, sizeof(msg
));
13323 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
13324 ok(ret
, "PeekMessage failed\n");
13325 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
13326 ok(msg
.wParam
== 0x1234, "wParam was 0x%Ix instead of 0x1234\n", msg
.wParam
);
13327 ok(msg
.lParam
== 0, "lParam was 0x%Ix instead of 0\n", msg
.lParam
);
13329 /* Check what happens to a WM_QUIT message posted to a window that gets
13332 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
13333 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
13335 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
13337 struct recvd_message rmsg
;
13338 rmsg
.hwnd
= msg
.hwnd
;
13339 rmsg
.message
= msg
.message
;
13340 rmsg
.flags
= posted
|wparam
|lparam
;
13341 rmsg
.wParam
= msg
.wParam
;
13342 rmsg
.lParam
= msg
.lParam
;
13343 rmsg
.descr
= "stop/quit";
13344 if (msg
.message
== WM_QUIT
)
13345 /* The hwnd can only be checked here */
13346 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
13347 add_message(&rmsg
);
13348 DispatchMessageA(&msg
);
13350 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
13353 static const struct message WmNotifySeq
[] = {
13354 { WM_NOTIFY
, sent
|wparam
|lparam
, 0x1234, 0xdeadbeef },
13358 static void test_notify_message(void)
13364 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
13365 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0, NULL
, NULL
, 0);
13366 ok(hwnd
!= 0, "Failed to create window\n");
13370 ret
= SendNotifyMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
13371 ok(ret
== TRUE
, "SendNotifyMessageA failed with error %lu\n", GetLastError());
13372 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13374 ret
= SendNotifyMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
13375 ok(ret
== TRUE
, "SendNotifyMessageW failed with error %lu\n", GetLastError());
13376 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13378 ret
= SendMessageCallbackA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
13379 ok(ret
== TRUE
, "SendMessageCallbackA failed with error %lu\n", GetLastError());
13380 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13382 ret
= SendMessageCallbackW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
13383 ok(ret
== TRUE
, "SendMessageCallbackW failed with error %lu\n", GetLastError());
13384 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13386 ret
= PostMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
13387 ok(ret
== TRUE
, "PostMessageA failed with error %lu\n", GetLastError());
13389 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13391 ret
= PostMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
13392 ok(ret
== TRUE
, "PostMessageW failed with error %lu\n", GetLastError());
13394 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13396 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
13397 ok(ret
== TRUE
, "PostThreadMessageA failed with error %lu\n", GetLastError());
13398 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
13401 DispatchMessageA(&msg
);
13403 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13405 ret
= PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
13406 ok(ret
== TRUE
, "PostThreadMessageW failed with error %lu\n", GetLastError());
13407 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
13410 DispatchMessageA(&msg
);
13412 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
13414 DestroyWindow(hwnd
);
13417 static const struct message WmMouseHoverSeq
[] = {
13418 { WM_GETMINMAXINFO
, sent
|optional
}, /* sometimes seen on w1064v1809 */
13419 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
13420 { WM_MOUSEACTIVATE
, sent
|optional
},
13421 { WM_TIMER
, sent
|optional
}, /* XP sends it */
13422 { WM_SYSTIMER
, sent
},
13423 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
13427 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
13430 DWORD start_ticks
, end_ticks
;
13432 start_ticks
= GetTickCount();
13433 /* add some deviation (50%) to cover not expected delays */
13434 start_ticks
+= timeout
/ 2;
13438 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
13440 /* Timer proc messages are not dispatched to the window proc,
13441 * and therefore not logged.
13443 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
13445 struct recvd_message s_msg
;
13447 s_msg
.hwnd
= msg
.hwnd
;
13448 s_msg
.message
= msg
.message
;
13449 s_msg
.flags
= sent
|wparam
|lparam
;
13450 s_msg
.wParam
= msg
.wParam
;
13451 s_msg
.lParam
= msg
.lParam
;
13452 s_msg
.descr
= "msg_loop";
13453 add_message(&s_msg
);
13455 DispatchMessageA(&msg
);
13458 end_ticks
= GetTickCount();
13460 /* inject WM_MOUSEMOVE to see how it changes tracking */
13461 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
13463 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
13464 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
13466 inject_mouse_move
= FALSE
;
13468 } while (start_ticks
+ timeout
>= end_ticks
);
13471 static void test_TrackMouseEvent(void)
13473 TRACKMOUSEEVENT tme
;
13476 RECT rc_parent
, rc_child
;
13477 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
13479 #define track_hover(track_hwnd, track_hover_time) \
13480 tme.cbSize = sizeof(tme); \
13481 tme.dwFlags = TME_HOVER; \
13482 tme.hwndTrack = track_hwnd; \
13483 tme.dwHoverTime = track_hover_time; \
13484 SetLastError(0xdeadbeef); \
13485 ret = pTrackMouseEvent(&tme); \
13486 ok(ret, "TrackMouseEvent(TME_HOVER) error %ld\n", GetLastError())
13488 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
13489 tme.cbSize = sizeof(tme); \
13490 tme.dwFlags = TME_QUERY; \
13491 tme.hwndTrack = (HWND)0xdeadbeef; \
13492 tme.dwHoverTime = 0xdeadbeef; \
13493 SetLastError(0xdeadbeef); \
13494 ret = pTrackMouseEvent(&tme); \
13495 ok(ret, "TrackMouseEvent(TME_QUERY) error %ld\n", GetLastError());\
13496 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %lu\n", tme.cbSize); \
13497 ok(tme.dwFlags == (expected_track_flags), \
13498 "wrong tme.dwFlags %08lx, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
13499 ok(tme.hwndTrack == (expected_track_hwnd), \
13500 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
13501 ok(tme.dwHoverTime == (expected_hover_time), \
13502 "wrong tme.dwHoverTime %lu, expected %u\n", tme.dwHoverTime, (expected_hover_time))
13504 #define track_hover_cancel(track_hwnd) \
13505 tme.cbSize = sizeof(tme); \
13506 tme.dwFlags = TME_HOVER | TME_CANCEL; \
13507 tme.hwndTrack = track_hwnd; \
13508 tme.dwHoverTime = 0xdeadbeef; \
13509 SetLastError(0xdeadbeef); \
13510 ret = pTrackMouseEvent(&tme); \
13511 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %ld\n", GetLastError())
13513 default_hover_time
= 0xdeadbeef;
13514 SetLastError(0xdeadbeef);
13515 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
13516 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
13517 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %lu\n", GetLastError());
13518 if (!ret
) default_hover_time
= 400;
13519 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
13521 SetLastError(0xdeadbeef);
13522 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
13523 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
13524 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %lu\n", GetLastError());
13525 if (!ret
) hover_width
= 4;
13526 SetLastError(0xdeadbeef);
13527 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
13528 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
13529 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %lu\n", GetLastError());
13530 if (!ret
) hover_height
= 4;
13531 trace("hover rect is %u x %d\n", hover_width
, hover_height
);
13533 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
13534 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13535 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
13539 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
13540 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
13541 50, 50, 200, 200, hwnd
,
13545 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
13550 tme
.dwFlags
= TME_QUERY
;
13551 tme
.hwndTrack
= (HWND
)0xdeadbeef;
13552 tme
.dwHoverTime
= 0xdeadbeef;
13553 SetLastError(0xdeadbeef);
13554 ret
= pTrackMouseEvent(&tme
);
13555 ok(!ret
, "TrackMouseEvent should fail\n");
13556 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
13557 "not expected error %lu\n", GetLastError());
13559 tme
.cbSize
= sizeof(tme
);
13560 tme
.dwFlags
= TME_HOVER
;
13561 tme
.hwndTrack
= (HWND
)0xdeadbeef;
13562 tme
.dwHoverTime
= 0xdeadbeef;
13563 SetLastError(0xdeadbeef);
13564 ret
= pTrackMouseEvent(&tme
);
13565 ok(!ret
, "TrackMouseEvent should fail\n");
13566 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
13567 "not expected error %lu\n", GetLastError());
13569 tme
.cbSize
= sizeof(tme
);
13570 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
13571 tme
.hwndTrack
= (HWND
)0xdeadbeef;
13572 tme
.dwHoverTime
= 0xdeadbeef;
13573 SetLastError(0xdeadbeef);
13574 ret
= pTrackMouseEvent(&tme
);
13575 ok(!ret
, "TrackMouseEvent should fail\n");
13576 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
13577 "not expected error %lu\n", GetLastError());
13579 GetWindowRect(hwnd
, &rc_parent
);
13580 GetWindowRect(hchild
, &rc_child
);
13581 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
13583 /* Process messages so that the system updates its internal current
13584 * window and hittest, otherwise TrackMouseEvent calls don't have any
13590 track_query(0, NULL
, 0);
13591 track_hover(hchild
, 0);
13592 track_query(0, NULL
, 0);
13597 track_hover(hwnd
, 0);
13598 tme
.cbSize
= sizeof(tme
);
13599 tme
.dwFlags
= TME_QUERY
;
13600 tme
.hwndTrack
= (HWND
)0xdeadbeef;
13601 tme
.dwHoverTime
= 0xdeadbeef;
13602 SetLastError(0xdeadbeef);
13603 ret
= pTrackMouseEvent(&tme
);
13604 ok(ret
, "TrackMouseEvent(TME_QUERY) error %ld\n", GetLastError());
13605 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %lu\n", tme
.cbSize
);
13608 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
13609 DestroyWindow( hwnd
);
13612 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08lx, expected TME_HOVER\n", tme
.dwFlags
);
13613 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
13614 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %lu, expected %u\n",
13615 tme
.dwHoverTime
, default_hover_time
);
13617 pump_msg_loop_timeout(default_hover_time
, FALSE
);
13618 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
13620 track_query(0, NULL
, 0);
13622 track_hover(hwnd
, HOVER_DEFAULT
);
13623 track_query(TME_HOVER
, hwnd
, default_hover_time
);
13625 Sleep(default_hover_time
/ 2);
13626 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
13627 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
13629 track_query(TME_HOVER
, hwnd
, default_hover_time
);
13631 pump_msg_loop_timeout(default_hover_time
, FALSE
);
13632 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
13634 track_query(0, NULL
, 0);
13636 track_hover(hwnd
, HOVER_DEFAULT
);
13637 track_query(TME_HOVER
, hwnd
, default_hover_time
);
13639 pump_msg_loop_timeout(default_hover_time
, TRUE
);
13640 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
13642 track_query(0, NULL
, 0);
13644 track_hover(hwnd
, HOVER_DEFAULT
);
13645 track_query(TME_HOVER
, hwnd
, default_hover_time
);
13646 track_hover_cancel(hwnd
);
13648 DestroyWindow(hwnd
);
13652 #undef track_hover_cancel
13656 static const struct message WmSetWindowRgn
[] = {
13657 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
13658 |SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
, 0 },
13659 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0xf },
13660 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
13661 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13662 { WM_ERASEBKGND
, sent
|optional
},
13663 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
, 0xf },
13664 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13668 static const struct message WmSetWindowRgn_no_redraw
[] = {
13669 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
13670 |SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
, 0 },
13671 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0xf },
13672 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
, 0xf },
13673 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13677 static const struct message WmSetWindowRgn_clear
[] = {
13678 { WM_WINDOWPOSCHANGING
, sent
/*|wparam|lparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
13679 |SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */, 0xf
13680 /* Some newer Windows versions set window coordinates instead of zeros in WINDOWPOS structure */},
13681 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0xf },
13682 { WM_NCPAINT
, sent
|optional
},
13683 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13684 { WM_ERASEBKGND
, sent
|optional
}, /* FIXME: remove optional once Wine is fixed */
13685 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
13686 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
13687 { WM_NCPAINT
, sent
|optional
},
13688 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13689 { WM_ERASEBKGND
, sent
|optional
},
13690 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13691 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13692 { WM_WINDOWPOSCHANGING
, sent
|optional
},
13693 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
13694 { WM_NCPAINT
, sent
|optional
},
13695 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13696 { WM_ERASEBKGND
, sent
|optional
},
13697 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
13698 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
13699 { WM_NCPAINT
, sent
|optional
},
13700 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13701 { WM_ERASEBKGND
, sent
|optional
},
13702 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13703 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not always sent. */
13707 static void test_SetWindowRgn(void)
13710 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
13711 100, 100, 200, 200, 0, 0, 0, NULL
);
13712 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
13714 ShowWindow( hwnd
, SW_SHOW
);
13715 UpdateWindow( hwnd
);
13719 trace("testing SetWindowRgn\n");
13720 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
13721 SetWindowRgn( hwnd
, hrgn
, TRUE
);
13722 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
13724 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
13725 SetWindowRgn( hwnd
, hrgn
, FALSE
);
13726 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
13728 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
13729 SetWindowRgn( hwnd
, hrgn
, TRUE
);
13730 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
13732 SetWindowRgn( hwnd
, 0, TRUE
);
13733 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
13735 DestroyWindow( hwnd
);
13738 /*************************** ShowWindow() test ******************************/
13739 static const struct message WmShowNormal
[] = {
13740 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13741 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13742 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13743 { HCBT_ACTIVATE
, hook
},
13744 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13745 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
13746 { HCBT_SETFOCUS
, hook
},
13747 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
13748 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13749 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
13752 static const struct message WmShow
[] = {
13753 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13754 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13755 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13756 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
13757 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
13758 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
13759 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13762 static const struct message WmShowNoActivate_1
[] = {
13763 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
13764 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13765 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13766 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13767 { WM_MOVE
, sent
|defwinproc
|optional
},
13768 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
13769 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13770 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13773 static const struct message WmShowNoActivate_2
[] = {
13774 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
13775 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
13776 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13777 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13778 { HCBT_ACTIVATE
, hook
|optional
},
13779 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
13780 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13781 { WM_WINDOWPOSCHANGED
, sent
|optional
}, /* Sometimes sent on Win8+. */
13782 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
13783 { HCBT_SETFOCUS
, hook
|optional
},
13784 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Win7 sends this. */
13785 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
13786 { WM_MOVE
, sent
|defwinproc
},
13787 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
13788 { HCBT_SETFOCUS
, hook
|optional
},
13789 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
13790 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
13791 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13792 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
13793 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13794 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13795 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13798 static const struct message WmShowNA_1
[] = {
13799 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13800 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13801 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13802 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13805 static const struct message WmShowNA_2
[] = {
13806 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13807 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13808 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13811 static const struct message WmRestore_1
[] = {
13812 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
13813 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13814 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13815 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13816 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
13817 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
13818 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
13819 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13820 { WM_MOVE
, sent
|defwinproc
},
13821 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
13822 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13823 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13824 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13825 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
13826 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
13829 static const struct message WmRestore_2
[] = {
13830 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13831 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13832 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13833 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
13834 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
13835 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
13836 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13839 static const struct message WmRestore_3
[] = {
13840 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
13841 { WM_GETMINMAXINFO
, sent
},
13842 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13843 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13844 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
13845 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13846 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
13847 { WM_WINDOWPOSCHANGED
, sent
|optional
}, /* Win8+ sometimes sends this. */
13848 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
13849 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
13850 { WM_WINDOWPOSCHANGED
, sent
|optional
},
13851 { WM_MOVE
, sent
|defwinproc
},
13852 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
13853 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
13854 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13855 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13856 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13859 static const struct message WmRestore_4
[] = {
13860 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
13861 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13862 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13863 { WM_MOVE
, sent
|defwinproc
|optional
},
13864 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
13865 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13866 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13869 static const struct message WmRestore_5
[] = {
13870 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
13871 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13872 { HCBT_ACTIVATE
, hook
|optional
},
13873 { HCBT_SETFOCUS
, hook
|optional
},
13874 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13875 { WM_MOVE
, sent
|defwinproc
|optional
},
13876 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
13877 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
13878 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13881 static const struct message WmHide_1
[] = {
13882 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
13883 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
13884 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13885 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
13886 { HCBT_ACTIVATE
, hook
|optional
},
13887 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
13888 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
13891 static const struct message WmHide_2
[] = {
13892 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
13893 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
13894 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13895 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
13896 { HCBT_ACTIVATE
, hook
|optional
},
13899 static const struct message WmHide_3
[] = {
13900 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
13901 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13902 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13903 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13904 { HCBT_SETFOCUS
, hook
|optional
},
13905 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
13908 static const struct message WmShowMinimized_1
[] = {
13909 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
13910 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13911 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13912 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13913 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
13914 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
13915 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13916 { WM_MOVE
, sent
|defwinproc
},
13917 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
13918 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13919 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13920 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13923 static const struct message WmMinimize_1
[] = {
13924 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
13925 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
13926 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
13927 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13928 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13929 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13930 { WM_MOVE
, sent
|defwinproc
},
13931 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
13932 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13933 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13934 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13937 static const struct message WmMinimize_2
[] = {
13938 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
13939 { HCBT_SETFOCUS
, hook
|optional
},
13940 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
13941 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13942 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
13943 { WM_MOVE
, sent
|defwinproc
},
13944 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
13945 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13946 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13947 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13950 static const struct message WmMinimize_3
[] = {
13951 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
13952 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
13953 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13954 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13955 { HCBT_ACTIVATE
, hook
|optional
},
13956 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sometimes sent on Win8/10. */
13957 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13958 { WM_WINDOWPOSCHANGED
, sent
|optional
},
13959 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sometimes sent on Win7. */
13960 { WM_WINDOWPOSCHANGED
, sent
|optional
},
13961 { WM_MOVE
, sent
|defwinproc
},
13962 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
13963 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13964 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
13965 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13968 static const struct message WmShowMinNoActivate
[] = {
13969 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
13970 { WM_WINDOWPOSCHANGING
, sent
},
13971 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
13972 { WM_WINDOWPOSCHANGED
, sent
},
13973 { WM_MOVE
, sent
|defwinproc
|optional
},
13974 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
13977 static const struct message WmMinMax_1
[] = {
13978 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
13981 static const struct message WmMinMax_2
[] = {
13982 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
13983 { WM_GETMINMAXINFO
, sent
|optional
},
13984 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
13985 { HCBT_ACTIVATE
, hook
|optional
},
13986 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13987 { HCBT_SETFOCUS
, hook
|optional
},
13988 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13989 { WM_MOVE
, sent
|defwinproc
|optional
},
13990 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
13991 { HCBT_SETFOCUS
, hook
|optional
},
13994 static const struct message WmMinMax_3
[] = {
13995 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
13996 { HCBT_SETFOCUS
, hook
|optional
},
13997 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13998 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13999 { WM_MOVE
, sent
|defwinproc
|optional
},
14000 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
14003 static const struct message WmMinMax_4
[] = {
14004 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
14007 static const struct message WmShowMaximized_1
[] = {
14008 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
14009 { WM_GETMINMAXINFO
, sent
},
14010 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14011 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14012 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14013 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
14014 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
14015 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
14016 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14017 { WM_MOVE
, sent
|defwinproc
},
14018 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
14019 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14020 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14021 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14022 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
14023 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
14026 static const struct message WmShowMaximized_2
[] = {
14027 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
14028 { WM_GETMINMAXINFO
, sent
},
14029 { WM_WINDOWPOSCHANGING
, sent
|optional
},
14030 { HCBT_ACTIVATE
, hook
|optional
},
14031 { WM_WINDOWPOSCHANGED
, sent
|optional
},
14032 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
14033 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
14034 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
14035 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
14036 { WM_WINDOWPOSCHANGING
, sent
|optional
},
14037 { HCBT_SETFOCUS
, hook
|optional
},
14038 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
14039 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
14040 { WM_MOVE
, sent
|defwinproc
},
14041 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
14042 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14043 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14044 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14045 { HCBT_SETFOCUS
, hook
|optional
},
14046 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
14049 static const struct message WmShowMaximized_3
[] = {
14050 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
14051 { WM_GETMINMAXINFO
, sent
|optional
},
14052 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14053 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
14054 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
14055 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
14056 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
14057 { WM_MOVE
, sent
|defwinproc
|optional
},
14058 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
14059 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14060 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
14064 static void test_ShowWindow(void)
14066 /* ShowWindow commands in random order */
14067 static const struct
14069 INT cmd
; /* ShowWindow command */
14070 LPARAM ret
; /* ShowWindow return value */
14071 DWORD style
; /* window style after the command */
14072 const struct message
*msg
; /* message sequence the command produces */
14073 INT wp_cmd
, wp_flags
; /* window placement after the command */
14074 POINT wp_min
, wp_max
; /* window placement after the command */
14075 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
14078 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
14079 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
14080 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
14081 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
14082 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
14083 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
14084 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
14085 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
14086 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
14087 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14088 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
14089 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14090 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
14091 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14092 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
14093 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14094 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
14095 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14096 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
14097 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14098 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
14099 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14100 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
14101 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14102 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
14103 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14104 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
14105 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14106 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
14107 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14108 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
14109 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14110 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
14111 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14112 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
14113 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14114 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
14115 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14116 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
14117 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14118 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
14119 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14120 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
14121 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
14122 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
14123 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14124 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
14125 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14126 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
14127 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14128 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
14129 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14130 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
14131 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14132 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
14133 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14134 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
14135 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14136 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
14137 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14138 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
14139 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14140 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
14141 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14142 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
14143 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14144 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
14145 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14146 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
14147 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14148 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
14149 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14150 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
14151 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14152 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
14153 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14154 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
14155 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14156 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
14157 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14158 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
14159 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14160 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
14161 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14162 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
14163 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14164 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
14165 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14166 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
14167 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14168 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
14169 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14170 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
14171 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14172 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
14173 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14174 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
14175 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14176 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
14177 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14178 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
14179 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14180 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
14181 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14182 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
14183 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
14184 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
14185 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14186 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
14187 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14188 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
14189 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
14190 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
14191 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
14197 WINDOWPLACEMENT wp
;
14198 RECT win_rc
, work_rc
= {0, 0, 0, 0};
14203 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
14204 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
14209 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
14210 ok(style
== 0, "expected style 0, got %08lx\n", style
);
14215 SetLastError(0xdeadbeef);
14216 hmon
= MonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
14217 ok(hmon
!= 0, "MonitorFromPoint error %lu\n", GetLastError());
14219 mi
.cbSize
= sizeof(mi
);
14220 SetLastError(0xdeadbeef);
14221 ret
= GetMonitorInfoA(hmon
, &mi
);
14222 ok(ret
, "GetMonitorInfo error %lu\n", GetLastError());
14223 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi
.rcMonitor
),
14224 wine_dbgstr_rect(&mi
.rcWork
));
14225 work_rc
= mi
.rcWork
;
14227 GetWindowRect(hwnd
, &win_rc
);
14228 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
14230 wp
.length
= sizeof(wp
);
14231 SetLastError(0xdeadbeaf);
14232 ret
= GetWindowPlacement(hwnd
, &wp
);
14233 ok(ret
, "GetWindowPlacement error %lu\n", GetLastError());
14234 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
14235 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
14236 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
14237 "expected -1,-1 got %ld,%ld\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
14238 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
14239 "expected -1,-1 got %ld,%ld\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
14240 todo_wine_if (work_rc
.left
|| work_rc
.top
) /* FIXME: remove once Wine is fixed */
14241 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n", wine_dbgstr_rect(&win_rc
),
14242 wine_dbgstr_rect(&wp
.rcNormalPosition
));
14244 for (i
= 0; i
< ARRAY_SIZE(sw
); i
++)
14246 static const char * const sw_cmd_name
[13] =
14248 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
14249 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
14250 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
14251 "SW_NORMALNA" /* 0xCC */
14254 INT idx
; /* index into the above array of names */
14256 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
14258 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
14259 trace("%d: sending %s, current window style %08lx\n", i
+1, sw_cmd_name
[idx
], style
);
14260 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
14261 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %Iu, got %Iu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
14262 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
14263 ok(style
== sw
[i
].style
, "%d: expected style %08lx, got %08lx\n", i
+1, sw
[i
].style
, style
);
14265 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
14266 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
14268 wp
.length
= sizeof(wp
);
14269 SetLastError(0xdeadbeaf);
14270 ret
= GetWindowPlacement(hwnd
, &wp
);
14271 ok(ret
, "GetWindowPlacement error %lu\n", GetLastError());
14272 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
14273 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
14275 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
14276 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
14277 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
14279 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
14280 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
14281 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
14285 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
14286 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
14289 todo_wine_if(wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
14290 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
14291 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
14293 if (0) /* FIXME: Wine behaves completely different here */
14294 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n",
14295 wine_dbgstr_rect(&win_rc
), wine_dbgstr_rect(&wp
.rcNormalPosition
));
14297 DestroyWindow(hwnd
);
14301 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14303 struct recvd_message msg
;
14305 if (ignore_message( message
)) return 0;
14308 msg
.message
= message
;
14309 msg
.flags
= sent
|wparam
|lparam
;
14310 msg
.wParam
= wParam
;
14311 msg
.lParam
= lParam
;
14312 msg
.descr
= "dialog";
14315 /* calling DefDlgProc leads to a recursion under XP */
14319 case WM_INITDIALOG
:
14322 case WM_GETDLGCODE
:
14328 static WNDPROC orig_edit_proc
;
14329 static LRESULT WINAPI
dlg_creation_edit_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14331 struct recvd_message msg
;
14333 if (ignore_message( message
)) return 0;
14336 msg
.message
= message
;
14337 msg
.flags
= sent
|wparam
|lparam
;
14340 msg
.descr
= "edit";
14343 return CallWindowProcW(orig_edit_proc
, hwnd
, message
, wp
, lp
);
14346 static INT_PTR WINAPI
test_dlg_proc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14348 struct recvd_message msg
;
14350 if (ignore_message( message
)) return 0;
14353 msg
.message
= message
;
14354 msg
.flags
= sent
|wparam
|lparam
|parent
;
14355 msg
.wParam
= wParam
;
14356 msg
.lParam
= lParam
;
14357 msg
.descr
= "dialog";
14360 if (message
== WM_INITDIALOG
)
14362 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
14363 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
14369 static INT_PTR WINAPI
test_dlg_proc3(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14371 ok( 0, "should not be called since DefDlgProc is not used\n" );
14375 static LRESULT WINAPI
test_dlg_proc4(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14377 struct recvd_message msg
;
14379 if (!ignore_message( message
))
14382 msg
.message
= message
;
14383 msg
.flags
= sent
|wparam
|lparam
|parent
;
14384 msg
.wParam
= wParam
;
14385 msg
.lParam
= lParam
;
14386 msg
.descr
= "dialog";
14389 if (message
== WM_INITDIALOG
)
14391 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
14392 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
14395 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
14398 static const struct message WmDefDlgSetFocus_1
[] = {
14399 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
14400 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
14401 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
14402 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
14403 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
14404 { HCBT_SETFOCUS
, hook
},
14405 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
14406 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
14407 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
14408 { WM_SETFOCUS
, sent
|wparam
, 0 },
14409 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
14410 { WM_CTLCOLOREDIT
, sent
},
14411 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
14412 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
14413 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
14414 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
14415 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
14418 static const struct message WmDefDlgSetFocus_2
[] = {
14419 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
14420 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
14421 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
14422 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
14423 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
14424 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
14425 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
14426 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CARET
, 0 },
14429 /* Creation of a dialog */
14430 static const struct message WmCreateDialogParamSeq_0
[] = {
14431 { HCBT_CREATEWND
, hook
},
14432 { WM_NCCREATE
, sent
},
14433 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
14434 { WM_CREATE
, sent
},
14435 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14436 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
14438 { WM_SETFONT
, sent
},
14439 { WM_INITDIALOG
, sent
},
14440 { WM_CHANGEUISTATE
, sent
|optional
},
14443 /* Creation of a dialog */
14444 static const struct message WmCreateDialogParamSeq_1
[] = {
14445 { HCBT_CREATEWND
, hook
},
14446 { WM_NCCREATE
, sent
},
14447 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
14448 { WM_CREATE
, sent
},
14449 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14450 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
14452 { WM_SETFONT
, sent
},
14453 { WM_INITDIALOG
, sent
},
14454 { WM_GETDLGCODE
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
14455 { HCBT_SETFOCUS
, hook
},
14456 { HCBT_ACTIVATE
, hook
},
14457 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14458 { WM_QUERYNEWPALETTE
, sent
|optional
},
14459 { WM_PALETTEISCHANGING
, sent
|optional
},
14460 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14461 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOREDRAW
},
14462 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
14463 { WM_NCACTIVATE
, sent
},
14464 { WM_ACTIVATE
, sent
|wparam
, 1 },
14465 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
14466 { WM_SETFOCUS
, sent
},
14467 { WM_CHANGEUISTATE
, sent
|optional
},
14470 /* Creation of a dialog */
14471 static const struct message WmCreateDialogParamSeq_2
[] = {
14472 { HCBT_CREATEWND
, hook
},
14473 { WM_NCCREATE
, sent
},
14474 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
14475 { WM_CREATE
, sent
},
14476 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14477 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
14479 { WM_CHANGEUISTATE
, sent
|optional
},
14483 static const struct message WmCreateDialogParamSeq_3
[] = {
14484 { HCBT_CREATEWND
, hook
},
14485 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14486 { WM_SETFONT
, sent
|parent
},
14487 { WM_INITDIALOG
, sent
|parent
},
14488 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
14489 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
14490 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
14491 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
14492 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
14493 { HCBT_ACTIVATE
, hook
},
14494 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14495 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
14496 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14497 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14498 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14499 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14500 { WM_NCCALCSIZE
, sent
|parent
|optional
, 0 },
14501 { WM_MOVE
, sent
|parent
|optional
},
14502 { WM_SIZE
, sent
|parent
|optional
},
14503 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
14504 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
14505 { WM_NCACTIVATE
, sent
|parent
},
14506 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
14507 { WM_SETFOCUS
, sent
},
14508 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
14509 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
14510 { WM_USER
, sent
|parent
},
14511 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
14515 static const struct message WmCreateDialogParamSeq_4
[] = {
14516 { HCBT_CREATEWND
, hook
},
14517 { WM_NCCREATE
, sent
|parent
},
14518 { WM_NCCALCSIZE
, sent
|parent
|wparam
, 0 },
14519 { WM_CREATE
, sent
|parent
},
14520 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14521 { WM_SIZE
, sent
|parent
|wparam
, SIZE_RESTORED
},
14522 { WM_MOVE
, sent
|parent
},
14523 { WM_SETFONT
, sent
|parent
},
14524 { WM_INITDIALOG
, sent
|parent
},
14525 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
14526 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
14527 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
14528 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
14529 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
14530 { HCBT_ACTIVATE
, hook
},
14531 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14532 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
14533 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14534 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14535 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14536 { WM_NCCALCSIZE
, sent
|parent
|optional
, 0 },
14537 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
14538 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
14539 { WM_NCACTIVATE
, sent
|parent
},
14540 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
14541 { HCBT_SETFOCUS
, hook
},
14542 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14543 { WM_SETFOCUS
, sent
|parent
},
14544 { WM_KILLFOCUS
, sent
|parent
},
14545 { WM_SETFOCUS
, sent
},
14546 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
14547 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
14548 { WM_USER
, sent
|parent
},
14549 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
14550 { WM_UPDATEUISTATE
, sent
|parent
|optional
},
14551 { WM_UPDATEUISTATE
, sent
|optional
},
14555 static void test_dialog_messages(void)
14558 HWND hdlg
, hedit1
, hedit2
, hfocus
, parent
, child
, child2
;
14561 #define set_selection(hctl, start, end) \
14562 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
14563 ok(ret == 1, "EM_SETSEL returned %Id\n", ret);
14565 #define check_selection(hctl, start, end) \
14566 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
14567 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
14571 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
14572 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
14573 0, 0, 100, 100, 0, 0, 0, NULL
);
14574 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
14576 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
14577 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
14578 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
14579 ok(hedit1
!= 0, "Failed to create edit control\n");
14580 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
14581 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
14582 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
14583 ok(hedit2
!= 0, "Failed to create edit control\n");
14585 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
14586 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
14588 hfocus
= GetFocus();
14589 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
14592 hfocus
= GetFocus();
14593 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
14595 check_selection(hedit1
, 0, 0);
14596 check_selection(hedit2
, 0, 0);
14598 set_selection(hedit2
, 0, -1);
14599 check_selection(hedit2
, 0, 3);
14602 hfocus
= GetFocus();
14603 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
14606 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
14607 ok(ret
== 0, "WM_SETFOCUS returned %Id\n", ret
);
14608 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
14610 hfocus
= GetFocus();
14611 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
14613 check_selection(hedit1
, 0, 5);
14614 check_selection(hedit2
, 0, 3);
14617 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
14618 ok(ret
== 0, "WM_SETFOCUS returned %Id\n", ret
);
14619 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
14621 hfocus
= GetFocus();
14622 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
14624 check_selection(hedit1
, 0, 5);
14625 check_selection(hedit2
, 0, 3);
14627 EndDialog(hdlg
, 0);
14628 DestroyWindow(hedit1
);
14629 DestroyWindow(hedit2
);
14630 DestroyWindow(hdlg
);
14633 #undef set_selection
14634 #undef check_selection
14636 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
14637 cls
.lpszClassName
= "MyDialogClass";
14638 cls
.hInstance
= GetModuleHandleA(NULL
);
14639 /* need a cast since a dlgproc is used as a wndproc */
14640 cls
.lpfnWndProc
= (WNDPROC
)test_dlg_proc
;
14641 if (!RegisterClassA(&cls
)) assert(0);
14645 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
14646 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14647 ok_sequence(WmCreateDialogParamSeq_0
, "CreateDialogParam_0", FALSE
);
14648 hfocus
= GetFocus();
14649 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
14650 EndDialog(hdlg
, 0);
14651 DestroyWindow(hdlg
);
14656 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 1);
14657 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14658 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
14659 hfocus
= GetFocus();
14660 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
14661 EndDialog(hdlg
, 0);
14662 DestroyWindow(hdlg
);
14665 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
14666 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14667 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
14668 EndDialog(hdlg
, 0);
14669 DestroyWindow(hdlg
);
14672 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2
, 0);
14673 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14674 ok_sequence(WmCreateDialogParamSeq_3
, "CreateDialogParam_3", TRUE
);
14675 EndDialog(hdlg
, 0);
14676 DestroyWindow(hdlg
);
14679 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
14680 cls
.lpfnWndProc
= test_dlg_proc4
;
14681 ok( RegisterClassA(&cls
), "failed to register class again\n" );
14682 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3
, 0);
14683 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14684 ok_sequence(WmCreateDialogParamSeq_4
, "CreateDialogParam_4", TRUE
);
14685 EndDialog(hdlg
, 0);
14686 DestroyWindow(hdlg
);
14689 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
14691 parent
= CreateWindowExA(0, "TestParentClass", "Test parent",
14692 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14693 100, 100, 200, 200, 0, 0, 0, NULL
);
14694 ok (parent
!= 0, "Failed to create parent window\n");
14696 /* This child has no parent set. We will later call SetParent on it,
14697 * so that it will have a parent set, but no WS_CHILD style. */
14698 child
= CreateWindowExA(0, "TestWindowClass", "Test child",
14699 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14700 100, 100, 200, 200, 0, 0, 0, NULL
);
14701 ok (child
!= 0, "Failed to create child window\n");
14703 /* This is a regular child window. When used as an owner, the other
14704 * child window will be used. */
14705 child2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2",
14706 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CHILD
,
14707 100, 100, 200, 200, child
, 0, 0, NULL
);
14708 ok (child2
!= 0, "Failed to create child window\n");
14710 SetParent(child
, parent
);
14714 DialogBoxA( 0, "TEST_DIALOG", child2
, TestModalDlgProc2
);
14715 ok_sequence(WmModalDialogSeq_2
, "ModalDialog2", TRUE
);
14717 DestroyWindow(child2
);
14718 DestroyWindow(child
);
14719 DestroyWindow(parent
);
14723 static void test_enddialog_seq(HWND dialog
, HWND owner
)
14725 const struct message seq
[] = {
14726 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14727 { WM_ENABLE
, sent
},
14728 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14729 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
14730 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
14731 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
14732 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14733 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */
14734 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14735 { WM_QUERYNEWPALETTE
, sent
|optional
},
14736 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
14737 { WM_GETTEXT
, sent
|optional
|defwinproc
},
14738 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
14739 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
14740 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
14741 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14742 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, (WPARAM
)dialog
},
14747 EndDialog(dialog
, 0);
14748 ok_sequence(seq
, "EndDialog", FALSE
);
14751 static void test_enddialog_seq2(HWND dialog
, HWND owner
)
14753 const struct message seq
[] = {
14754 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14755 { WM_ENABLE
, parent
|sent
},
14756 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14757 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
14758 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
14759 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
14760 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14761 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14762 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14763 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
14764 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
14765 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14766 { WM_SETFOCUS
, sent
|parent
|defwinproc
|wparam
, (WPARAM
)dialog
},
14771 EndDialog(dialog
, 0);
14772 ok_sequence(seq
, "EndDialog2", FALSE
);
14775 static void test_EndDialog(void)
14777 HWND hparent
, hother
, hactive
, hdlg
, hchild
;
14780 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
14781 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
14782 100, 100, 200, 200, 0, 0, 0, NULL
);
14783 ok (hparent
!= 0, "Failed to create parent window\n");
14785 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
14786 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14787 200, 100, 200, 200, 0, 0, 0, NULL
);
14788 ok (hother
!= 0, "Failed to create parent window\n");
14790 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
14791 cls
.lpszClassName
= "MyDialogClass";
14792 cls
.hInstance
= GetModuleHandleA(NULL
);
14793 cls
.lpfnWndProc
= (WNDPROC
)test_dlg_proc
;
14794 if (!RegisterClassA(&cls
)) assert(0);
14797 SetForegroundWindow(hother
);
14798 hactive
= GetForegroundWindow();
14799 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
14801 /* create a dialog where the parent is disabled, this parent should be
14802 * enabled and receive focus when dialog exits */
14803 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
14804 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14805 SetForegroundWindow(hdlg
);
14806 hactive
= GetForegroundWindow();
14807 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
14808 EndDialog(hdlg
, 0);
14809 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
14810 hactive
= GetForegroundWindow();
14811 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
14812 DestroyWindow(hdlg
);
14815 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */
14816 EnableWindow(hparent
, FALSE
);
14817 hdlg
= CreateWindowExA(0, "TestDialogClass", NULL
,
14818 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
14819 0, 0, 100, 100, hparent
, 0, 0, NULL
);
14820 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14822 SetForegroundWindow(hother
);
14824 hactive
= GetForegroundWindow();
14825 ok(hactive
== hother
, "Wrong foreground (%p != %p)\n", hactive
, hother
);
14826 hactive
= GetActiveWindow();
14827 ok(hactive
== hother
, "Wrong active window (%p != %p)\n", hactive
, hother
);
14828 EndDialog(hdlg
, 0);
14829 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
14830 hactive
= GetForegroundWindow();
14831 ok(hother
== hactive
, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
14832 DestroyWindow(hdlg
);
14835 DestroyWindow( hparent
);
14837 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
14838 WS_POPUP
| WS_VISIBLE
| WS_DISABLED
,
14839 100, 100, 200, 200, 0, 0, 0, NULL
);
14840 ok (hparent
!= 0, "Failed to create parent window\n");
14842 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
14843 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
14844 0, 0, 0, 0, 0, 0, 0, NULL
);
14845 ok (hchild
!= 0, "Failed to create child window\n");
14847 SetParent(hchild
, hparent
);
14850 SetForegroundWindow(hother
);
14851 hactive
= GetForegroundWindow();
14852 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
14854 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
14855 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14857 SetForegroundWindow(hdlg
);
14858 test_enddialog_seq(hdlg
, hchild
);
14860 hactive
= GetForegroundWindow();
14861 ok(hactive
== hchild
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
14863 DestroyWindow(hdlg
);
14865 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */
14866 SetWindowLongW(hchild
, GWL_STYLE
, GetWindowLongW(hchild
, GWL_STYLE
) | WS_CHILD
);
14868 SetForegroundWindow(hother
);
14869 hactive
= GetForegroundWindow();
14870 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
14872 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
14873 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
14875 SetForegroundWindow(hdlg
);
14876 test_enddialog_seq2(hdlg
, hparent
);
14878 hactive
= GetForegroundWindow();
14879 ok(hactive
== hparent
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
14880 DestroyWindow(hdlg
);
14881 DestroyWindow(hchild
);
14882 DestroyWindow(hparent
);
14883 DestroyWindow(hother
);
14886 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
14889 static void test_nullCallback(void)
14893 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
14894 100, 100, 200, 200, 0, 0, 0, NULL
);
14895 ok (hwnd
!= 0, "Failed to create overlapped window\n");
14897 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
14899 DestroyWindow(hwnd
);
14902 /* SetActiveWindow( 0 ) hwnd visible */
14903 static const struct message SetActiveWindowSeq0
[] =
14905 { HCBT_ACTIVATE
, hook
|optional
},
14906 { WM_NCACTIVATE
, sent
|wparam
, 0 },
14907 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14908 { WM_ACTIVATE
, sent
|wparam
, 0 },
14909 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14910 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
14911 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
14912 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
14913 { WM_KILLFOCUS
, sent
|optional
},
14914 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
14915 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14916 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
14917 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14918 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
14919 { HCBT_SETFOCUS
, hook
|optional
},
14920 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
14921 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
14922 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
14923 { WM_IME_SETCONTEXT
, sent
|optional
},
14924 { WM_IME_SETCONTEXT
, sent
|optional
},
14925 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
14926 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
14927 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
14928 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
14929 { WM_GETTEXT
, sent
|optional
},
14932 /* SetActiveWindow( hwnd ) hwnd visible */
14933 static const struct message SetActiveWindowSeq1
[] =
14935 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
14938 /* SetActiveWindow( popup ) hwnd visible, popup visible */
14939 static const struct message SetActiveWindowSeq2
[] =
14941 { HCBT_ACTIVATE
, hook
},
14942 { WM_NCACTIVATE
, sent
|wparam
, 0 },
14943 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14944 { WM_ACTIVATE
, sent
|wparam
, 0 },
14945 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14946 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
14947 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
14948 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
14949 { WM_NCPAINT
, sent
|optional
},
14950 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14951 { WM_ERASEBKGND
, sent
|optional
},
14952 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14953 { WM_NCACTIVATE
, sent
|wparam
, 1 },
14954 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14955 { WM_ACTIVATE
, sent
|wparam
, 1 },
14956 { HCBT_SETFOCUS
, hook
},
14957 { WM_KILLFOCUS
, sent
|defwinproc
},
14958 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
14959 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
14960 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
14961 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
14962 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14963 { WM_SETFOCUS
, sent
|defwinproc
},
14964 { WM_GETTEXT
, sent
|optional
},
14968 /* SetActiveWindow( hwnd ) hwnd not visible */
14969 static const struct message SetActiveWindowSeq3
[] =
14971 { HCBT_ACTIVATE
, hook
},
14972 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14973 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
14974 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
14975 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
14976 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14977 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14978 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
14979 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
14980 { WM_NCACTIVATE
, sent
|wparam
, 1 },
14981 { WM_ACTIVATE
, sent
|wparam
, 1 },
14982 { HCBT_SETFOCUS
, hook
},
14983 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
14984 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
14985 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14986 { WM_SETFOCUS
, sent
|defwinproc
},
14989 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
14990 static const struct message SetActiveWindowSeq4
[] =
14992 { HCBT_ACTIVATE
, hook
},
14993 { WM_NCACTIVATE
, sent
|wparam
, 0 },
14994 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14995 { WM_ACTIVATE
, sent
|wparam
, 0 },
14996 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
14997 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
14998 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
14999 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
15000 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15001 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15002 { WM_NCACTIVATE
, sent
|wparam
, 1 },
15003 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15004 { WM_ACTIVATE
, sent
|wparam
, 1 },
15005 { HCBT_SETFOCUS
, hook
},
15006 { WM_KILLFOCUS
, sent
|defwinproc
},
15007 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
15008 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
15009 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
15010 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
15011 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15012 { WM_SETFOCUS
, sent
|defwinproc
},
15017 static void test_SetActiveWindow(void)
15019 HWND hwnd
, popup
, ret
;
15021 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
15022 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15023 100, 100, 200, 200, 0, 0, 0, NULL
);
15025 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
15026 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
15027 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
15029 ok(hwnd
!= 0, "Failed to create overlapped window\n");
15030 ok(popup
!= 0, "Failed to create popup window\n");
15031 SetForegroundWindow( popup
);
15034 trace("SetActiveWindow(0)\n");
15035 ret
= SetActiveWindow(0);
15036 ok( ret
== popup
|| broken(ret
== 0) /* w1064v1809 */, "Failed to SetActiveWindow(0), ret:%p\n", ret
);
15037 if (ret
== popup
) ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
15040 trace("SetActiveWindow(hwnd), hwnd visible\n");
15041 ret
= SetActiveWindow(hwnd
);
15042 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
15045 trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
15046 ret
= SetActiveWindow(popup
);
15047 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
15048 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
15051 ShowWindow(hwnd
, SW_HIDE
);
15052 ShowWindow(popup
, SW_HIDE
);
15055 trace("SetActiveWindow(hwnd), hwnd not visible\n");
15056 ret
= SetActiveWindow(hwnd
);
15057 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
15058 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
15061 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
15062 ret
= SetActiveWindow(popup
);
15063 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
15064 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
15069 DestroyWindow(hwnd
);
15072 static const struct message SetForegroundWindowSeq
[] =
15074 { WM_NCACTIVATE
, sent
|wparam
, 0 },
15075 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15076 { WM_ACTIVATE
, sent
|wparam
, 0 },
15077 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
15078 { WM_KILLFOCUS
, sent
},
15079 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
15080 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
15084 static void test_SetForegroundWindow(void)
15088 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
15089 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15090 100, 100, 200, 200, 0, 0, 0, NULL
);
15091 ok (hwnd
!= 0, "Failed to create overlapped window\n");
15092 SetForegroundWindow( hwnd
);
15095 trace("SetForegroundWindow( 0 )\n");
15096 SetForegroundWindow( 0 );
15097 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
15098 trace("SetForegroundWindow( GetDesktopWindow() )\n");
15099 SetForegroundWindow( GetDesktopWindow() );
15100 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
15101 "foreground top level window", FALSE
);
15104 DestroyWindow(hwnd
);
15107 static DWORD
get_input_codepage( void )
15111 HKL hkl
= GetKeyboardLayout( 0 );
15113 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
,
15114 (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
15115 if (!ret
) cp
= CP_ACP
;
15119 static void test_dbcs_wm_char(void)
15122 WCHAR wch
, bad_wch
;
15130 struct message wmCharSeq
[2];
15132 DWORD cp
= get_input_codepage();
15134 if (!pGetCPInfoExA
)
15136 win_skip("GetCPInfoExA is not available\n");
15140 pGetCPInfoExA( cp
, 0, &cpinfo
);
15141 if (cpinfo
.MaxCharSize
!= 2)
15143 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
15147 dbch
[0] = dbch
[1] = 0;
15149 bad_wch
= cpinfo
.UnicodeDefaultChar
;
15150 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
15151 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
15152 for (k
= 128; k
<= 255; k
++)
15158 if (MultiByteToWideChar( cp
, 0, str
, 2, wstr
, 2 ) == 1 &&
15159 WideCharToMultiByte( cp
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
15160 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
15161 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
15172 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
15175 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
15176 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
15178 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
15179 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
15180 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
15181 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
15182 ok (hwnd
!= 0, "Failed to create overlapped window\n");
15183 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
15187 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
15188 wmCharSeq
[0].message
= WM_CHAR
;
15189 wmCharSeq
[0].flags
= sent
|wparam
;
15190 wmCharSeq
[0].wParam
= wch
;
15192 /* posted message */
15193 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
15194 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15195 ok( !ret
, "got message %x\n", msg
.message
);
15196 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15197 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15198 ok( ret
, "no message\n" );
15199 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15200 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
15201 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15202 ok( !ret
, "got message %x\n", msg
.message
);
15204 /* posted thread message */
15205 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
15206 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15207 ok( !ret
, "got message %x\n", msg
.message
);
15208 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15209 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15210 ok( ret
, "no message\n" );
15211 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15212 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
15213 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15214 ok( !ret
, "got message %x\n", msg
.message
);
15218 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
15219 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15220 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15221 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15222 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15223 ok( !ret
, "got message %x\n", msg
.message
);
15225 /* sent message with timeout */
15227 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
15228 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15229 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
15230 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15231 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15232 ok( !ret
, "got message %x\n", msg
.message
);
15234 /* sent message with timeout and callback */
15236 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
15237 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15238 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
15239 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15240 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15241 ok( !ret
, "got message %x\n", msg
.message
);
15243 /* sent message with callback */
15245 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
15246 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15247 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
15248 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15249 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15250 ok( !ret
, "got message %x\n", msg
.message
);
15252 /* direct window proc call */
15254 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
15255 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15256 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
15257 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15259 /* dispatch message */
15261 msg
.message
= WM_CHAR
;
15262 msg
.wParam
= dbch
[0];
15264 DispatchMessageA( &msg
);
15265 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15266 msg
.wParam
= dbch
[1];
15267 DispatchMessageA( &msg
);
15268 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15270 /* window handle is irrelevant */
15272 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
15273 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15274 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15275 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15276 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15277 ok( !ret
, "got message %x\n", msg
.message
);
15279 /* interleaved post and send */
15281 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
15282 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
15283 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15284 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15285 ok( !ret
, "got message %x\n", msg
.message
);
15286 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15287 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15288 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15289 ok( ret
, "no message\n" );
15290 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15291 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
15292 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15293 ok( !ret
, "got message %x\n", msg
.message
);
15294 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15295 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15296 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15297 ok( !ret
, "got message %x\n", msg
.message
);
15299 /* interleaved sent message and winproc */
15301 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
15302 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
15303 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15304 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15305 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15306 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
15307 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15309 /* interleaved winproc and dispatch */
15311 msg
.message
= WM_CHAR
;
15312 msg
.wParam
= dbch
[0];
15314 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
15315 DispatchMessageA( &msg
);
15316 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15317 msg
.wParam
= dbch
[1];
15318 DispatchMessageA( &msg
);
15319 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15320 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
15321 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15323 /* interleaved sends */
15325 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
15326 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
15327 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
15328 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
15329 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15330 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
15331 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15335 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
15336 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
15337 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15338 ok( !ret
, "got message %x\n", msg
.message
);
15340 /* other char messages are not magic */
15341 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
15342 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15343 ok( ret
, "no message\n" );
15344 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
15345 ok( msg
.wParam
== bad_wch
, "bad wparam %Ix/%x\n", msg
.wParam
, bad_wch
);
15346 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15347 ok( !ret
, "got message %x\n", msg
.message
);
15348 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
15349 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15350 ok( ret
, "no message\n" );
15351 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
15352 ok( msg
.wParam
== bad_wch
, "bad wparam %Ix/%x\n", msg
.wParam
, bad_wch
);
15353 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15354 ok( !ret
, "got message %x\n", msg
.message
);
15356 /* test retrieving messages */
15358 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
15359 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15360 ok( ret
, "no message\n" );
15361 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15362 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15363 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15364 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15365 ok( ret
, "no message\n" );
15366 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15367 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15368 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15369 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15370 ok( !ret
, "got message %x\n", msg
.message
);
15372 /* message filters */
15373 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
15374 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15375 ok( ret
, "no message\n" );
15376 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15377 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15378 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15379 /* message id is filtered, hwnd is not */
15380 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
15381 ok( !ret
, "no message\n" );
15382 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
15383 ok( ret
, "no message\n" );
15384 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15385 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15386 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15387 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15388 ok( !ret
, "got message %x\n", msg
.message
);
15390 /* mixing GetMessage and PostMessage */
15391 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
15392 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
15393 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15394 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15395 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15396 ok( msg
.lParam
== 0xbeef, "bad lparam %Ix\n", msg
.lParam
);
15399 ok( time
- GetTickCount() <= 100, "bad time %lx\n", msg
.time
);
15400 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
15401 ok( ret
, "no message\n" );
15402 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15403 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15404 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15405 ok( msg
.lParam
== 0xbeef, "bad lparam %Ix\n", msg
.lParam
);
15406 ok( msg
.time
== time
, "bad time %lx/%lx\n", msg
.time
, time
);
15407 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
);
15408 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15409 ok( !ret
, "got message %x\n", msg
.message
);
15411 /* without PM_REMOVE */
15412 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
15413 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15414 ok( ret
, "no message\n" );
15415 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15416 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15417 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15418 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
15419 ok( ret
, "no message\n" );
15420 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15421 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15422 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15423 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15424 ok( ret
, "no message\n" );
15425 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15426 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15427 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15428 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
15429 ok( ret
, "no message\n" );
15430 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15431 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15432 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
15433 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
15434 ok( !ret
, "got message %x\n", msg
.message
);
15436 DestroyWindow(hwnd
);
15437 DestroyWindow(hwnd2
);
15440 static void test_unicode_wm_char(void)
15444 struct message seq
[2];
15445 HKL hkl_orig
, hkl_greek
;
15447 LCID thread_locale
;
15449 hkl_orig
= GetKeyboardLayout( 0 );
15450 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
15453 skip( "Default codepage %ld\n", cp
);
15457 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
15458 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
15460 skip( "Unable to load Greek keyboard layout\n" );
15464 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
15465 100, 100, 200, 200, 0, 0, 0, NULL
);
15468 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
15470 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
15472 if (!ignore_message( msg
.message
)) break;
15475 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15476 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15477 ok( msg
.wParam
== 0x3b1, "bad wparam %Ix\n", msg
.wParam
);
15478 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
15480 DispatchMessageW( &msg
);
15482 memset( seq
, 0, sizeof(seq
) );
15483 seq
[0].message
= WM_CHAR
;
15484 seq
[0].flags
= sent
|wparam
;
15485 seq
[0].wParam
= 0x3b1;
15487 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
15491 /* greek alpha -> 'a' in cp1252 */
15492 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
15494 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
15495 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15496 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15497 ok( msg
.wParam
== 0x61, "bad wparam %Ix\n", msg
.wParam
);
15498 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
15500 DispatchMessageA( &msg
);
15502 seq
[0].wParam
= 0x61;
15503 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
15505 thread_locale
= GetThreadLocale();
15506 ActivateKeyboardLayout( hkl_greek
, 0 );
15507 ok( GetThreadLocale() == thread_locale
, "locale changed from %08lx to %08lx\n",
15508 thread_locale
, GetThreadLocale() );
15512 /* greek alpha -> 0xe1 in cp1253 */
15513 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
15515 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
15516 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
15517 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
15518 ok( msg
.wParam
== 0xe1, "bad wparam %Ix\n", msg
.wParam
);
15519 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
15521 DispatchMessageA( &msg
);
15523 seq
[0].wParam
= 0x3b1;
15524 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
15526 DestroyWindow( hwnd
);
15527 ActivateKeyboardLayout( hkl_orig
, 0 );
15528 UnloadKeyboardLayout( hkl_greek
);
15531 #define ID_LISTBOX 0x000f
15533 static const struct message wm_lb_setcursel_0
[] =
15535 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
15536 { WM_CTLCOLORLISTBOX
, sent
|parent
},
15537 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
15538 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15539 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15542 static const struct message wm_lb_setcursel_1
[] =
15544 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
15545 { WM_CTLCOLORLISTBOX
, sent
|parent
},
15546 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
15547 { WM_CTLCOLORLISTBOX
, sent
|parent
},
15548 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
15549 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
15550 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
15553 static const struct message wm_lb_setcursel_2
[] =
15555 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
15556 { WM_CTLCOLORLISTBOX
, sent
|parent
},
15557 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
15558 { WM_CTLCOLORLISTBOX
, sent
|parent
},
15559 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
15560 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
15561 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
15564 static const struct message wm_lb_click_0
[] =
15566 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
15567 { HCBT_SETFOCUS
, hook
},
15568 { WM_KILLFOCUS
, sent
|parent
},
15569 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
15570 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
15571 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15572 { WM_SETFOCUS
, sent
|defwinproc
},
15574 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
15575 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
15576 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
15577 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
15578 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15580 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
15581 { WM_CTLCOLORLISTBOX
, sent
|parent
},
15582 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
15583 { WM_CTLCOLORLISTBOX
, sent
|parent
},
15584 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
15585 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
15587 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15588 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15590 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
15591 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15592 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
15593 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
15596 static const struct message wm_lb_deletestring
[] =
15598 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
15599 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15600 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
15601 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
15602 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
15605 static const struct message wm_lb_deletestring_reset
[] =
15607 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
15608 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15609 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
15610 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
15611 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
15612 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
15615 static const struct message wm_lb_addstring
[] =
15617 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
15618 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15619 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
15620 /* Child ID changes each test, don't test lparam. */
15621 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15622 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
15623 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15626 static const struct message wm_lb_addstring_ownerdraw
[] =
15628 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
15629 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
15630 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15631 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
15632 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
15633 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
15634 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
15635 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
15636 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
15639 static const struct message wm_lb_addstring_sort_ownerdraw
[] =
15641 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
15642 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
15643 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15644 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
15645 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ee },
15646 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
15647 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 2 },
15648 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
15649 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ef },
15650 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ee, 0xf30604ef },
15651 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
15652 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 3 },
15656 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
15658 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
15660 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
15662 static LONG defwndproc_counter
= 0;
15664 struct recvd_message msg
;
15666 /* do not log painting messages */
15667 if (message
!= WM_PAINT
&&
15668 message
!= WM_NCPAINT
&&
15669 message
!= WM_SYNCPAINT
&&
15670 message
!= WM_ERASEBKGND
&&
15671 message
!= WM_NCHITTEST
&&
15672 message
!= WM_GETTEXT
&&
15673 !ignore_message( message
))
15676 msg
.message
= message
;
15677 msg
.flags
= sent
|wparam
|lparam
;
15678 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
15680 if (message
== LB_ADDSTRING
)
15681 msg
.lParam
= lp
? hash_Ly((const char *)lp
) : 0;
15684 msg
.descr
= "listbox";
15688 defwndproc_counter
++;
15689 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
15690 defwndproc_counter
--;
15695 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
15696 int caret_index
, int top_index
, int line
)
15700 /* calling an orig proc helps to avoid unnecessary message logging */
15701 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
15702 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %Id\n", count
, ret
);
15703 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
15704 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %Id\n", cur_sel
, ret
);
15705 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
15706 ok_(__FILE__
, line
)(ret
== caret_index
||
15707 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
15708 "expected caret index %d, got %Id\n", caret_index
, ret
);
15709 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
15710 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %Id\n", top_index
, ret
);
15713 static void test_listbox_messages(void)
15715 HWND parent
, listbox
;
15718 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15719 100, 100, 200, 200, 0, 0, 0, NULL
);
15720 /* with LBS_HASSTRINGS */
15721 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
15722 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
15723 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
15724 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
15726 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
15730 log_all_parent_messages
++;
15732 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
15733 ok(ret
== 0, "expected 0, got %Id\n", ret
);
15734 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
15735 ok(ret
== 1, "expected 1, got %Id\n", ret
);
15736 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
15737 ok(ret
== 2, "expected 2, got %Id\n", ret
);
15739 ok_sequence(wm_lb_addstring_ownerdraw
, "LB_ADDSTRING", FALSE
);
15740 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
15744 trace("selecting item 0\n");
15745 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
15746 ok(ret
== 0, "expected 0, got %Id\n", ret
);
15747 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
15748 check_lb_state(listbox
, 3, 0, 0, 0);
15751 trace("selecting item 1\n");
15752 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
15753 ok(ret
== 1, "expected 1, got %Id\n", ret
);
15754 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
15755 check_lb_state(listbox
, 3, 1, 1, 0);
15757 trace("selecting item 2\n");
15758 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
15759 ok(ret
== 2, "expected 2, got %Id\n", ret
);
15760 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
15761 check_lb_state(listbox
, 3, 2, 2, 0);
15763 trace("clicking on item 0\n");
15764 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
15765 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
15766 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
15767 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
15768 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
15769 check_lb_state(listbox
, 3, 0, 0, 0);
15772 trace("deleting item 0\n");
15773 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
15774 ok(ret
== 2, "expected 2, got %Id\n", ret
);
15775 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
15776 check_lb_state(listbox
, 2, -1, 0, 0);
15779 trace("deleting item 0\n");
15780 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
15781 ok(ret
== 1, "expected 1, got %Id\n", ret
);
15782 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
15783 check_lb_state(listbox
, 1, -1, 0, 0);
15786 trace("deleting item 0\n");
15787 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
15788 ok(ret
== 0, "expected 0, got %Id\n", ret
);
15789 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
15790 check_lb_state(listbox
, 0, -1, 0, 0);
15793 trace("deleting item 0\n");
15794 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
15795 ok(ret
== LB_ERR
, "expected LB_ERR, got %Id\n", ret
);
15796 check_lb_state(listbox
, 0, -1, 0, 0);
15799 log_all_parent_messages
--;
15801 DestroyWindow(listbox
);
15803 /* with LBS_SORT and without LBS_HASSTRINGS */
15804 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
15805 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_SORT
| WS_VISIBLE
,
15806 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
15807 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
15809 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
15813 log_all_parent_messages
++;
15815 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
15816 ok(ret
== 0, "expected 0, got %Id\n", ret
);
15817 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
15818 ok(ret
== 1, "expected 1, got %Id\n", ret
);
15819 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
15820 ok(ret
== 2, "expected 2, got %Id\n", ret
);
15822 ok_sequence(wm_lb_addstring_sort_ownerdraw
, "LB_ADDSTRING", FALSE
);
15823 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
15825 log_all_parent_messages
--;
15827 DestroyWindow(listbox
);
15829 /* with LBS_HASSTRINGS */
15830 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
15831 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| WS_VISIBLE
,
15832 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
15833 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
15835 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
15839 log_all_parent_messages
++;
15841 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
15842 ok(ret
== 0, "expected 0, got %Id\n", ret
);
15843 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
15844 ok(ret
== 1, "expected 1, got %Id\n", ret
);
15845 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
15846 ok(ret
== 2, "expected 2, got %Id\n", ret
);
15848 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
15849 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
15851 log_all_parent_messages
--;
15853 DestroyWindow(listbox
);
15855 /* with LBS_HASSTRINGS and LBS_SORT */
15856 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
15857 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| LBS_SORT
| WS_VISIBLE
,
15858 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
15859 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
15861 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
15865 log_all_parent_messages
++;
15867 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
15868 ok(ret
== 0, "expected 0, got %Id\n", ret
);
15869 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
15870 ok(ret
== 0, "expected 0, got %Id\n", ret
);
15871 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
15872 ok(ret
== 1, "expected 1, got %Id\n", ret
);
15874 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
15875 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
15877 log_all_parent_messages
--;
15879 DestroyWindow(listbox
);
15880 DestroyWindow(parent
);
15883 /*************************** Menu test ******************************/
15884 static const struct message wm_popup_menu_1
[] =
15886 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
15887 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
15888 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
15889 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
15890 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
15891 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
15892 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
15893 { WM_INITMENU
, sent
|lparam
, 0, 0 },
15894 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
15895 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
15896 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
15897 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15898 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15899 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15900 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15901 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15902 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
15903 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15904 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
15905 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
15906 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
15907 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_MENU
, 0 },
15908 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15909 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
15910 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15911 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15912 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
15913 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
15914 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
15915 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
15916 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
15917 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
15920 static const struct message wm_popup_menu_2
[] =
15922 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
15923 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
15924 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
15925 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
15926 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
15927 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
15928 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
15929 { WM_INITMENU
, sent
|lparam
, 0, 0 },
15930 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
15931 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
15932 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
15933 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
15934 { HCBT_CREATEWND
, hook
},
15935 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15936 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15937 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15938 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15939 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15940 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
15941 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
15942 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15943 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
15944 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
15945 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
15946 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
15947 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
15948 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15949 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15950 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15951 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15952 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15953 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
15954 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15955 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
15956 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
15957 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_MENU
, 0 },
15958 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15959 { HCBT_DESTROYWND
, hook
},
15960 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15961 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15962 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
15963 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15964 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
15965 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15966 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15967 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
15968 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
15969 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
15970 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
15971 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
15972 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
15975 static const struct message wm_popup_menu_3
[] =
15977 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
15978 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
15979 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
15980 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
15981 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
15982 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
15983 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
15984 { WM_INITMENU
, sent
|lparam
, 0, 0 },
15985 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
15986 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
15987 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
15988 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
15989 { HCBT_CREATEWND
, hook
},
15990 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15991 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15992 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15993 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
15994 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
15995 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
15996 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
15997 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
15998 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
15999 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
16000 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
16001 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
16002 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
16003 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16004 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16005 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16006 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16007 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
16008 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
16009 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 1 },
16010 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
16011 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
16012 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_MENU
, 100 },
16013 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
16014 { HCBT_DESTROYWND
, hook
},
16015 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16016 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16017 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
16018 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, OBJID_CLIENT
, 0 },
16019 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
16020 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16021 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16022 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
16023 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
16024 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
16025 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
16026 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
16027 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
16031 static const struct message wm_single_menu_item
[] =
16033 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
16034 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
16035 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
16036 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
16037 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
16038 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
16039 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
16040 { WM_INITMENU
, sent
|lparam
, 0, 0 },
16041 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
16042 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
16043 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
16044 { WM_MENUCOMMAND
, sent
},
16045 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
16046 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
16047 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
16048 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
16050 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
16051 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
16052 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
16053 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
16054 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
16058 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
16060 if (message
== WM_ENTERIDLE
||
16061 message
== WM_INITMENU
||
16062 message
== WM_INITMENUPOPUP
||
16063 message
== WM_MENUSELECT
||
16064 message
== WM_PARENTNOTIFY
||
16065 message
== WM_ENTERMENULOOP
||
16066 message
== WM_EXITMENULOOP
||
16067 message
== WM_UNINITMENUPOPUP
||
16068 message
== WM_KEYDOWN
||
16069 message
== WM_KEYUP
||
16070 message
== WM_CHAR
||
16071 message
== WM_SYSKEYDOWN
||
16072 message
== WM_SYSKEYUP
||
16073 message
== WM_SYSCHAR
||
16074 message
== WM_COMMAND
||
16075 message
== WM_MENUCOMMAND
)
16077 struct recvd_message msg
;
16080 msg
.message
= message
;
16081 msg
.flags
= sent
|wparam
|lparam
;
16084 msg
.descr
= "parent_menu_proc";
16088 return DefWindowProcA(hwnd
, message
, wp
, lp
);
16091 static void set_menu_style(HMENU hmenu
, DWORD style
)
16096 mi
.cbSize
= sizeof(mi
);
16097 mi
.fMask
= MIM_STYLE
;
16098 mi
.dwStyle
= style
;
16099 SetLastError(0xdeadbeef);
16100 ret
= SetMenuInfo(hmenu
, &mi
);
16101 ok(ret
, "SetMenuInfo error %lu\n", GetLastError());
16104 static DWORD
get_menu_style(HMENU hmenu
)
16109 mi
.cbSize
= sizeof(mi
);
16110 mi
.fMask
= MIM_STYLE
;
16112 SetLastError(0xdeadbeef);
16113 ret
= GetMenuInfo(hmenu
, &mi
);
16114 ok(ret
, "GetMenuInfo error %lu\n", GetLastError());
16119 static void test_menu_messages(void)
16123 HMENU hmenu
, hmenu_popup
;
16126 BOOL us_kbd
= (GetKeyboardLayout(0) == (HKL
)(ULONG_PTR
)0x04090409);
16129 cls
.lpfnWndProc
= parent_menu_proc
;
16130 cls
.cbClsExtra
= 0;
16131 cls
.cbWndExtra
= 0;
16132 cls
.hInstance
= GetModuleHandleA(0);
16134 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
16135 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
16136 cls
.lpszMenuName
= NULL
;
16137 cls
.lpszClassName
= "TestMenuClass";
16138 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
16139 if (!RegisterClassA(&cls
)) assert(0);
16141 SetLastError(0xdeadbeef);
16142 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16143 100, 100, 200, 200, 0, 0, 0, NULL
);
16144 ok(hwnd
!= 0, "LoadMenuA error %lu\n", GetLastError());
16146 SetLastError(0xdeadbeef);
16147 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
16148 ok(hmenu
!= 0, "LoadMenuA error %lu\n", GetLastError());
16150 SetMenu(hwnd
, hmenu
);
16151 SetForegroundWindow( hwnd
);
16154 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
16155 style
= get_menu_style(hmenu
);
16156 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %lu\n", style
);
16158 hmenu_popup
= GetSubMenu(hmenu
, 0);
16159 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
16160 style
= get_menu_style(hmenu_popup
);
16161 ok(style
== 0, "expected 0, got %lu\n", style
);
16163 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
16164 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
16165 style
= get_menu_style(hmenu_popup
);
16166 ok(style
== 0, "expected 0, got %lu\n", style
);
16170 skip("skipping ascii VK events on non-us keyboard\n");
16175 trace("testing a popup menu command\n");
16177 keybd_event(VK_MENU
, 0, 0, 0);
16178 keybd_event('E', 0, 0, 0);
16179 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
16180 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
16181 keybd_event(VK_RETURN
, 0, 0, 0);
16182 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
16183 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
16185 TranslateMessage(&msg
);
16186 DispatchMessageA(&msg
);
16188 if (!sequence_cnt
) /* we didn't get any message */
16190 skip( "queuing key events not supported\n" );
16193 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
16194 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
16196 win_skip( "menu tracking through VK_MENU not supported\n" );
16199 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
16201 /* Alt+F, Right, Enter */
16202 trace("testing submenu of a popup menu command\n");
16204 keybd_event(VK_MENU
, 0, 0, 0);
16205 keybd_event('F', 0, 0, 0);
16206 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
16207 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
16208 keybd_event(VK_RIGHT
, 0, 0, 0);
16209 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
16210 keybd_event(VK_RETURN
, 0, 0, 0);
16211 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
16212 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
16214 TranslateMessage(&msg
);
16215 DispatchMessageA(&msg
);
16217 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
16219 trace("testing single menu item command\n");
16221 keybd_event(VK_MENU
, 0, 0, 0);
16222 keybd_event('Q', 0, 0, 0);
16223 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
16224 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
16225 keybd_event(VK_ESCAPE
, 0, 0, 0);
16226 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
16227 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
16229 TranslateMessage(&msg
);
16230 DispatchMessageA(&msg
);
16232 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
16234 set_menu_style(hmenu
, 0);
16235 style
= get_menu_style(hmenu
);
16236 ok(style
== 0, "expected 0, got %lu\n", style
);
16238 hmenu_popup
= GetSubMenu(hmenu
, 0);
16239 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
16240 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
16241 style
= get_menu_style(hmenu_popup
);
16242 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %lu\n", style
);
16244 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
16245 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
16246 style
= get_menu_style(hmenu_popup
);
16247 ok(style
== 0, "expected 0, got %lu\n", style
);
16249 /* Alt+F, Right, Enter */
16250 trace("testing submenu of a popup menu command\n");
16252 keybd_event(VK_MENU
, 0, 0, 0);
16253 keybd_event('F', 0, 0, 0);
16254 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
16255 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
16256 keybd_event(VK_RIGHT
, 0, 0, 0);
16257 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
16258 keybd_event(VK_RETURN
, 0, 0, 0);
16259 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
16260 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
16262 TranslateMessage(&msg
);
16263 DispatchMessageA(&msg
);
16265 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
16268 DestroyWindow(hwnd
);
16269 DestroyMenu(hmenu
);
16273 static void test_paintingloop(void)
16277 paint_loop_done
= FALSE
;
16278 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
16279 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
16280 100, 100, 100, 100, 0, 0, 0, NULL
);
16281 ok(hwnd
!= 0, "PaintLoop window error %lu\n", GetLastError());
16282 ShowWindow(hwnd
,SW_NORMAL
);
16285 while (!paint_loop_done
)
16288 if (PeekMessageA(&msg
, 0, 0, 0, 1))
16290 TranslateMessage(&msg
);
16291 DispatchMessageA(&msg
);
16294 DestroyWindow(hwnd
);
16297 static const struct message NCRBUTTONDOWNSeq
[] =
16299 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16300 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16301 { WM_CAPTURECHANGED
, sent
},
16302 { WM_CONTEXTMENU
, sent
, /*hwnd*/0, -1 },
16306 static const struct message NCXBUTTONUPSeq1
[] =
16308 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_BACKWARD
) },
16312 static const struct message NCXBUTTONUPSeq2
[] =
16314 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_FORWARD
) },
16318 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to minimized visible window */
16319 static const struct message WmRestoreMinimizedOverlappedSeq
[] =
16321 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_RESTORE
, 0 },
16322 { HCBT_MINMAX
, hook
},
16323 { WM_QUERYOPEN
, sent
},
16324 { WM_GETTEXT
, sent
|optional
},
16325 { WM_NCACTIVATE
, sent
|optional
},
16326 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
16327 { WM_WINDOWPOSCHANGED
, sent
|optional
},
16328 { WM_WINDOWPOSCHANGING
, sent
|optional
},
16329 { WM_GETMINMAXINFO
, sent
|defwinproc
},
16330 { WM_NCCALCSIZE
, sent
|optional
},
16331 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16332 { WM_NCPAINT
, sent
|optional
},
16333 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16334 { WM_ERASEBKGND
, sent
|optional
},
16335 { WM_WINDOWPOSCHANGED
, sent
|optional
},
16336 { HCBT_ACTIVATE
, hook
},
16337 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16338 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
16339 { WM_ACTIVATEAPP
, sent
|wparam
, TRUE
},
16340 { WM_NCACTIVATE
, sent
|wparam
, TRUE
},
16341 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16342 { WM_ACTIVATE
, sent
|wparam
, TRUE
},
16343 { HCBT_SETFOCUS
, hook
},
16344 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16345 { WM_SETFOCUS
, sent
|defwinproc
},
16346 { WM_NCPAINT
, sent
},
16347 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16348 { WM_ERASEBKGND
, sent
},
16349 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
16350 { WM_MOVE
, sent
|defwinproc
},
16351 { WM_SIZE
, sent
|defwinproc
},
16352 { WM_NCCALCSIZE
, sent
|optional
},
16353 { WM_NCPAINT
, sent
|optional
},
16354 { WM_ERASEBKGND
, sent
|optional
},
16355 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16356 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
16357 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16358 { WM_ACTIVATE
, sent
|wparam
, TRUE
},
16359 { WM_SYNCPAINT
, sent
|optional
},
16360 { WM_PAINT
, sent
},
16364 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to an active minimized window */
16365 static const struct message WmRestoreActiveMinimizedOverlappedSeq
[] =
16367 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_RESTORE
, 0 },
16368 { HCBT_MINMAX
, hook
},
16369 { WM_QUERYOPEN
, sent
},
16370 { WM_GETTEXT
, sent
|optional
},
16371 { WM_NCACTIVATE
, sent
},
16372 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
16373 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16374 { WM_NCCALCSIZE
, sent
|optional
},
16375 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
16376 { WM_MOVE
, sent
|optional
},
16377 { WM_SIZE
, sent
|optional
},
16378 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
16379 { WM_GETTEXT
, sent
|optional
},
16380 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
16381 { WM_GETMINMAXINFO
, sent
|defwinproc
},
16382 { WM_NCCALCSIZE
, sent
},
16383 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win8+. */
16384 { WM_NCPAINT
, sent
},
16385 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16386 { WM_ERASEBKGND
, sent
},
16387 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
16388 { WM_MOVE
, sent
|defwinproc
},
16389 { WM_SIZE
, sent
|defwinproc
},
16390 { WM_NCCALCSIZE
, sent
|optional
},
16391 { WM_NCPAINT
, sent
|optional
},
16392 { WM_ERASEBKGND
, sent
|optional
},
16393 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16394 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
16395 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
16396 { HCBT_SETFOCUS
, hook
},
16397 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16398 { WM_SETFOCUS
, sent
},
16399 /* Note this WM_ACTIVATE messages even if the window is already active */
16400 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
16401 { WM_SYNCPAINT
, sent
|optional
},
16402 { WM_PAINT
, sent
},
16403 { WM_GETMINMAXINFO
, sent
|optional
},
16407 static struct message WmContextMenuSeq
[] = {
16408 { WM_CONTEXTMENU
, sent
|wparam
, 0 }, /* wparams set in the code */
16409 { WM_CONTEXTMENU
, sent
|wparam
|defwinproc
, 0 },
16410 { WM_CONTEXTMENU
, sent
|wparam
|defwinproc
, 0 },
16414 struct rbuttonup_thread_data
16417 HANDLE wndproc_finished
;
16420 static DWORD CALLBACK
post_rbuttonup_msg( void *arg
)
16422 struct rbuttonup_thread_data
*data
= arg
;
16425 ret
= WaitForSingleObject( data
->wndproc_finished
, 500 );
16426 todo_wine
ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lx\n", ret
);
16427 if( ret
== WAIT_OBJECT_0
) return 0;
16429 PostMessageA( data
->hwnd
, WM_RBUTTONUP
, 0, 0 );
16433 static void test_defwinproc(void)
16435 HWND hwnd
, child
[3];
16437 BOOL gotwmquit
= FALSE
;
16442 struct rbuttonup_thread_data data
;
16446 hwnd
= CreateWindowExA(0, "TestWindowClass", "test_defwndproc",
16447 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0,0,500,100,0,0,0, NULL
);
16452 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
16453 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
16455 /* Zero high word of the lParam */
16456 res
= DefWindowProcA(hwnd
, WM_SETTEXT
, 0, 0x1234);
16457 ok(res
== 0, "WM_SETTEXT was expected to fail, %Id\n", res
);
16459 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
16460 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
16462 res
= DefWindowProcW(hwnd
, WM_SETTEXT
, 0, 0x1234);
16463 ok(res
== 0, "WM_SETTEXT was expected to fail, %Id\n", res
);
16465 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
16466 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
16468 ShowWindow(hwnd
, SW_MINIMIZE
);
16472 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
16474 ok_sequence(WmRestoreMinimizedOverlappedSeq
, "DefWindowProcA(SC_RESTORE):overlapped", TRUE
);
16476 ShowWindow(hwnd
, SW_MINIMIZE
);
16477 SetActiveWindow(hwnd
);
16478 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
16481 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
16483 ok_sequence(WmRestoreActiveMinimizedOverlappedSeq
, "DefWindowProcA(SC_RESTORE):active minimized overlapped", TRUE
);
16485 child
[0] = CreateWindowExA(0, "TestWindowClass", "1st child",
16486 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, hwnd
, 0, 0, NULL
);
16487 child
[1] = CreateWindowExA(0, "TestWindowClass", "2nd child",
16488 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, child
[0], 0, 0, NULL
);
16489 child
[2] = CreateWindowExA(0, "TestWindowClass", "3rd child",
16490 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, child
[1], 0, 0, NULL
);
16493 test_context_menu
= TRUE
;
16494 DefWindowProcA(child
[2], WM_CONTEXTMENU
, 0xcafe, 0);
16495 test_context_menu
= FALSE
;
16496 WmContextMenuSeq
[0].wParam
= (WPARAM
)child
[2];
16497 WmContextMenuSeq
[1].wParam
= (WPARAM
)child
[1];
16498 WmContextMenuSeq
[2].wParam
= (WPARAM
)child
[0];
16499 ok_sequence(WmContextMenuSeq
, "DefWindowProcA(WM_CONTEXTMENU)", FALSE
);
16500 DestroyWindow(child
[0]);
16502 GetCursorPos(&pos
);
16503 GetWindowRect(hwnd
, &rect
);
16504 x
= (rect
.left
+rect
.right
) / 2;
16505 y
= rect
.top
+ GetSystemMetrics(SM_CYFRAME
) + 1;
16506 SetCursorPos(x
, y
);
16508 res
= DefWindowProcA( hwnd
, WM_NCHITTEST
, 0, MAKELPARAM(x
, y
));
16509 ok(res
== HTCAPTION
, "WM_NCHITTEST returned %Id\n", res
);
16511 mouse_event( MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0 );
16512 mouse_event( MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0 );
16516 mouse_event( MOUSEEVENTF_RIGHTUP
, 0, 0, 0, 0 );
16517 /* workaround for missing support for clicking on window frame */
16519 data
.wndproc_finished
= CreateEventA( NULL
, FALSE
, FALSE
, NULL
);
16520 thread
= CreateThread( NULL
, 0, post_rbuttonup_msg
, (void*)&data
, 0, NULL
);
16522 DefWindowProcA( hwnd
, WM_NCRBUTTONDOWN
, HTCAPTION
, MAKELPARAM(x
, y
));
16523 ok_sequence(NCRBUTTONDOWNSeq
, "WM_NCRBUTTONDOWN on caption", FALSE
);
16525 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, 0, MAKELPARAM(x
, y
));
16526 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
16527 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP without button", FALSE
);
16529 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON1
), MAKELPARAM(x
, y
));
16530 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
16531 ok_sequence(NCXBUTTONUPSeq1
, "WM_NCXBUTTONUP with XBUTTON1", FALSE
);
16533 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON2
), MAKELPARAM(x
, y
));
16534 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
16535 ok_sequence(NCXBUTTONUPSeq2
, "WM_NCXBUTTONUP with XBUTTON2", FALSE
);
16537 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, 3), MAKELPARAM(x
, y
));
16538 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
16539 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP with invalid button", FALSE
);
16541 /* Test WM_MOUSEACTIVATE */
16542 #define TEST_MOUSEACTIVATE(A,B,C) \
16543 res = DefWindowProcA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0)); \
16544 ok(res == B, "WM_MOUSEACTIVATE for %s returned %Id\n", #A, res); \
16545 res = DefWindowProcA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,WM_LBUTTONDOWN)); \
16546 ok(res == C, "WM_MOUSEACTIVATE for %s returned %Id\n", #A, res);
16548 TEST_MOUSEACTIVATE(HTERROR
, MA_ACTIVATE
, MA_ACTIVATE
);
16549 TEST_MOUSEACTIVATE(HTTRANSPARENT
, MA_ACTIVATE
, MA_ACTIVATE
);
16550 TEST_MOUSEACTIVATE(HTNOWHERE
, MA_ACTIVATE
, MA_ACTIVATE
);
16551 TEST_MOUSEACTIVATE(HTCLIENT
, MA_ACTIVATE
, MA_ACTIVATE
);
16552 TEST_MOUSEACTIVATE(HTCAPTION
, MA_ACTIVATE
, MA_NOACTIVATE
);
16553 TEST_MOUSEACTIVATE(HTSYSMENU
, MA_ACTIVATE
, MA_ACTIVATE
);
16554 TEST_MOUSEACTIVATE(HTSIZE
, MA_ACTIVATE
, MA_ACTIVATE
);
16555 TEST_MOUSEACTIVATE(HTMENU
, MA_ACTIVATE
, MA_ACTIVATE
);
16556 TEST_MOUSEACTIVATE(HTHSCROLL
, MA_ACTIVATE
, MA_ACTIVATE
);
16557 TEST_MOUSEACTIVATE(HTVSCROLL
, MA_ACTIVATE
, MA_ACTIVATE
);
16558 TEST_MOUSEACTIVATE(HTMINBUTTON
, MA_ACTIVATE
, MA_ACTIVATE
);
16559 TEST_MOUSEACTIVATE(HTMAXBUTTON
, MA_ACTIVATE
, MA_ACTIVATE
);
16560 TEST_MOUSEACTIVATE(HTLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
16561 TEST_MOUSEACTIVATE(HTRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
16562 TEST_MOUSEACTIVATE(HTTOP
, MA_ACTIVATE
, MA_ACTIVATE
);
16563 TEST_MOUSEACTIVATE(HTTOPLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
16564 TEST_MOUSEACTIVATE(HTTOPRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
16565 TEST_MOUSEACTIVATE(HTBOTTOM
, MA_ACTIVATE
, MA_ACTIVATE
);
16566 TEST_MOUSEACTIVATE(HTBOTTOMLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
16567 TEST_MOUSEACTIVATE(HTBOTTOMRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
16568 TEST_MOUSEACTIVATE(HTBORDER
, MA_ACTIVATE
, MA_ACTIVATE
);
16569 TEST_MOUSEACTIVATE(HTOBJECT
, MA_ACTIVATE
, MA_ACTIVATE
);
16570 TEST_MOUSEACTIVATE(HTCLOSE
, MA_ACTIVATE
, MA_ACTIVATE
);
16571 TEST_MOUSEACTIVATE(HTHELP
, MA_ACTIVATE
, MA_ACTIVATE
);
16573 SetEvent( data
.wndproc_finished
);
16574 WaitForSingleObject( thread
, 1000 );
16575 CloseHandle( data
.wndproc_finished
);
16576 CloseHandle( thread
);
16578 SetCursorPos(pos
.x
, pos
.y
);
16580 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
16581 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
16582 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
16583 DispatchMessageA( &msg
);
16585 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
16586 DestroyWindow( hwnd
);
16589 static void test_desktop_winproc(void)
16591 HINSTANCE instance
= GetModuleHandleA(NULL
);
16592 RECT rect
, default_rect
;
16593 WNDPROC desktop_proc
;
16600 ret
= GetClassInfoA(instance
, (const CHAR
*)MAKEINTATOM(32769), &cls
);
16601 ok(ret
, "Failed to get desktop class.\n");
16602 desktop_proc
= cls
.lpfnWndProc
;
16604 memset(&cls
, 0, sizeof(cls
));
16605 cls
.lpfnWndProc
= desktop_proc
;
16606 cls
.hInstance
= instance
;
16607 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
16608 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
16609 cls
.lpszClassName
= "TestDesktopClass";
16610 ret
= !!RegisterClassA(&cls
);
16611 ok(ret
, "Failed to register class.\n");
16613 hwnd
= CreateWindowExA(0, cls
.lpszClassName
, "test_desktop_wndproc",
16614 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0, 0, 500, 100, 0, 0, 0, NULL
);
16615 if (!hwnd
) /* win2003 */
16617 skip("Failed to create window with desktop window procedure.\n");
16618 goto out_unregister
;
16621 memset(&cls
, 0, sizeof(cls
));
16622 ret
= GetClassInfoA(instance
, "TestDesktopClass", &cls
);
16623 ok(ret
, "Failed to get class info.\n");
16624 ok(cls
.lpfnWndProc
== desktop_proc
, "Got %p, expected %p.\n", cls
.lpfnWndProc
, desktop_proc
);
16626 GetWindowTextA(hwnd
, buffer
, ARRAY_SIZE(buffer
));
16627 todo_wine
ok(!strcmp(buffer
, "test_desktop_wndproc"), "Got unexpected window text: %s.\n", buffer
);
16629 res
= CallWindowProcA(desktop_proc
, hwnd
, WM_SETTEXT
, 0, (LPARAM
)"test");
16630 ok(res
== TRUE
, "Failed to set text, %Id.\n", res
);
16631 GetWindowTextA(hwnd
, buffer
, ARRAY_SIZE(buffer
));
16632 ok(!strcmp(buffer
, "test"), "Got unexpected window text: %s.\n", buffer
);
16634 SetRect(&default_rect
, 0, 0, 100, 100);
16635 res
= DefWindowProcW(hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&default_rect
);
16636 ok(!res
, "Got unexpected result %Id.\n", res
);
16638 SetRect(&rect
, 0, 0, 100, 100);
16639 res
= CallWindowProcA(desktop_proc
, hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
);
16640 ok(!res
, "Got unexpected result %Id.\n", res
);
16641 todo_wine
ok(EqualRect(&rect
, &default_rect
), "rect Got %s, expected %s.\n",
16642 wine_dbgstr_rect(&rect
), wine_dbgstr_rect(&default_rect
));
16644 DestroyWindow(hwnd
);
16647 UnregisterClassA("TestDesktopClass", instance
);
16650 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
16651 static void clear_clipboard_(int line
, HWND hWnd
)
16654 succ
= OpenClipboard(hWnd
);
16655 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%lu\n", GetLastError());
16656 succ
= EmptyClipboard();
16657 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%lu\n", GetLastError());
16658 succ
= CloseClipboard();
16659 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%lu\n", GetLastError());
16662 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
16663 static void expect_HWND_(int line
, HWND expected
, HWND got
)
16665 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
16668 static WNDPROC pOldViewerProc
;
16670 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16672 static BOOL recursion_guard
;
16674 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
16676 recursion_guard
= TRUE
;
16677 clear_clipboard(hWnd
);
16678 recursion_guard
= FALSE
;
16680 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
16683 static void test_clipboard_viewers(void)
16685 static struct message wm_change_cb_chain
[] =
16687 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
16690 static const struct message wm_clipboard_destroyed
[] =
16692 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
16695 static struct message wm_clipboard_changed
[] =
16697 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
16700 static struct message wm_clipboard_changed_and_owned
[] =
16702 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
16703 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
16707 HINSTANCE hInst
= GetModuleHandleA(NULL
);
16708 HWND hWnd1
, hWnd2
, hWnd3
;
16712 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
16713 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
16714 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
16715 GetDesktopWindow(), NULL
, hInst
, NULL
);
16716 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
16717 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
16718 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
16719 GetDesktopWindow(), NULL
, hInst
, NULL
);
16720 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
16721 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
16722 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
16723 GetDesktopWindow(), NULL
, hInst
, NULL
);
16724 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
16725 assert(hWnd1
&& hWnd2
&& hWnd3
);
16727 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */
16730 /* Test getting the clipboard viewer and setting the viewer to NULL. */
16731 hOrigViewer
= GetClipboardViewer();
16732 hRet
= SetClipboardViewer(NULL
);
16733 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
16734 expect_HWND(hOrigViewer
, hRet
);
16735 expect_HWND(NULL
, GetClipboardViewer());
16737 /* Test registering hWnd1 as a viewer. */
16738 hRet
= SetClipboardViewer(hWnd1
);
16739 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
16740 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
16741 expect_HWND(NULL
, hRet
);
16742 expect_HWND(hWnd1
, GetClipboardViewer());
16744 /* Test that changing the clipboard actually refreshes the registered viewer. */
16745 clear_clipboard(hWnd1
);
16746 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
16747 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
16749 /* Again, but with different owner. */
16750 clear_clipboard(hWnd2
);
16751 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
16752 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
16754 /* Test re-registering same window. */
16755 hRet
= SetClipboardViewer(hWnd1
);
16756 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
16757 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
16758 expect_HWND(hWnd1
, hRet
);
16759 expect_HWND(hWnd1
, GetClipboardViewer());
16761 /* Test ChangeClipboardChain. */
16762 ChangeClipboardChain(hWnd2
, hWnd3
);
16763 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
16764 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
16765 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
16766 expect_HWND(hWnd1
, GetClipboardViewer());
16768 ChangeClipboardChain(hWnd2
, NULL
);
16769 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
16770 wm_change_cb_chain
[0].lParam
= 0;
16771 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
16772 expect_HWND(hWnd1
, GetClipboardViewer());
16774 ChangeClipboardChain(NULL
, hWnd2
);
16775 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", FALSE
);
16776 expect_HWND(hWnd1
, GetClipboardViewer());
16778 /* Actually change clipboard viewer with ChangeClipboardChain. */
16779 ChangeClipboardChain(hWnd1
, hWnd2
);
16780 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
16781 expect_HWND(hWnd2
, GetClipboardViewer());
16783 /* Test that no refresh messages are sent when viewer has unregistered. */
16784 clear_clipboard(hWnd2
);
16785 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
16787 /* Register hWnd1 again. */
16788 ChangeClipboardChain(hWnd2
, hWnd1
);
16789 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
16790 expect_HWND(hWnd1
, GetClipboardViewer());
16792 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
16793 * changes the clipboard. When this happens, the system shouldn't send
16794 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
16796 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
16797 clear_clipboard(hWnd2
);
16798 /* The clipboard owner is changed in recursive_viewer_proc: */
16799 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
16800 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
16802 /* Test unregistering. */
16803 ChangeClipboardChain(hWnd1
, NULL
);
16804 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
16805 expect_HWND(NULL
, GetClipboardViewer());
16807 clear_clipboard(hWnd1
);
16808 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
16810 DestroyWindow(hWnd1
);
16811 DestroyWindow(hWnd2
);
16812 DestroyWindow(hWnd3
);
16813 SetClipboardViewer(hOrigViewer
);
16816 static void test_PostMessage(void)
16818 static const struct
16824 { HWND_TOP
/* 0 */, TRUE
},
16825 { HWND_BROADCAST
, TRUE
},
16826 { HWND_BOTTOM
, TRUE
},
16827 { HWND_TOPMOST
, TRUE
},
16828 { HWND_NOTOPMOST
, FALSE
},
16829 { HWND_MESSAGE
, FALSE
},
16830 { (HWND
)0xdeadbeef, FALSE
}
16836 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
16838 SetLastError(0xdeadbeef);
16839 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
16840 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
16842 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
16849 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
16850 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
16852 for (i
= 0; i
< ARRAY_SIZE(data
); i
++)
16854 memset(&msg
, 0xab, sizeof(msg
));
16855 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
16856 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
16860 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
16861 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
16862 "%d: got ret %d hwnd %p msg %04x wParam %08Ix lParam %08Ix instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
16863 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
16865 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
16866 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
16867 "%d: got ret %d hwnd %p msg %04x wParam %08Ix lParam %08Ix instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
16868 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
16872 DestroyWindow(hwnd
);
16876 static WPARAM g_broadcast_wparam
;
16877 static LRESULT WINAPI
broadcast_test_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16879 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
16881 if (wParam
== 0xbaadbeef)
16882 g_broadcast_wparam
= wParam
;
16884 g_broadcast_wparam
= 0;
16886 return CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
16888 static WNDPROC
*g_oldproc_sub
;
16889 static WPARAM
*g_broadcast_sub_wparam
;
16890 static LRESULT WINAPI
broadcast_test_sub_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16892 int sub_index
= GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
16894 g_broadcast_sub_wparam
[sub_index
] = (wParam
== 0xbaadbeef) ? wParam
: 0;
16896 return CallWindowProcA(g_oldproc_sub
[sub_index
], hwnd
, message
, wParam
, lParam
);
16899 static void test_broadcast(void)
16901 static const UINT messages
[] =
16907 0xc000, /* lowest possible atom returned by RegisterWindowMessage */
16910 static const struct
16916 {WS_OVERLAPPED
, TRUE
},
16917 {WS_OVERLAPPED
|WS_DLGFRAME
, TRUE
},
16918 {WS_OVERLAPPED
|WS_BORDER
, TRUE
},
16919 {WS_OVERLAPPED
|WS_CAPTION
, TRUE
},
16921 {WS_CHILD
|WS_DLGFRAME
, FALSE
},
16922 {WS_CHILD
|WS_BORDER
, FALSE
},
16923 {WS_CHILD
|WS_CAPTION
, FALSE
},
16924 {WS_CHILD
|WS_POPUP
, TRUE
},
16926 {WS_POPUP
|WS_DLGFRAME
, TRUE
},
16927 {WS_POPUP
|WS_BORDER
, TRUE
},
16928 {WS_POPUP
|WS_CAPTION
, TRUE
},
16935 hwnd_sub
= HeapAlloc( GetProcessHeap(), 0, ARRAY_SIZE(bcast_expect
) * sizeof(*hwnd_sub
) );
16936 g_oldproc_sub
= HeapAlloc( GetProcessHeap(), 0, ARRAY_SIZE(bcast_expect
) * sizeof(*g_oldproc_sub
) );
16937 g_broadcast_sub_wparam
= HeapAlloc( GetProcessHeap(), 0, ARRAY_SIZE(bcast_expect
) * sizeof(*g_broadcast_sub_wparam
) );
16939 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0, 0, 0, 0, 0, 0, 0, NULL
);
16940 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
16942 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_proc
);
16943 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
16945 for (i
= 0; i
< ARRAY_SIZE(messages
); i
++)
16948 BOOL msg_expected
= (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000);
16952 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
16955 /* post, broadcast */
16956 ret
= PostMessageA(HWND_BROADCAST
, messages
[i
], 0, 0);
16957 ok(ret
, "%d: got %d, error %ld\n", i
, ret
, GetLastError());
16959 memset(&msg
, 0xab, sizeof(msg
));
16960 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
16961 ok(ret
== msg_expected
, "%d: message %04x, got %d, error %ld\n", i
, messages
[i
], ret
, GetLastError());
16963 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
16965 /* post, topmost */
16966 ret
= PostMessageA(HWND_TOPMOST
, messages
[i
], 0, 0);
16967 ok(ret
, "%d: got %d, error %ld\n", i
, ret
, GetLastError());
16969 memset(&msg
, 0xab, sizeof(msg
));
16970 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
16971 ok(ret
== msg_expected
, "%d: message %04x, got %d, error %ld\n", i
, messages
[i
], ret
, GetLastError());
16973 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
16976 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
16978 hwnd_sub
[j
] = CreateWindowA("static", NULL
, bcast_expect
[j
].style
, 0, 0, 0, 0, hwnd
, 0, 0, NULL
);
16979 ok(hwnd_sub
[j
] != NULL
, "got %p\n", hwnd_sub
[j
]);
16980 /* CreateWindow adds extra style flags, so call SetWindowLong to clear some of those. */
16981 SetWindowLongA(hwnd_sub
[j
], GWL_STYLE
, bcast_expect
[j
].style
);
16983 g_oldproc_sub
[j
] = (WNDPROC
)SetWindowLongPtrA(hwnd_sub
[j
], GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_sub_proc
);
16984 SetWindowLongPtrA(hwnd_sub
[j
], GWLP_USERDATA
, (LONG_PTR
)j
);
16987 for (i
= 0; i
< ARRAY_SIZE(messages
); i
++)
16990 BOOL msg_expected
= (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000);
16992 /* send, broadcast */
16993 g_broadcast_wparam
= 0xdead;
16994 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
16995 g_broadcast_sub_wparam
[j
] = 0xdead;
16996 ret
= SendMessageTimeoutA(HWND_BROADCAST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
16997 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
16998 win_skip("broadcasting test %d, timeout\n", i
);
17001 WPARAM wparam_expected
= msg_expected
? 0xbaadbeef : 0xdead;
17002 ok(g_broadcast_wparam
== wparam_expected
, "%d: message %04x, got %#Ix, error %ld\n",
17003 i
, messages
[i
], g_broadcast_wparam
, GetLastError());
17004 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
17006 wparam_expected
= (msg_expected
&& bcast_expect
[j
].receive
) ? 0xbaadbeef : 0xdead;
17007 ok(g_broadcast_sub_wparam
[j
] == wparam_expected
,
17008 "%d,%d: message %04x, got %#Ix, error %ld\n", i
, j
, messages
[i
],
17009 g_broadcast_sub_wparam
[j
], GetLastError());
17013 /* send, topmost */
17014 g_broadcast_wparam
= 0xdead;
17015 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
17016 g_broadcast_sub_wparam
[j
] = 0xdead;
17017 ret
= SendMessageTimeoutA(HWND_TOPMOST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
17018 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
17019 win_skip("broadcasting test %d, timeout\n", i
);
17022 WPARAM wparam_expected
= msg_expected
? 0xbaadbeef : 0xdead;
17023 ok(g_broadcast_wparam
== wparam_expected
, "%d: message %04x, got %#Ix, error %ld\n",
17024 i
, messages
[i
], g_broadcast_wparam
, GetLastError());
17025 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
17027 wparam_expected
= (msg_expected
&& bcast_expect
[j
].receive
) ? 0xbaadbeef : 0xdead;
17028 ok(g_broadcast_sub_wparam
[j
] == wparam_expected
,
17029 "%d,%d: message %04x, got %#Ix, error %ld\n", i
, j
, messages
[i
],
17030 g_broadcast_sub_wparam
[j
], GetLastError());
17035 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
17036 DestroyWindow(hwnd_sub
[j
]);
17038 HeapFree(GetProcessHeap(), 0, g_broadcast_sub_wparam
);
17039 HeapFree(GetProcessHeap(), 0, g_oldproc_sub
);
17040 HeapFree(GetProcessHeap(), 0, hwnd_sub
);
17042 DestroyWindow(hwnd
);
17045 static const struct
17049 } wait_idle_expect
[] =
17051 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
17052 { WAIT_TIMEOUT
, 0, FALSE
},
17053 { WAIT_TIMEOUT
, 0, FALSE
},
17054 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
17055 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
17056 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
17057 { WAIT_TIMEOUT
, 0, FALSE
},
17058 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
17061 /* 10 */ { 0, 0, FALSE
},
17063 { 0, WAIT_TIMEOUT
, FALSE
},
17066 /* 15 */ { 0, 0, FALSE
},
17067 { WAIT_TIMEOUT
, 0, FALSE
},
17068 { WAIT_TIMEOUT
, 0, FALSE
},
17069 { WAIT_TIMEOUT
, 0, FALSE
},
17070 { WAIT_TIMEOUT
, 0, FALSE
},
17071 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
17074 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
17078 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
17080 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
17084 static void do_wait_idle_child( int arg
)
17091 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
17092 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
17094 memset( &cls
, 0, sizeof(cls
) );
17095 cls
.lpfnWndProc
= DefWindowProcA
;
17096 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
17097 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
17098 cls
.lpszClassName
= "TestClass";
17099 RegisterClassA( &cls
);
17101 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
17103 ok( start_event
!= 0, "failed to create start event, error %lu\n", GetLastError() );
17104 ok( end_event
!= 0, "failed to create end event, error %lu\n", GetLastError() );
17109 SetEvent( start_event
);
17112 SetEvent( start_event
);
17114 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
17117 SetEvent( start_event
);
17119 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
17120 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
17121 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
17124 SetEvent( start_event
);
17126 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
17129 SetEvent( start_event
);
17131 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
17132 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
17135 SetEvent( start_event
);
17137 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
17138 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
17141 SetEvent( start_event
);
17143 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
17144 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
17146 GetMessageA( &msg
, 0, 0, 0 );
17147 DispatchMessageA( &msg
);
17151 SetEvent( start_event
);
17153 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
17154 SetTimer( hwnd
, 3, 1, NULL
);
17156 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
17159 SetEvent( start_event
);
17161 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
17162 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
17165 SetEvent( start_event
);
17167 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
17168 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
17169 for (;;) GetMessageA( &msg
, 0, 0, 0 );
17172 SetEvent( start_event
);
17174 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
17175 SetTimer( hwnd
, 3, 1, NULL
);
17177 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
17180 SetEvent( start_event
);
17182 return; /* exiting the process makes WaitForInputIdle return success too */
17184 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
17186 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
17187 SetEvent( start_event
);
17190 SetEvent( start_event
);
17191 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
17193 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
17194 WaitForSingleObject( thread
, 10000 );
17195 CloseHandle( thread
);
17198 SetEvent( start_event
);
17200 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
17203 SetEvent( start_event
);
17205 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
17208 SetEvent( start_event
);
17210 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
17213 SetEvent( start_event
);
17215 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
17218 SetEvent( start_event
);
17220 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
17223 SetEvent( start_event
);
17225 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
17228 SetEvent( start_event
);
17230 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
17233 WaitForSingleObject( end_event
, 2000 );
17234 CloseHandle( start_event
);
17235 CloseHandle( end_event
);
17236 if (hwnd
) DestroyWindow( hwnd
);
17239 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
17241 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
17242 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
17245 static DWORD CALLBACK
wait_idle_thread( void *arg
)
17251 memset( &cls
, 0, sizeof(cls
) );
17252 cls
.lpfnWndProc
= wait_idle_proc
;
17253 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
17254 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
17255 cls
.lpszClassName
= "TestClass";
17256 RegisterClassA( &cls
);
17258 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
17259 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
17260 DestroyWindow(hwnd
);
17264 static void test_WaitForInputIdle( char *argv0
)
17266 char path
[MAX_PATH
];
17267 PROCESS_INFORMATION pi
;
17268 STARTUPINFOA startup
;
17270 HANDLE start_event
, end_event
, thread
;
17273 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
17274 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
17275 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
17277 if (console_app
) /* build the test with -mwindows for better coverage */
17278 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
17280 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
17281 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
17282 ok(start_event
!= 0, "failed to create start event, error %lu\n", GetLastError());
17283 ok(end_event
!= 0, "failed to create end event, error %lu\n", GetLastError());
17285 memset( &startup
, 0, sizeof(startup
) );
17286 startup
.cb
= sizeof(startup
);
17287 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
17288 startup
.wShowWindow
= SW_SHOWNORMAL
;
17290 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
17292 for (i
= 0; i
< ARRAY_SIZE(wait_idle_expect
); i
++)
17294 ResetEvent( start_event
);
17295 ResetEvent( end_event
);
17296 sprintf( path
, "%s msg %u", argv0
, i
);
17297 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
17298 ok( ret
, "CreateProcess '%s' failed err %lu.\n", path
, GetLastError() );
17301 ret
= WaitForSingleObject( start_event
, 5000 );
17302 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
17303 if (ret
== WAIT_OBJECT_0
)
17305 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
17306 if (ret
== WAIT_FAILED
)
17308 ret
== wait_idle_expect
[i
].exp
||
17309 broken(ret
== wait_idle_expect
[i
].broken
),
17310 "%u: WaitForInputIdle error %08x expected %08lx\n",
17311 i
, ret
, wait_idle_expect
[i
].exp
);
17312 else todo_wine_if (wait_idle_expect
[i
].todo
)
17313 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
17314 "%u: WaitForInputIdle error %08x expected %08lx\n",
17315 i
, ret
, wait_idle_expect
[i
].exp
);
17316 SetEvent( end_event
);
17317 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
17319 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
17320 wait_child_process( pi
.hProcess
);
17321 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
17322 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
17323 CloseHandle( pi
.hProcess
);
17324 CloseHandle( pi
.hThread
);
17327 CloseHandle( end_event
);
17328 CloseHandle( start_event
);
17329 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
17330 WaitForSingleObject( thread
, 10000 );
17331 CloseHandle( thread
);
17334 static const struct message WmSetParentSeq_1
[] = {
17335 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
17336 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17337 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
17338 { WM_CHILDACTIVATE
, sent
},
17339 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
17340 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
17341 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17342 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
17346 static const struct message WmSetParentSeq_2
[] = {
17347 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
17348 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
17349 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17350 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
17351 { HCBT_SETFOCUS
, hook
|optional
},
17352 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
17353 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
17354 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
17355 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
17356 { WM_KILLFOCUS
, sent
|wparam
, 0 },
17357 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17358 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
17359 { HCBT_ACTIVATE
, hook
|optional
},
17360 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
17361 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
17362 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
17363 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
17364 { HCBT_SETFOCUS
, hook
|optional
},
17365 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
17366 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
17367 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
17368 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
17369 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17370 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
17371 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
17372 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
17373 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
17378 static void test_SetParent(void)
17380 HWND parent1
, parent2
, child
, popup
;
17383 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
17384 100, 100, 200, 200, 0, 0, 0, NULL
);
17385 ok(parent1
!= 0, "Failed to create parent1 window\n");
17387 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
17388 400, 100, 200, 200, 0, 0, 0, NULL
);
17389 ok(parent2
!= 0, "Failed to create parent2 window\n");
17391 /* WS_CHILD window */
17392 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
17393 10, 10, 150, 150, parent1
, 0, 0, NULL
);
17394 ok(child
!= 0, "Failed to create child window\n");
17396 GetWindowRect(parent1
, &rc
);
17397 trace("parent1 %s\n", wine_dbgstr_rect(&rc
));
17398 GetWindowRect(child
, &rc_old
);
17399 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
17400 trace("child %s\n", wine_dbgstr_rect(&rc_old
));
17404 SetParent(child
, parent2
);
17406 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", FALSE
);
17408 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
17409 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
17411 GetWindowRect(parent2
, &rc
);
17412 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
17413 GetWindowRect(child
, &rc
);
17414 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
17415 trace("child %s\n", wine_dbgstr_rect(&rc
));
17417 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
17418 wine_dbgstr_rect(&rc
));
17420 /* WS_POPUP window */
17421 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
17422 20, 20, 100, 100, 0, 0, 0, NULL
);
17423 ok(popup
!= 0, "Failed to create popup window\n");
17425 GetWindowRect(popup
, &rc_old
);
17426 trace("popup %s\n", wine_dbgstr_rect(&rc_old
));
17430 SetParent(popup
, child
);
17432 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
17434 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
17435 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
17437 GetWindowRect(child
, &rc
);
17438 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
17439 GetWindowRect(popup
, &rc
);
17440 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
17441 trace("popup %s\n", wine_dbgstr_rect(&rc
));
17443 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
17444 wine_dbgstr_rect(&rc
));
17446 DestroyWindow(popup
);
17447 DestroyWindow(child
);
17448 DestroyWindow(parent1
);
17449 DestroyWindow(parent2
);
17454 static const struct message WmKeyReleaseOnly
[] = {
17455 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
17456 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
17459 static const struct message WmKeyPressNormal
[] = {
17460 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
17461 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
17464 static const struct message WmKeyPressRepeat
[] = {
17465 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
17466 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
17469 static const struct message WmKeyReleaseNormal
[] = {
17470 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
17471 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
17475 static void test_keyflags(void)
17479 BYTE keyboard_state
[256];
17482 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
17483 100, 100, 200, 200, 0, 0, 0, NULL
);
17488 /* keyup without a keydown */
17489 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
17490 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
17491 DispatchMessageA(&msg
);
17492 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
17494 key_state
= GetAsyncKeyState(0x41);
17495 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
17497 key_state
= GetKeyState(0x41);
17498 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
17501 keybd_event(0x41, 0, 0, 0);
17502 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
17503 DispatchMessageA(&msg
);
17504 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
17506 key_state
= GetAsyncKeyState(0x41);
17507 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17509 key_state
= GetKeyState(0x41);
17510 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17512 /* keydown repeat */
17513 keybd_event(0x41, 0, 0, 0);
17514 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
17515 DispatchMessageA(&msg
);
17516 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
17518 key_state
= GetAsyncKeyState(0x41);
17519 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17521 key_state
= GetKeyState(0x41);
17522 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17525 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
17526 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
17527 DispatchMessageA(&msg
);
17528 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
17530 key_state
= GetAsyncKeyState(0x41);
17531 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
17533 key_state
= GetKeyState(0x41);
17534 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
17536 /* set the key state in this thread */
17537 GetKeyboardState(keyboard_state
);
17538 keyboard_state
[0x41] = 0x80;
17539 SetKeyboardState(keyboard_state
);
17541 key_state
= GetAsyncKeyState(0x41);
17542 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
17545 keybd_event(0x41, 0, 0, 0);
17546 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
17547 DispatchMessageA(&msg
);
17548 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
17550 key_state
= GetAsyncKeyState(0x41);
17551 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17553 key_state
= GetKeyState(0x41);
17554 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17556 /* clear the key state in this thread */
17557 GetKeyboardState(keyboard_state
);
17558 keyboard_state
[0x41] = 0;
17559 SetKeyboardState(keyboard_state
);
17561 key_state
= GetAsyncKeyState(0x41);
17562 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17565 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
17566 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
17567 DispatchMessageA(&msg
);
17568 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
17570 key_state
= GetAsyncKeyState(0x41);
17571 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
17573 key_state
= GetKeyState(0x41);
17574 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
17576 DestroyWindow(test_window
);
17580 static const struct message WmHotkeyPressLWIN
[] = {
17581 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
17582 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
17583 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
17586 static const struct message WmHotkeyPress
[] = {
17587 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
17588 { WM_HOTKEY
, sent
|wparam
, 5 },
17591 static const struct message WmHotkeyRelease
[] = {
17592 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
17593 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
17594 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
17597 static const struct message WmHotkeyReleaseLWIN
[] = {
17598 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
17599 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
17600 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
17603 static const struct message WmHotkeyCombined
[] = {
17604 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
17605 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
17606 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
17607 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
17608 { WM_APP
, sent
, 0, 0 },
17609 { WM_HOTKEY
, sent
|wparam
, 5 },
17610 { WM_APP
+1, sent
, 0, 0 },
17611 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
17612 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
17613 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
17614 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
17615 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
17616 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
17619 static const struct message WmHotkeyPrevious
[] = {
17620 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
17621 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
17622 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
17623 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
17624 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
17625 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
17626 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
17627 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
17628 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
17629 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
17630 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
17631 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
17634 static const struct message WmHotkeyNew
[] = {
17635 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
17636 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
17637 { WM_HOTKEY
, sent
|wparam
, 5 },
17638 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
17639 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
17642 static const struct message WmHotkeyPressALT
[] = {
17643 { WM_SYSKEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LMENU
, LLKHF_INJECTED
|LLKHF_ALTDOWN
},
17644 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17645 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17648 static const struct message WmHotkeyPressWithALT
[] = {
17649 { WM_SYSKEYDOWN
, kbd_hook
, 0, LLKHF_INJECTED
|LLKHF_ALTDOWN
}, /* lparam not checked */
17650 { WM_HOTKEY
, sent
|wparam
, 6 },
17653 static const struct message WmHotkeyReleaseWithALT
[] = {
17654 { WM_SYSKEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
|LLKHF_ALTDOWN
},
17655 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0xa0000001 },
17656 { WM_SYSKEYUP
, sent
|lparam
, 0, 0xa0000001 },
17659 static const struct message WmHotkeyReleaseALT
[] = {
17660 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LMENU
, LLKHF_INJECTED
|LLKHF_UP
},
17661 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
17662 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
17666 static int hotkey_letter
;
17668 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
17670 struct recvd_message msg
;
17672 if (nCode
== HC_ACTION
)
17674 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
17677 msg
.message
= wParam
;
17678 msg
.flags
= kbd_hook
|wparam
|lparam
;
17679 msg
.wParam
= kdbhookstruct
->vkCode
;
17680 msg
.lParam
= kdbhookstruct
->flags
;
17681 msg
.descr
= "KeyboardHookProc";
17684 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
||
17685 wParam
== WM_SYSKEYUP
|| wParam
== WM_SYSKEYDOWN
)
17687 ok(kdbhookstruct
->vkCode
== VK_LWIN
||
17688 kdbhookstruct
->vkCode
== VK_LMENU
||
17689 kdbhookstruct
->vkCode
== hotkey_letter
,
17690 "unexpected keycode %lx\n", kdbhookstruct
->vkCode
);
17694 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
17697 static void test_hotkey(void)
17699 HWND test_window
, taskbar_window
;
17702 DWORD queue_status
;
17705 SetLastError(0xdeadbeef);
17706 ret
= UnregisterHotKey(NULL
, 0);
17709 skip("hotkeys not supported\n");
17713 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
17714 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17715 "unexpected error %ld\n", GetLastError());
17717 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
17718 100, 100, 200, 200, 0, 0, 0, NULL
);
17722 SetLastError(0xdeadbeef);
17723 ret
= UnregisterHotKey(test_window
, 0);
17724 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
17725 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17726 "unexpected error %ld\n", GetLastError());
17728 /* Search for a Windows Key + letter combination that hasn't been registered */
17729 for (hotkey_letter
= 0x41; hotkey_letter
<= 0x51; hotkey_letter
++)
17731 SetLastError(0xdeadbeef);
17732 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
17740 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17741 "unexpected error %ld\n", GetLastError());
17745 if (hotkey_letter
== 0x52)
17747 ok(0, "Couldn't find any free Windows Key + letter combination\n");
17751 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
17752 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
17754 /* Same key combination, different id */
17755 SetLastError(0xdeadbeef);
17756 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
17757 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
17758 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17759 "unexpected error %ld\n", GetLastError());
17761 /* Same key combination, different window */
17762 SetLastError(0xdeadbeef);
17763 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
17764 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
17765 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17766 "unexpected error %ld\n", GetLastError());
17768 /* Register the same hotkey twice */
17769 SetLastError(0xdeadbeef);
17770 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
17771 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
17772 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17773 "unexpected error %ld\n", GetLastError());
17775 /* Window on another thread */
17776 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
17777 if (!taskbar_window
)
17779 skip("no taskbar?\n");
17783 SetLastError(0xdeadbeef);
17784 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
17785 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
17786 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
17787 "unexpected error %ld\n", GetLastError());
17790 /* Inject the appropriate key sequence */
17791 keybd_event(VK_LWIN
, 0, 0, 0);
17792 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17793 DispatchMessageA(&msg
);
17794 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
17796 keybd_event(hotkey_letter
, 0, 0, 0);
17797 queue_status
= GetQueueStatus(QS_HOTKEY
);
17798 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
17799 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17801 if (msg
.message
== WM_HOTKEY
)
17803 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
17804 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
17806 DispatchMessageA(&msg
);
17808 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
17810 queue_status
= GetQueueStatus(QS_HOTKEY
);
17811 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %lx\n", queue_status
);
17813 key_state
= GetAsyncKeyState(hotkey_letter
);
17814 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
17816 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
17817 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17818 DispatchMessageA(&msg
);
17819 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
17821 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
17822 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17823 DispatchMessageA(&msg
);
17824 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
17826 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
17827 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
17828 queue_status
= GetQueueStatus(QS_HOTKEY
);
17829 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
17830 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
17831 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %lx\n", queue_status
);
17832 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17833 DispatchMessageA(&msg
);
17836 /* Send and process all messages at once */
17837 PostMessageA(test_window
, WM_APP
, 0, 0);
17838 keybd_event(VK_LWIN
, 0, 0, 0);
17839 keybd_event(hotkey_letter
, 0, 0, 0);
17840 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
17841 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
17843 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17845 if (msg
.message
== WM_HOTKEY
)
17847 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
17848 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
17850 DispatchMessageA(&msg
);
17852 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
17854 /* Register same hwnd/id with different key combination */
17855 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
17856 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
17858 /* Previous key combination does not work */
17859 keybd_event(VK_LWIN
, 0, 0, 0);
17860 keybd_event(hotkey_letter
, 0, 0, 0);
17861 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
17862 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
17864 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17865 DispatchMessageA(&msg
);
17866 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
17868 /* New key combination works */
17869 keybd_event(hotkey_letter
, 0, 0, 0);
17870 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
17872 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17874 if (msg
.message
== WM_HOTKEY
)
17876 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
17877 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
17879 DispatchMessageA(&msg
);
17881 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
17883 /* Unregister hotkey properly */
17884 ret
= UnregisterHotKey(test_window
, 5);
17885 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
17887 /* Unregister hotkey again */
17888 SetLastError(0xdeadbeef);
17889 ret
= UnregisterHotKey(test_window
, 5);
17890 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
17891 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17892 "unexpected error %ld\n", GetLastError());
17894 /* Register thread hotkey */
17895 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
17896 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
17898 /* Inject the appropriate key sequence */
17899 keybd_event(VK_LWIN
, 0, 0, 0);
17900 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17902 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
17903 DispatchMessageA(&msg
);
17905 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
17907 keybd_event(hotkey_letter
, 0, 0, 0);
17908 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17910 if (msg
.message
== WM_HOTKEY
)
17912 struct recvd_message message
;
17913 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
17914 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
17915 message
.message
= msg
.message
;
17916 message
.flags
= sent
|wparam
|lparam
;
17917 message
.wParam
= msg
.wParam
;
17918 message
.lParam
= msg
.lParam
;
17919 message
.descr
= "test_hotkey thread message";
17920 add_message(&message
);
17923 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
17924 DispatchMessageA(&msg
);
17926 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
17928 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
17929 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17931 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
17932 DispatchMessageA(&msg
);
17934 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
17936 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
17937 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17939 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
17940 DispatchMessageA(&msg
);
17942 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
17944 /* Search for an ALT + letter combination that hasn't been registered */
17945 for (hotkey_letter
= 0x41; hotkey_letter
<= 0x51; hotkey_letter
++)
17947 SetLastError(0xdeadbeef);
17948 ret
= RegisterHotKey(test_window
, 6, MOD_ALT
, hotkey_letter
);
17956 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
17957 "unexpected error %ld\n", GetLastError());
17961 if (hotkey_letter
== 0x52)
17963 ok(0, "Couldn't find any free ALT + letter combination\n");
17967 keybd_event(VK_LMENU
, 0, 0, 0);
17968 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17969 DispatchMessageA(&msg
);
17970 ok_sequence(WmHotkeyPressALT
, "window hotkey press ALT", TRUE
);
17972 keybd_event(hotkey_letter
, 0, 0, 0);
17973 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17975 if (msg
.message
== WM_HOTKEY
)
17977 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
17978 ok(msg
.lParam
== MAKELPARAM(MOD_ALT
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
17980 DispatchMessageA(&msg
);
17982 ok_sequence(WmHotkeyPressWithALT
, "window hotkey press with ALT", FALSE
);
17984 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
17985 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17986 DispatchMessageA(&msg
);
17987 ok_sequence(WmHotkeyReleaseWithALT
, "window hotkey release with ALT", TRUE
);
17989 keybd_event(VK_LMENU
, 0, KEYEVENTF_KEYUP
, 0);
17990 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
17991 DispatchMessageA(&msg
);
17992 ok_sequence(WmHotkeyReleaseALT
, "window hotkey release ALT", FALSE
);
17994 /* Unregister thread hotkey */
17995 ret
= UnregisterHotKey(NULL
, 5);
17996 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
17998 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
18002 UnregisterHotKey(NULL
, 5);
18003 UnregisterHotKey(test_window
, 5);
18004 UnregisterHotKey(test_window
, 6);
18005 DestroyWindow(test_window
);
18010 static const struct message WmSetFocus_1
[] = {
18011 { HCBT_SETFOCUS
, hook
}, /* child */
18012 { HCBT_ACTIVATE
, hook
}, /* parent */
18013 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18014 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
18015 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
18016 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
18017 { WM_NCACTIVATE
, sent
|parent
},
18018 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
18019 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
18020 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
18021 { HCBT_SETFOCUS
, hook
}, /* parent */
18022 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
18023 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
18024 { WM_KILLFOCUS
, sent
|parent
},
18025 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
18026 { WM_SETFOCUS
, sent
},
18029 static const struct message WmSetFocus_2
[] = {
18030 { HCBT_SETFOCUS
, hook
}, /* parent */
18031 { WM_KILLFOCUS
, sent
},
18032 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
18033 { WM_SETFOCUS
, sent
|parent
},
18036 static const struct message WmSetFocus_3
[] = {
18037 { HCBT_SETFOCUS
, hook
}, /* child */
18041 static void test_SetFocus(void)
18043 HWND parent
, old_parent
, child
, old_focus
, old_active
;
18045 struct wnd_event wnd_event
;
18049 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
18050 ok(wnd_event
.start_event
!= 0, "CreateEvent error %ld\n", GetLastError());
18051 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
18052 ok(hthread
!= 0, "CreateThread error %ld\n", GetLastError());
18053 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
18054 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
18055 CloseHandle(wnd_event
.start_event
);
18057 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
18058 0, 0, 0, 0, 0, 0, 0, NULL
);
18059 ok(parent
!= 0, "failed to create parent window\n");
18060 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
18061 0, 0, 0, 0, parent
, 0, 0, NULL
);
18062 ok(child
!= 0, "failed to create child window\n");
18064 trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
18067 SetActiveWindow(0);
18072 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
18073 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
18075 log_all_parent_messages
++;
18077 old_focus
= SetFocus(child
);
18078 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18079 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
18080 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
18081 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18082 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
18084 old_focus
= SetFocus(parent
);
18085 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18086 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
18087 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
18088 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18089 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18091 SetLastError(0xdeadbeef);
18092 old_focus
= SetFocus((HWND
)0xdeadbeef);
18093 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
18094 "expected ERROR_INVALID_WINDOW_HANDLE, got %ld\n", GetLastError());
18095 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18096 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
18097 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
18098 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18099 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18101 SetLastError(0xdeadbeef);
18102 old_focus
= SetFocus(GetDesktopWindow());
18103 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
18104 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
18105 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18106 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
18107 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
18108 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18109 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18111 SetLastError(0xdeadbeef);
18112 old_focus
= SetFocus(wnd_event
.hwnd
);
18113 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
18114 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
18115 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18116 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
18117 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
18118 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18119 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18121 SetLastError(0xdeadbeef);
18122 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
18123 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
18124 "expected ERROR_INVALID_WINDOW_HANDLE, got %ld\n", GetLastError());
18125 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18126 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
18127 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
18128 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18129 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18131 SetLastError(0xdeadbeef);
18132 old_active
= SetActiveWindow(GetDesktopWindow());
18134 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
18135 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18136 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
18137 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
18138 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18139 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18141 SetLastError(0xdeadbeef);
18142 old_active
= SetActiveWindow(wnd_event
.hwnd
);
18144 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
18145 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18146 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
18147 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
18148 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18149 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18151 SetLastError(0xdeadbeef);
18152 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
18153 ok(ret
, "AttachThreadInput error %ld\n", GetLastError());
18155 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18156 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18161 old_focus
= SetFocus(wnd_event
.hwnd
);
18162 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18163 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
18164 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
18165 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
18167 old_focus
= SetFocus(parent
);
18168 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18169 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
18170 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18171 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18176 old_active
= SetActiveWindow(wnd_event
.hwnd
);
18177 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18178 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
18179 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
18180 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
18182 SetLastError(0xdeadbeef);
18183 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
18184 ok(ret
, "AttachThreadInput error %ld\n", GetLastError());
18186 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
18187 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
18189 old_parent
= SetParent(child
, GetDesktopWindow());
18190 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
18192 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
18193 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
18195 old_focus
= SetFocus(parent
);
18196 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18197 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
18198 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18199 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18204 SetLastError(0xdeadbeef);
18205 old_focus
= SetFocus(child
);
18207 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
18208 broken(GetLastError() == 0) /* XP */ ||
18209 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
18210 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18211 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
18212 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
18213 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18214 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18216 SetLastError(0xdeadbeef);
18217 old_active
= SetActiveWindow(child
);
18218 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
18219 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
18220 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
18221 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
18222 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
18223 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
18225 log_all_parent_messages
--;
18227 DestroyWindow(child
);
18228 DestroyWindow(parent
);
18230 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
18231 ok(ret
, "PostMessage(WM_QUIT) error %ld\n", GetLastError());
18232 ret
= WaitForSingleObject(hthread
, INFINITE
);
18233 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
18234 CloseHandle(hthread
);
18237 static const struct message WmSetLayeredStyle
[] = {
18238 { WM_STYLECHANGING
, sent
},
18239 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
18240 { WM_STYLECHANGED
, sent
},
18241 { WM_GETTEXT
, sent
|defwinproc
|optional
},
18245 static const struct message WmSetLayeredStyle2
[] = {
18246 { WM_STYLECHANGING
, sent
},
18247 { WM_STYLECHANGED
, sent
},
18248 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
18249 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
18250 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
18251 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
18252 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
18253 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
18254 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
18258 static const struct message WmLayeredWinEmptySeq
[] = {
18259 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18263 struct layered_window_info
18272 static DWORD CALLBACK
update_layered_proc( void *param
)
18274 struct layered_window_info
*info
= param
;
18275 POINT src
= { 0, 0 };
18277 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
18278 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
18279 ok( info
->ret
, "failed\n");
18280 SetEvent( info
->event
);
18284 static void test_layered_window(void)
18295 struct layered_window_info info
;
18297 if (!pUpdateLayeredWindow
)
18299 win_skip( "UpdateLayeredWindow not supported\n" );
18303 hdc
= CreateCompatibleDC( 0 );
18304 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
18305 SelectObject( hdc
, bmp
);
18307 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
18308 100, 100, 300, 300, 0, 0, 0, NULL
);
18309 ok( hwnd
!= 0, "failed to create window\n" );
18310 ShowWindow( hwnd
, SW_SHOWNORMAL
);
18311 UpdateWindow( hwnd
);
18315 GetWindowRect( hwnd
, &rect
);
18316 GetClientRect( hwnd
, &client
);
18317 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
18318 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
18321 pos
.x
= pos
.y
= 300;
18322 size
.cx
= size
.cy
= 250;
18323 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
18324 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
18325 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
18326 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
18327 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
18329 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
18330 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
18331 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
18332 GetWindowRect( hwnd
, &rect
);
18333 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
18334 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
18335 GetClientRect( hwnd
, &rect
);
18336 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
18337 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
18341 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
18342 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
18343 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
18344 GetWindowRect( hwnd
, &rect
);
18345 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
18346 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
18347 GetClientRect( hwnd
, &rect
);
18348 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
18349 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
18351 SetWindowLongA( hwnd
, GWL_STYLE
,
18352 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
18353 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
18357 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
18358 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
18359 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
18360 GetWindowRect( hwnd
, &rect
);
18361 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
18362 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
18363 GetClientRect( hwnd
, &rect
);
18364 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
18365 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
18366 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
18369 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
18370 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
18371 ok( GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == ERROR_MR_MID_NOT_FOUND
) ||
18372 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win7 */, "wrong error %lu\n", GetLastError() );
18375 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
18376 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
18377 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
18379 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
18380 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
18381 GetWindowRect( hwnd
, &rect
);
18382 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
18383 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
18384 GetClientRect( hwnd
, &rect
);
18385 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
18386 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
18387 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
18389 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
18392 info
.size
.cx
= 250;
18393 info
.size
.cy
= 300;
18394 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
18396 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
18397 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
18398 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
18399 WaitForSingleObject( thread
, 1000 );
18400 CloseHandle( thread
);
18401 GetWindowRect( hwnd
, &rect
);
18402 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
18403 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
18404 GetClientRect( hwnd
, &rect
);
18405 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
18406 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
18407 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
18409 DestroyWindow( hwnd
);
18411 DeleteObject( bmp
);
18414 static HMENU hpopupmenu
;
18416 static LRESULT WINAPI
minimize_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
18420 if (ignore_message( message
)) return 0;
18421 ret
= MsgCheckProc( FALSE
, hwnd
, message
, wParam
, lParam
);
18425 ShowWindow(hwnd
, SW_MINIMIZE
);
18435 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
18437 if (ignore_message( message
)) return 0;
18441 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
18445 case WM_INITMENUPOPUP
:
18446 case WM_UNINITMENUPOPUP
:
18447 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %Ix\n", hpopupmenu
, wParam
);
18449 case WM_CAPTURECHANGED
:
18450 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %Ix\n", lParam
);
18454 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
18457 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
18459 if (ignore_message( message
)) return 0;
18462 case WM_ENTERMENULOOP
:
18463 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
18467 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
18470 static void test_TrackPopupMenu(void)
18476 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
18479 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
18481 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
18483 hpopupmenu
= CreatePopupMenu();
18484 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
18486 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
18487 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
18491 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
18492 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
18493 ok(ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError());
18495 /* Test popup closing with an ESC-press */
18497 PostMessageW(hwnd
, WM_KEYDOWN
, VK_ESCAPE
, 0);
18498 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
18499 ok(ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError());
18500 PostQuitMessage(0);
18502 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
18504 TranslateMessage(&msg
);
18505 DispatchMessageA(&msg
);
18507 ok_sequence(WmTrackPopupMenuEsc
, "TrackPopupMenuEsc", FALSE
); /* Shouldn't get any message */
18509 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
18513 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
18514 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
18515 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
18517 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)minimize_popup_proc
);
18519 /* set cursor over the window, otherwise the WM_CANCELMODE message may not always be sent */
18520 SetCursorPos( 0, 0 );
18521 ShowWindow( hwnd
, SW_SHOW
);
18525 SetTimer( hwnd
, TIMER_ID
, 500, NULL
);
18526 ret
= TrackPopupMenu( hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
18527 ok_sequence( WmTrackPopupMenuMinimizeWindow
, "TrackPopupMenuMinimizeWindow", TRUE
);
18528 ok( ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError() );
18529 KillTimer( hwnd
, TIMER_ID
);
18530 ShowWindow( hwnd
, SW_RESTORE
);
18532 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
18538 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
18539 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
18540 ok(ret
== 1, "TrackPopupMenuCapture failed with error %li\n", GetLastError());
18542 DestroyMenu(hpopupmenu
);
18543 DestroyWindow(hwnd
);
18546 static void test_TrackPopupMenuEmpty(void)
18551 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
18554 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
18556 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
18558 hpopupmenu
= CreatePopupMenu();
18559 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
18563 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
18564 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
18565 ok(ret
== 0, "TrackPopupMenu succeeded\n");
18567 DestroyMenu(hpopupmenu
);
18568 DestroyWindow(hwnd
);
18571 static const struct message send_message_1
[] = {
18572 { WM_USER
+2, sent
|wparam
|lparam
, 0, 0 },
18573 { WM_USER
, sent
|wparam
|lparam
, 0, 0 },
18576 static const struct message send_message_2
[] = {
18577 { WM_USER
+4, sent
|wparam
|lparam
, 0, 0 },
18580 static const struct message send_message_3
[] = {
18581 { WM_USER
+3, sent
|wparam
|lparam
, 0, 0 },
18582 { WM_USER
+1, sent
|wparam
|lparam
, 0, 0 },
18586 static DWORD WINAPI
SendMessage_thread_1(void *param
)
18588 struct wnd_event
*wnd_event
= param
;
18590 trace("thread: starting\n");
18591 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
18593 trace("thread: call PostMessage\n");
18594 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
18596 trace("thread: call PostMessage\n");
18597 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
18599 trace("thread: call SendMessage\n");
18600 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
18601 SetEvent(wnd_event
->stop_event
);
18603 trace("thread: call SendMessage\n");
18604 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
18609 static DWORD WINAPI
SendMessage_thread_2(void *param
)
18611 struct wnd_event
*wnd_event
= param
;
18613 trace("thread: starting\n");
18614 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
18616 trace("thread: call PostMessage\n");
18617 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
18619 trace("thread: call PostMessage\n");
18620 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
18622 /* this leads to sending an internal message under Wine */
18623 trace("thread: call SetParent\n");
18624 SetParent(wnd_event
->hwnd
, wnd_event
->hwnd
);
18626 trace("thread: call SendMessage\n");
18627 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
18628 SetEvent(wnd_event
->stop_event
);
18630 trace("thread: call SendMessage\n");
18631 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
18636 static void test_SendMessage_other_thread(int thread_n
)
18638 DWORD qs_all_input
= QS_ALLINPUT
& ~QS_RAWINPUT
;
18640 struct wnd_event wnd_event
;
18644 wnd_event
.start_event
= CreateEventA(NULL
, 0, 0, NULL
);
18645 wnd_event
.stop_event
= CreateEventA(NULL
, 0, 0, NULL
);
18647 wnd_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
18648 100, 100, 200, 200, 0, 0, 0, NULL
);
18649 ok(wnd_event
.hwnd
!= 0, "CreateWindowEx failed\n");
18651 hthread
= CreateThread(NULL
, 0, thread_n
== 1 ? SendMessage_thread_1
: SendMessage_thread_2
, &wnd_event
, 0, &tid
);
18652 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
18653 CloseHandle(hthread
);
18658 ret
= GetQueueStatus(QS_SENDMESSAGE
);
18659 ok(ret
== 0, "wrong status %08lx\n", ret
);
18661 SetEvent(wnd_event
.start_event
);
18663 /* wait for other thread's SendMessage */
18666 ret
= GetQueueStatus(QS_SENDMESSAGE
);
18667 if (ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
)) break;
18671 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
18672 ok(ret
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08lx\n", ret
);
18674 trace("main: call GetMessage\n");
18675 GetMessageA(&msg
, 0, 0, 0);
18676 ok(msg
.message
== WM_USER
, "expected WM_USER, got %04x\n", msg
.message
);
18677 DispatchMessageA(&msg
);
18678 ok_sequence(send_message_1
, "SendMessage from other thread 1", thread_n
== 2);
18680 ret
= WaitForSingleObject(wnd_event
.stop_event
, 100);
18681 todo_wine_if (thread_n
== 2)
18682 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed, ret:%lx\n", ret
);
18684 /* intentionally yield */
18685 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
18687 trace("main: call SendMessage\n");
18688 SendMessageA(wnd_event
.hwnd
, WM_USER
+4, 0, 0);
18689 ok_sequence(send_message_2
, "SendMessage from other thread 2", FALSE
);
18691 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
18692 ok(ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08lx\n", ret
);
18694 trace("main: call PeekMessage\n");
18695 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should not fail\n");
18696 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
18697 DispatchMessageA(&msg
);
18698 ok_sequence(send_message_3
, "SendMessage from other thread 3", thread_n
== 2);
18700 /* intentionally yield */
18701 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
18703 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
18704 /* FIXME: remove once Wine is fixed */
18705 todo_wine_if (thread_n
== 2)
18706 ok(ret
== 0, "wrong status %08lx\n", ret
);
18708 trace("main: call PeekMessage\n");
18709 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should fail\n");
18710 ok_sequence(WmEmptySeq
, "SendMessage from other thread 5", thread_n
== 2);
18712 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
18713 ok(ret
== 0, "wrong status %08lx\n", ret
);
18715 trace("main: call DestroyWindow\n");
18716 DestroyWindow(msg
.hwnd
);
18721 CloseHandle(wnd_event
.start_event
);
18722 CloseHandle(wnd_event
.stop_event
);
18725 static LRESULT CALLBACK
insendmessage_wnd_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
18727 DWORD flags
= InSendMessageEx( NULL
);
18733 ok( flags
== ISMEX_SEND
, "wrong flags %lx\n", flags
);
18734 ok( InSendMessage(), "InSendMessage returned false\n" );
18735 ret
= ReplyMessage( msg
);
18736 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
18737 flags
= InSendMessageEx( NULL
);
18738 ok( flags
== (ISMEX_SEND
| ISMEX_REPLIED
), "wrong flags %lx\n", flags
);
18739 ok( InSendMessage(), "InSendMessage returned false\n" );
18742 ok( flags
== ISMEX_NOTIFY
, "wrong flags %lx\n", flags
);
18743 ok( InSendMessage(), "InSendMessage returned false\n" );
18744 ret
= ReplyMessage( msg
);
18745 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
18746 flags
= InSendMessageEx( NULL
);
18747 ok( flags
== ISMEX_NOTIFY
, "wrong flags %lx\n", flags
);
18748 ok( InSendMessage(), "InSendMessage returned false\n" );
18751 ok( flags
== ISMEX_CALLBACK
, "wrong flags %lx\n", flags
);
18752 ok( InSendMessage(), "InSendMessage returned false\n" );
18753 ret
= ReplyMessage( msg
);
18754 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
18755 flags
= InSendMessageEx( NULL
);
18756 ok( flags
== (ISMEX_CALLBACK
| ISMEX_REPLIED
) || flags
== ISMEX_SEND
, "wrong flags %lx\n", flags
);
18757 ok( InSendMessage(), "InSendMessage returned false\n" );
18760 ok( flags
== ISMEX_NOSEND
, "wrong flags %lx\n", flags
);
18761 ok( !InSendMessage(), "InSendMessage returned true\n" );
18762 ret
= ReplyMessage( msg
);
18763 ok( !ret
, "ReplyMessage succeeded\n" );
18767 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
18770 static void CALLBACK
msg_callback( HWND hwnd
, UINT msg
, ULONG_PTR arg
, LRESULT result
)
18772 ok( msg
== WM_USER
+ 2, "wrong msg %x\n", msg
);
18773 ok( result
== WM_USER
+ 2, "wrong result %Ix\n", result
);
18776 static DWORD WINAPI
send_message_thread( void *arg
)
18780 SendMessageA( win
, WM_USER
, 0, 0 );
18781 SendNotifyMessageA( win
, WM_USER
+ 1, 0, 0 );
18782 SendMessageCallbackA( win
, WM_USER
+ 2, 0, 0, msg_callback
, 0 );
18783 PostMessageA( win
, WM_USER
+ 3, 0, 0 );
18784 PostMessageA( win
, WM_QUIT
, 0, 0 );
18788 static void test_InSendMessage(void)
18796 memset(&cls
, 0, sizeof(cls
));
18797 cls
.lpfnWndProc
= insendmessage_wnd_proc
;
18798 cls
.hInstance
= GetModuleHandleA(NULL
);
18799 cls
.lpszClassName
= "InSendMessage_test";
18800 RegisterClassA(&cls
);
18802 win
= CreateWindowA( "InSendMessage_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
18803 ok( win
!= NULL
, "CreateWindow failed: %ld\n", GetLastError() );
18805 thread
= CreateThread( NULL
, 0, send_message_thread
, win
, 0, &tid
);
18806 ok( thread
!= NULL
, "CreateThread failed: %ld\n", GetLastError() );
18808 while (GetMessageA(&msg
, NULL
, 0, 0)) DispatchMessageA( &msg
);
18810 ok( WaitForSingleObject( thread
, 30000 ) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
18811 CloseHandle( thread
);
18813 DestroyWindow( win
);
18814 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL
) );
18817 static const struct message DoubleSetCaptureSeq
[] =
18819 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18820 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18821 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18822 { WM_CAPTURECHANGED
, sent
},
18826 static void test_DoubleSetCapture(void)
18830 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture",
18831 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
18832 100, 100, 200, 200, 0, 0, 0, NULL
);
18833 ok (hwnd
!= 0, "Failed to create overlapped window\n");
18835 ShowWindow( hwnd
, SW_SHOW
);
18836 UpdateWindow( hwnd
);
18840 SetCapture( hwnd
);
18841 SetCapture( hwnd
);
18842 ok_sequence(DoubleSetCaptureSeq
, "SetCapture( hwnd ) twice", FALSE
);
18844 DestroyWindow(hwnd
);
18847 static const struct message WmRestoreMinimizedSeq
[] =
18849 { HCBT_ACTIVATE
, hook
},
18850 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18851 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
18852 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
18853 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
18854 { WM_NCACTIVATE
, sent
|wparam
, 0x200001 },
18855 { WM_GETTEXT
, sent
|defwinproc
|optional
},
18856 { WM_ACTIVATE
, sent
|wparam
, 0x200001 }, /* Note that activate messages are after WM_WINDOWPOSCHANGED and before WM_SYSCOMMAND */
18857 { HCBT_KEYSKIPPED
, hook
|optional
},
18858 { WM_SYSKEYUP
, sent
|optional
},
18859 { WM_SYSCOMMAND
, sent
|wparam
, SC_RESTORE
},
18860 { HCBT_SYSCOMMAND
, hook
|wparam
, SC_RESTORE
},
18861 { HCBT_SYSCOMMAND
, hook
|wparam
|optional
, SC_RESTORE
},
18862 { HCBT_MINMAX
, hook
},
18863 { HCBT_MINMAX
, hook
|optional
},
18864 { WM_QUERYOPEN
, sent
|defwinproc
},
18865 { WM_QUERYOPEN
, sent
|optional
},
18866 { WM_GETTEXT
, sent
|defwinproc
|optional
},
18867 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
18868 { WM_GETMINMAXINFO
, sent
|defwinproc
},
18869 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
18870 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18871 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
18872 { WM_GETTEXT
, sent
|defwinproc
|optional
},
18873 { WM_ERASEBKGND
, sent
|defwinproc
},
18874 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
18875 { WM_MOVE
, sent
|defwinproc
},
18876 { WM_SIZE
, sent
|defwinproc
},
18877 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18878 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|winevent_hook_todo
, 0, 0 },
18879 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
18880 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
18881 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
18882 { HCBT_SETFOCUS
, hook
},
18883 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
18884 { WM_SETFOCUS
, sent
|defwinproc
},
18885 { WM_ACTIVATE
, sent
|wparam
|defwinproc
, 1 },
18886 { WM_PAINT
, sent
| optional
},
18887 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
18888 { HCBT_KEYSKIPPED
, hook
|optional
},
18889 { WM_KEYUP
, sent
|optional
},
18890 { HCBT_KEYSKIPPED
, hook
|optional
},
18891 { WM_SYSKEYUP
, sent
|optional
},
18892 { HCBT_KEYSKIPPED
, hook
|optional
},
18893 { WM_KEYUP
, sent
|optional
},
18894 { HCBT_KEYSKIPPED
, hook
|optional
},
18895 { WM_SYSKEYUP
, sent
|optional
},
18896 { HCBT_KEYSKIPPED
, hook
|optional
},
18897 { WM_KEYUP
, sent
|optional
},
18898 { WM_PAINT
, sent
| optional
},
18902 static void test_restore_messages(void)
18908 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, 100,
18909 100, 200, 200, 0, 0, 0, NULL
);
18910 ok (hwnd
!= 0, "Failed to create overlapped window\n");
18911 SetForegroundWindow(hwnd
);
18912 ShowWindow(hwnd
, SW_MINIMIZE
);
18916 for (i
= 0; i
< 5; i
++)
18918 /* Send Alt+Tab to restore test window from minimized state */
18919 ip
.type
= INPUT_KEYBOARD
;
18920 ip
.ki
.wVk
= VK_MENU
;
18921 SendInput(1, &ip
, sizeof(INPUT
));
18922 ip
.ki
.wVk
= VK_TAB
;
18923 SendInput(1, &ip
, sizeof(INPUT
));
18924 ip
.ki
.wVk
= VK_MENU
;
18925 ip
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
18926 SendInput(1, &ip
, sizeof(INPUT
));
18927 ip
.ki
.wVk
= VK_TAB
;
18928 ip
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
18929 SendInput(1, &ip
, sizeof(INPUT
));
18931 if (!IsIconic(hwnd
))
18935 if (IsIconic(hwnd
))
18937 skip("Alt+Tab failed to bring up test window.\n");
18940 ok_sequence(WmRestoreMinimizedSeq
, "Restore minimized window", TRUE
);
18943 DestroyWindow(hwnd
);
18946 static void test_invalid_window(void)
18951 SetLastError(0xdeadbeef);
18952 ret
= GetMessageA(&msg
, (HWND
)0xdeadbeef, 0, 0);
18953 ok(ret
== -1, "wrong ret %d\n", ret
);
18954 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError());
18956 SetLastError(0xdeadbeef);
18957 ret
= PeekMessageA(&msg
, (HWND
)0xdeadbeef, 0, 0, PM_REMOVE
);
18958 ok(!ret
, "wrong ret %d\n", ret
);
18959 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError());
18962 static void test_button_style(void)
18964 DWORD type
, expected_type
;
18969 for (i
= BS_PUSHBUTTON
; i
<= BS_DEFCOMMANDLINK
; ++i
)
18971 button
= CreateWindowA(WC_BUTTONA
, "test", i
, 0, 0, 50, 50, NULL
, 0, 0, NULL
);
18972 ok(button
!= NULL
, "Expected button not null.\n");
18974 type
= GetWindowLongW(button
, GWL_STYLE
) & BS_TYPEMASK
;
18975 expected_type
= (i
== BS_USERBUTTON
? BS_PUSHBUTTON
: i
);
18976 ok(type
== expected_type
, "Expected type %#lx, got %#lx.\n", expected_type
, type
);
18978 for (j
= BS_PUSHBUTTON
; j
<= BS_DEFCOMMANDLINK
; ++j
)
18980 ret
= SendMessageA(button
, BM_SETSTYLE
, j
, FALSE
);
18981 ok(ret
== 0, "Expected %#x, got %#Ix.\n", 0, ret
);
18983 type
= GetWindowLongW(button
, GWL_STYLE
) & BS_TYPEMASK
;
18986 ok(type
== expected_type
, "Original type %#lx, expected new type %#lx, got %#lx.\n", i
,
18987 expected_type
, type
);
18989 DestroyWindow(button
);
18997 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
19000 argc
= winetest_get_mainargs( &test_argv
);
19004 /* Child process. */
19005 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
19006 do_wait_idle_child( arg
);
19010 InitializeCriticalSection( &sequence_cs
);
19014 if (!RegisterWindowClasses()) assert(0);
19016 if (pSetWinEventHook
)
19018 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
19019 GetModuleHandleA(0), win_event_proc
,
19020 0, GetCurrentThreadId(),
19021 WINEVENT_INCONTEXT
);
19022 if (pIsWinEventHookInstalled
&& hEvent_hook
)
19025 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
19026 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
19029 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
19031 cbt_hook_thread_id
= winevent_hook_thread_id
= GetCurrentThreadId();
19032 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
19033 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
19036 test_SendMessage_other_thread(1);
19037 test_SendMessage_other_thread(2);
19038 test_InSendMessage();
19041 test_PostMessage();
19044 test_PeekMessage();
19045 test_PeekMessage2();
19046 test_PeekMessage3();
19047 test_WaitForInputIdle( test_argv
[0] );
19048 test_scrollwindowex();
19050 test_setwindowpos();
19052 invisible_parent_tests();
19053 test_mdi_messages();
19054 test_button_messages();
19055 test_button_bm_get_set_image();
19056 test_button_style();
19057 test_autoradio_BM_CLICK();
19058 test_autoradio_kbd_move();
19059 test_static_messages();
19060 test_listbox_messages();
19061 test_combobox_messages();
19062 test_wmime_keydown_message();
19063 test_paint_messages();
19064 test_interthread_messages();
19065 test_message_conversion();
19066 test_accelerators();
19068 test_timers_no_wnd();
19069 test_timers_exceptions();
19073 test_recursive_hook();
19075 test_DestroyWindow();
19076 test_DispatchMessage();
19077 test_SendMessageTimeout();
19078 test_edit_messages();
19079 test_quit_message();
19080 test_notify_message();
19081 test_SetActiveWindow();
19082 test_restore_messages();
19083 test_invalid_window();
19084 test_menu_messages();
19085 test_paintingloop();
19087 if (!pTrackMouseEvent
)
19088 win_skip("TrackMouseEvent is not available\n");
19090 test_TrackMouseEvent();
19092 test_SetWindowRgn();
19094 test_dialog_messages();
19096 test_nullCallback();
19097 test_dbcs_wm_char();
19098 test_unicode_wm_char();
19100 test_desktop_winproc();
19101 test_clipboard_viewers();
19104 test_layered_window();
19105 test_TrackPopupMenu();
19106 test_TrackPopupMenuEmpty();
19107 test_DoubleSetCapture();
19108 /* keep it the last test, under Windows it tends to break the tests
19109 * which rely on active/foreground windows being correct.
19111 test_SetForegroundWindow();
19113 UnhookWindowsHookEx(hCBT_hook
);
19114 if (pUnhookWinEvent
&& hEvent_hook
)
19116 ret
= pUnhookWinEvent(hEvent_hook
);
19117 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
19118 SetLastError(0xdeadbeef);
19119 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
19120 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
19121 GetLastError() == 0xdeadbeef, /* Win9x */
19122 "unexpected error %ld\n", GetLastError());
19124 DeleteCriticalSection( &sequence_cs
);