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
24 #define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */
25 #define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */
40 #include "wine/test.h"
42 #define MDI_FIRST_CHILD_ID 2004
44 /* undocumented SWP flags - from SDK 3.1 */
45 #define SWP_NOCLIENTSIZE 0x0800
46 #define SWP_NOCLIENTMOVE 0x1000
47 #define SWP_STATECHANGED 0x8000
49 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
52 #define WM_KEYF1 0x004d
56 #define WM_SYSTIMER 0x0118
59 #define WND_PARENT_ID 1
60 #define WND_POPUP_ID 2
61 #define WND_CHILD_ID 3
63 #ifndef WM_LBTRACKPOINT
64 #define WM_LBTRACKPOINT 0x0131
69 #elif defined __x86_64__
73 #elif defined __aarch64__
79 static BOOL (WINAPI
*pActivateActCtx
)(HANDLE
,ULONG_PTR
*);
80 static HANDLE (WINAPI
*pCreateActCtxW
)(PCACTCTXW
);
81 static BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
,ULONG_PTR
);
82 static BOOL (WINAPI
*pGetCurrentActCtx
)(HANDLE
*);
83 static BOOL (WINAPI
*pQueryActCtxW
)(DWORD
,HANDLE
,void*,ULONG
,void*,SIZE_T
,SIZE_T
*);
84 static void (WINAPI
*pReleaseActCtx
)(HANDLE
);
86 /* encoded DRAWITEMSTRUCT into an LPARAM */
93 UINT type
: 4; /* ODT_* flags */
94 UINT ctl_id
: 4; /* Control ID */
95 UINT item_id
: 4; /* Menu item ID */
96 UINT action
: 4; /* ODA_* flags */
97 UINT state
: 16; /* ODS_* flags */
103 /* encoded MEASUREITEMSTRUCT into a WPARAM */
117 } MEASURE_ITEM_STRUCT
;
119 static BOOL test_DestroyWindow_flag
;
120 static HWINEVENTHOOK hEvent_hook
;
121 static HHOOK hKBD_hook
;
122 static HHOOK hCBT_hook
;
123 static DWORD cbt_hook_thread_id
;
125 static const WCHAR testWindowClassW
[] =
126 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
128 static LRESULT WINAPI
ParentMsgCheckProcA(HWND
, UINT
, WPARAM
, LPARAM
);
131 FIXME: add tests for these
132 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
133 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
134 WS_THICKFRAME: thick border
135 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
136 WS_BORDER (default for overlapped windows): single black border
137 none (default for child (and popup?) windows): no border
155 UINT message
; /* the WM_* code */
156 msg_flags_t flags
; /* message props */
157 WPARAM wParam
; /* expected value of wParam */
158 LPARAM lParam
; /* expected value of lParam */
159 WPARAM wp_mask
; /* mask for wParam checks */
160 LPARAM lp_mask
; /* mask for lParam checks */
163 struct recvd_message
{
164 UINT message
; /* the WM_* code */
165 msg_flags_t flags
; /* message props */
166 HWND hwnd
; /* window that received the message */
167 WPARAM wParam
; /* expected value of wParam */
168 LPARAM lParam
; /* expected value of lParam */
169 int line
; /* source line where logged */
170 const char *descr
; /* description for trace output */
171 char output
[512]; /* trace output */
174 /* Empty message sequence */
175 static const struct message WmEmptySeq
[] =
179 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
180 static const struct message WmCreateOverlappedSeq
[] = {
181 { HCBT_CREATEWND
, hook
},
182 { WM_GETMINMAXINFO
, sent
},
183 { WM_NCCREATE
, sent
},
184 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
185 { 0x0093, sent
|defwinproc
|optional
},
186 { 0x0094, sent
|defwinproc
|optional
},
187 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
189 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
192 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
193 * for a not visible overlapped window.
195 static const struct message WmSWP_ShowOverlappedSeq
[] = {
196 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
197 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
198 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
199 { WM_GETTEXT
, sent
|defwinproc
|optional
},
200 { WM_ERASEBKGND
, sent
|optional
},
201 { HCBT_ACTIVATE
, hook
},
202 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
203 { WM_NOTIFYFORMAT
, sent
|optional
},
204 { WM_QUERYUISTATE
, sent
|optional
},
205 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
206 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
207 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
208 { WM_NCACTIVATE
, sent
},
209 { WM_GETTEXT
, sent
|defwinproc
|optional
},
210 { WM_ACTIVATE
, sent
|wparam
, 1 },
211 { HCBT_SETFOCUS
, hook
},
212 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
213 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
214 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
215 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
216 { WM_GETTEXT
, sent
|optional
},
217 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
218 { WM_GETTEXT
, sent
|defwinproc
|optional
},
219 { WM_ERASEBKGND
, sent
|optional
},
220 /* Win9x adds SWP_NOZORDER below */
221 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
222 { WM_GETTEXT
, sent
|optional
},
223 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
224 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
225 { WM_ERASEBKGND
, sent
|optional
},
226 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
227 { WM_SYNCPAINT
, sent
|optional
},
228 { WM_GETTITLEBARINFOEX
, sent
|optional
},
229 { WM_PAINT
, sent
|optional
},
230 { WM_NCPAINT
, sent
|beginpaint
|optional
},
231 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
232 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
235 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
236 * for a visible overlapped window.
238 static const struct message WmSWP_HideOverlappedSeq
[] = {
239 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
240 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
241 { HCBT_ACTIVATE
, hook
|optional
},
242 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
243 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
244 { WM_NCACTIVATE
, sent
|optional
},
245 { WM_ACTIVATE
, sent
|optional
},
246 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
250 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
251 * for a visible overlapped window.
253 static const struct message WmSWP_ResizeSeq
[] = {
254 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
255 { WM_GETMINMAXINFO
, sent
|defwinproc
},
256 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
257 { WM_NCPAINT
, sent
|optional
},
258 { WM_GETTEXT
, sent
|defwinproc
|optional
},
259 { WM_ERASEBKGND
, sent
|optional
},
260 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
261 { WM_SIZE
, sent
|defwinproc
|optional
},
262 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
263 { WM_NCPAINT
, sent
|optional
},
264 { WM_GETTEXT
, sent
|defwinproc
|optional
},
265 { WM_ERASEBKGND
, sent
|optional
},
266 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
267 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
271 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
272 * for a visible popup window.
274 static const struct message WmSWP_ResizePopupSeq
[] = {
275 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
276 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* Win9x */
277 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
278 { WM_NCPAINT
, sent
|optional
},
279 { WM_GETTEXT
, sent
|defwinproc
|optional
},
280 { WM_ERASEBKGND
, sent
|optional
},
281 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
282 { WM_SIZE
, sent
|defwinproc
|wparam
|optional
, SIZE_RESTORED
},
283 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
284 { WM_NCPAINT
, sent
|optional
},
285 { WM_GETTEXT
, sent
|defwinproc
|optional
},
286 { WM_ERASEBKGND
, sent
|optional
},
287 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
291 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
292 * for a visible overlapped window.
294 static const struct message WmSWP_MoveSeq
[] = {
295 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
},
296 { WM_NCPAINT
, sent
|optional
},
297 { WM_GETTEXT
, sent
|defwinproc
|optional
},
298 { WM_ERASEBKGND
, sent
|optional
},
299 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
300 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
301 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
304 /* Resize with SetWindowPos(SWP_NOZORDER)
305 * for a visible overlapped window
306 * SWP_NOZORDER is stripped by the logging code
308 static const struct message WmSWP_ResizeNoZOrder
[] = {
309 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
},
310 { WM_GETMINMAXINFO
, sent
|defwinproc
},
311 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
312 { WM_NCPAINT
, sent
|optional
},
313 { WM_GETTEXT
, sent
|defwinproc
|optional
},
314 { WM_ERASEBKGND
, sent
|optional
},
315 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
, 0,
316 SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
317 { WM_MOVE
, sent
|defwinproc
|optional
},
318 { WM_SIZE
, sent
|defwinproc
|optional
},
319 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
320 { WM_NCPAINT
, sent
|optional
}, /* Win9x doesn't send it */
321 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
322 { WM_ERASEBKGND
, sent
|optional
}, /* Win9x doesn't send it */
323 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
324 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
328 /* Switch visible mdi children */
329 static const struct message WmSwitchChild
[] = {
330 /* Switch MDI child */
331 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
332 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 1st MDI child */
333 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
334 { WM_CHILDACTIVATE
, sent
},/* in the 1st MDI child */
335 /* Deactivate 2nd MDI child */
336 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
337 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
338 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
339 /* Preparing for maximize and maximize the 1st MDI child */
340 { WM_GETMINMAXINFO
, sent
|defwinproc
}, /* in the 1st MDI child */
341 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
}, /* in the 1st MDI child */
342 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
343 { WM_CHILDACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
344 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 1st MDI child */
345 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
}, /* in the 1st MDI child */
346 /* Lock redraw 2nd MDI child */
347 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
348 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
349 /* Restore 2nd MDI child */
350 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},/* in the 2nd MDI child */
351 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
352 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
353 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 2nd MDI child */
354 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
}, /* in the 2nd MDI child */
355 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
356 /* Redraw 2nd MDI child */
357 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
358 /* Redraw MDI frame */
359 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},/* in MDI frame */
360 { WM_NCCALCSIZE
, sent
|wparam
, 1 },/* in MDI frame */
361 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in MDI frame */
362 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in MDI frame */
363 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
364 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
365 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
366 { HCBT_SETFOCUS
, hook
},
367 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
368 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },/* in the 1st MDI child */
369 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
370 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
371 { WM_SETFOCUS
, sent
},/* in the MDI client */
372 { HCBT_SETFOCUS
, hook
},
373 { WM_KILLFOCUS
, sent
},/* in the MDI client */
374 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
375 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 }, /* in the 1st MDI child */
376 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
377 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
378 { WM_MDIACTIVATE
, sent
|defwinproc
},/* in the 1st MDI child */
379 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 1st MDI child */
383 /* Switch visible not maximized mdi children */
384 static const struct message WmSwitchNotMaximizedChild
[] = {
385 /* Switch not maximized MDI child */
386 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
387 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 2nd MDI child */
388 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
389 { WM_CHILDACTIVATE
, sent
},/* in the 2nd MDI child */
390 /* Deactivate 1st MDI child */
391 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
392 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
393 /* Activate 2nd MDI child */
394 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
}, /* in the 2nd MDI child */
395 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 2nd MDI child */
396 { HCBT_SETFOCUS
, hook
}, /* in the 1st MDI child */
397 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
398 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
399 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
400 { WM_SETFOCUS
, sent
, 0 }, /* in the MDI client */
401 { HCBT_SETFOCUS
, hook
},
402 { WM_KILLFOCUS
, sent
}, /* in the MDI client */
403 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
404 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
405 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
406 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
407 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 2nd MDI child */
412 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
413 SWP_NOZORDER|SWP_FRAMECHANGED)
414 * for a visible overlapped window with WS_CLIPCHILDREN style set.
416 static const struct message WmSWP_FrameChanged_clip
[] = {
417 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
418 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
419 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
420 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
421 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
422 { WM_NCPAINT
, sent
}, /* wparam != 1 */
423 { WM_ERASEBKGND
, sent
},
424 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
425 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
429 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
430 SWP_NOZORDER|SWP_FRAMECHANGED)
431 * for a visible overlapped window.
433 static const struct message WmSWP_FrameChangedDeferErase
[] = {
434 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
435 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
436 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
437 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
438 { WM_PAINT
, sent
|parent
|optional
},
439 { WM_NCPAINT
, sent
|beginpaint
|parent
|optional
}, /* wparam != 1 */
440 { WM_GETTEXT
, sent
|beginpaint
|parent
|defwinproc
|optional
},
442 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
443 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
447 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
448 SWP_NOZORDER|SWP_FRAMECHANGED)
449 * for a visible overlapped window without WS_CLIPCHILDREN style set.
451 static const struct message WmSWP_FrameChanged_noclip
[] = {
452 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
453 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
454 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
455 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
456 { WM_ERASEBKGND
, sent
|parent
|optional
},
457 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
458 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
460 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
461 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
465 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
466 static const struct message WmShowOverlappedSeq
[] = {
467 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
468 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
469 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
470 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
471 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
472 { WM_GETTEXT
, sent
|defwinproc
|optional
},
473 { WM_ERASEBKGND
, sent
|optional
},
474 { HCBT_ACTIVATE
, hook
|optional
},
475 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
476 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
477 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
478 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
479 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
480 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
481 { WM_GETTEXT
, sent
|defwinproc
|optional
},
482 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
483 { HCBT_SETFOCUS
, hook
|optional
},
484 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
485 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
486 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
487 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
488 { WM_GETTEXT
, sent
|optional
},
489 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
490 { WM_GETTEXT
, sent
|defwinproc
|optional
},
491 { WM_ERASEBKGND
, sent
|optional
},
492 /* Win9x adds SWP_NOZORDER below */
493 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
494 { WM_NCCALCSIZE
, sent
|optional
},
495 { WM_GETTEXT
, sent
|optional
},
496 { WM_NCPAINT
, sent
|optional
},
497 { WM_ERASEBKGND
, sent
|optional
},
498 { WM_SYNCPAINT
, sent
|optional
},
499 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
500 * messages. Does that mean that CreateWindow doesn't set initial
501 * window dimensions for overlapped windows?
506 { WM_PAINT
, sent
|optional
},
507 { WM_NCPAINT
, sent
|beginpaint
|optional
},
510 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
511 static const struct message WmShowMaxOverlappedSeq
[] = {
512 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
513 { WM_GETMINMAXINFO
, sent
},
514 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
515 { WM_GETMINMAXINFO
, sent
|defwinproc
},
516 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
517 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
518 { HCBT_ACTIVATE
, hook
|optional
},
519 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
520 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
521 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
522 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
523 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
524 { WM_GETTEXT
, sent
|defwinproc
|optional
},
525 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
526 { HCBT_SETFOCUS
, hook
|optional
},
527 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
528 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
529 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
530 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
531 { WM_GETTEXT
, sent
|optional
},
532 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
533 { WM_GETTEXT
, sent
|defwinproc
|optional
},
534 { WM_ERASEBKGND
, sent
|optional
},
535 /* Win9x adds SWP_NOZORDER below */
536 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
537 { WM_MOVE
, sent
|defwinproc
},
538 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
539 { WM_GETTEXT
, sent
|optional
},
540 { WM_NCCALCSIZE
, sent
|optional
},
541 { WM_NCPAINT
, sent
|optional
},
542 { WM_ERASEBKGND
, sent
|optional
},
543 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
544 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
545 { WM_SYNCPAINT
, sent
|optional
},
546 { WM_GETTITLEBARINFOEX
, sent
|optional
},
547 { WM_PAINT
, sent
|optional
},
548 { WM_NCPAINT
, sent
|beginpaint
|optional
},
549 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
552 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
553 static const struct message WmShowRestoreMaxOverlappedSeq
[] = {
554 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
555 { WM_GETTEXT
, sent
|optional
},
556 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
557 { WM_GETMINMAXINFO
, sent
|defwinproc
},
558 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
559 { WM_NCPAINT
, sent
|optional
},
560 { WM_GETTEXT
, sent
|defwinproc
|optional
},
561 { WM_ERASEBKGND
, sent
|optional
},
562 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
563 { WM_MOVE
, sent
|defwinproc
|optional
},
564 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
565 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
566 { WM_NCPAINT
, sent
|optional
},
567 { WM_ERASEBKGND
, sent
|optional
},
568 { WM_PAINT
, sent
|optional
},
569 { WM_GETTITLEBARINFOEX
, sent
|optional
},
570 { WM_NCPAINT
, sent
|beginpaint
|optional
},
571 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
574 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
575 static const struct message WmShowRestoreMinOverlappedSeq
[] = {
576 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
577 { WM_QUERYOPEN
, sent
|optional
},
578 { WM_GETTEXT
, sent
|optional
},
579 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
580 { WM_WINDOWPOSCHANGING
, sent
|optional
}, /* SWP_NOSIZE|SWP_NOMOVE */
581 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
582 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
583 { WM_MOVE
, sent
|optional
},
584 { WM_SIZE
, sent
|wparam
|optional
, SIZE_RESTORED
},
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 { HCBT_ACTIVATE
, hook
|optional
},
590 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
591 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
592 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
593 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
594 { WM_GETTEXT
, sent
|defwinproc
|optional
},
595 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
596 { HCBT_SETFOCUS
, hook
|optional
},
597 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
598 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
599 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
600 { WM_GETTEXT
, sent
|optional
},
601 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
602 { WM_GETTEXT
, sent
|defwinproc
|optional
},
603 { WM_ERASEBKGND
, sent
},
604 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_STATECHANGED
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
},
605 { WM_MOVE
, sent
|defwinproc
},
606 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
607 { HCBT_SETFOCUS
, hook
|optional
},
608 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
609 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
610 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
611 { WM_ERASEBKGND
, sent
|optional
},
612 { HCBT_SETFOCUS
, hook
|optional
},
613 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
614 { WM_ACTIVATE
, sent
|wparam
, 1 },
615 { WM_GETTEXT
, sent
|optional
},
616 { WM_PAINT
, sent
|optional
},
617 { WM_GETTITLEBARINFOEX
, sent
|optional
},
618 { WM_NCPAINT
, sent
|beginpaint
|optional
},
619 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
622 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
623 static const struct message WmShowMinOverlappedSeq
[] = {
624 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
625 { HCBT_SETFOCUS
, hook
|optional
},
626 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
627 { WM_KILLFOCUS
, sent
|optional
},
628 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
629 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
630 { WM_GETTEXT
, sent
|optional
},
631 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCOPYBITS
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
632 { WM_GETMINMAXINFO
, sent
|defwinproc
},
633 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
634 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
635 { WM_NCPAINT
, sent
|optional
},
636 { WM_GETTEXT
, sent
|defwinproc
|optional
},
637 { WM_WINDOWPOSCHANGED
, sent
},
638 { WM_MOVE
, sent
|defwinproc
},
639 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
640 { WM_NCCALCSIZE
, sent
|optional
},
641 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
642 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
643 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
644 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
645 { WM_GETTEXT
, sent
|defwinproc
|optional
},
646 { WM_ACTIVATE
, sent
|optional
},
647 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
649 /* Vista sometimes restores the window right away... */
650 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
651 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
652 { HCBT_MINMAX
, hook
|optional
|lparam
, 0, SW_RESTORE
},
653 { WM_QUERYOPEN
, sent
|optional
},
654 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
655 { WM_GETMINMAXINFO
, sent
|optional
|defwinproc
},
656 { WM_NCCALCSIZE
, sent
|optional
|wparam
, TRUE
},
657 { HCBT_ACTIVATE
, hook
|optional
},
658 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 1 },
659 { WM_NCACTIVATE
, sent
|optional
},
660 { WM_GETTEXT
, sent
|optional
},
661 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
662 { HCBT_SETFOCUS
, hook
|optional
},
663 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
664 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
665 { WM_SETFOCUS
, sent
|optional
},
666 { WM_NCPAINT
, sent
|optional
},
667 { WM_GETTEXT
, sent
|defwinproc
|optional
},
668 { WM_ERASEBKGND
, sent
|optional
},
669 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
670 { WM_MOVE
, sent
|defwinproc
|optional
},
671 { WM_SIZE
, sent
|defwinproc
|optional
|wparam
, SIZE_RESTORED
},
672 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
673 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
674 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
676 { WM_PAINT
, sent
|optional
},
677 { WM_NCPAINT
, sent
|beginpaint
|optional
},
678 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
681 /* ShowWindow(SW_HIDE) for a visible overlapped window */
682 static const struct message WmHideOverlappedSeq
[] = {
683 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
684 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
685 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
686 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
687 { WM_SIZE
, sent
|optional
}, /* XP doesn't send it */
688 { WM_MOVE
, sent
|optional
}, /* XP doesn't send it */
689 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
690 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
691 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
692 { HCBT_SETFOCUS
, hook
|optional
},
693 { WM_KILLFOCUS
, sent
|wparam
|optional
, 0 },
694 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
695 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
698 /* DestroyWindow for a visible overlapped window */
699 static const struct message WmDestroyOverlappedSeq
[] = {
700 { HCBT_DESTROYWND
, hook
},
701 { 0x0090, sent
|optional
},
702 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
703 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
704 { 0x0090, sent
|optional
},
705 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
706 { WM_NCACTIVATE
, sent
|optional
|wparam
, 0 },
707 { WM_ACTIVATE
, sent
|optional
},
708 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 0 },
709 { WM_KILLFOCUS
, sent
|optional
|wparam
, 0 },
710 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
711 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
712 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
713 { WM_DESTROY
, sent
},
714 { WM_NCDESTROY
, sent
},
717 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
718 static const struct message WmCreateMaxPopupSeq
[] = {
719 { HCBT_CREATEWND
, hook
},
720 { WM_NCCREATE
, sent
},
721 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
723 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
724 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
726 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
727 { WM_GETMINMAXINFO
, sent
},
728 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
729 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
730 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
731 { WM_MOVE
, sent
|defwinproc
},
732 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
733 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
734 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
735 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
736 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
737 { HCBT_ACTIVATE
, hook
},
738 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
739 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
740 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
741 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
742 { WM_ERASEBKGND
, sent
|optional
},
743 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_NOMOVE
|SWP_NOSIZE
},
744 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
745 { WM_NCACTIVATE
, sent
},
746 { WM_ACTIVATE
, sent
|wparam
, 1 },
747 { HCBT_SETFOCUS
, hook
},
748 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
749 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
750 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
751 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
752 { WM_GETTEXT
, sent
|optional
},
753 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
754 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
755 { WM_ERASEBKGND
, sent
|optional
},
756 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
757 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
758 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
761 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
762 static const struct message WmCreateInvisibleMaxPopupSeq
[] = {
763 { HCBT_CREATEWND
, hook
},
764 { WM_NCCREATE
, sent
},
765 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
767 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
768 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
770 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
771 { WM_GETMINMAXINFO
, sent
},
772 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
773 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
774 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
775 { WM_MOVE
, sent
|defwinproc
},
776 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
777 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
780 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
781 static const struct message WmShowMaxPopupResizedSeq_todo
[] = {
782 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
783 { WM_GETMINMAXINFO
, sent
},
784 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
785 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
786 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
787 { HCBT_ACTIVATE
, hook
},
788 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
789 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
790 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
791 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
792 { WM_ERASEBKGND
, sent
|optional
},
793 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
794 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
795 { WM_NCACTIVATE
, sent
},
796 { WM_ACTIVATE
, sent
|wparam
, 1 },
797 { HCBT_SETFOCUS
, hook
},
798 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
799 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
800 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
801 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
802 { WM_GETTEXT
, sent
|optional
},
803 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
804 { WM_ERASEBKGND
, sent
|optional
},
805 { WM_WINDOWPOSCHANGED
, sent
},
806 /* WinNT4.0 sends WM_MOVE */
807 { WM_MOVE
, sent
|defwinproc
|optional
},
808 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
809 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
812 static const struct message WmShowMaxPopupResizedSeq
[] = {
813 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
814 { WM_GETMINMAXINFO
, sent
},
815 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
816 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
817 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
818 { HCBT_ACTIVATE
, hook
},
819 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
820 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
821 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
822 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
823 { WM_ERASEBKGND
, sent
|optional
},
824 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
825 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
826 { WM_NCACTIVATE
, sent
},
827 { WM_ACTIVATE
, sent
|wparam
, 1 },
828 { HCBT_SETFOCUS
, hook
},
829 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
830 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
831 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
832 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
833 { WM_GETTEXT
, sent
|optional
},
834 { WM_NCPAINT
, sent
|optional
}, /* We'll check WM_NCPAINT behaviour in another test */
835 { WM_ERASEBKGND
, sent
|optional
},
836 { WM_WINDOWPOSCHANGED
, sent
},
837 /* WinNT4.0 sends WM_MOVE */
838 { WM_MOVE
, sent
|defwinproc
|optional
},
839 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
840 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
843 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
844 static const struct message WmShowMaxPopupSeq
[] = {
845 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
846 { WM_GETMINMAXINFO
, sent
},
847 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
848 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
849 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
850 { HCBT_ACTIVATE
, hook
},
851 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
852 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
853 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
854 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
855 { WM_ERASEBKGND
, sent
|optional
},
856 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOMOVE
|SWP_NOSIZE
},
857 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
858 { WM_NCACTIVATE
, sent
},
859 { WM_ACTIVATE
, sent
|wparam
, 1 },
860 { HCBT_SETFOCUS
, hook
},
861 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
862 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
863 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
864 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
865 { WM_GETTEXT
, sent
|optional
},
866 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
867 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
868 { WM_ERASEBKGND
, sent
|optional
},
869 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
870 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
871 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
},
872 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
875 /* CreateWindow(WS_VISIBLE) for popup window */
876 static const struct message WmCreatePopupSeq
[] = {
877 { HCBT_CREATEWND
, hook
},
878 { WM_NCCREATE
, sent
},
879 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
881 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
882 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
884 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
885 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
886 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
887 { HCBT_ACTIVATE
, hook
},
888 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
889 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
890 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
891 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
892 { WM_ERASEBKGND
, sent
|optional
},
893 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
894 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
895 { WM_NCACTIVATE
, sent
},
896 { WM_ACTIVATE
, sent
|wparam
, 1 },
897 { HCBT_SETFOCUS
, hook
},
898 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
899 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
900 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
901 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
902 { WM_GETTEXT
, sent
|optional
},
903 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
904 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
905 { WM_ERASEBKGND
, sent
|optional
},
906 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
909 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
910 static const struct message WmShowVisMaxPopupSeq
[] = {
911 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
912 { WM_GETMINMAXINFO
, sent
},
913 { WM_GETTEXT
, sent
|optional
},
914 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
915 { WM_GETTEXT
, sent
|optional
},
916 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
917 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
918 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
919 { WM_ERASEBKGND
, sent
|optional
},
920 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
921 { WM_MOVE
, sent
|defwinproc
},
922 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
923 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
926 /* CreateWindow (for a child popup window, not initially visible) */
927 static const struct message WmCreateChildPopupSeq
[] = {
928 { HCBT_CREATEWND
, hook
},
929 { WM_NCCREATE
, sent
},
930 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
932 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
933 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
937 /* CreateWindow (for a popup window, not initially visible,
938 * which sets WS_VISIBLE in WM_CREATE handler)
940 static const struct message WmCreateInvisiblePopupSeq
[] = {
941 { HCBT_CREATEWND
, hook
},
942 { WM_NCCREATE
, sent
},
943 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
945 { WM_STYLECHANGING
, sent
},
946 { WM_STYLECHANGED
, sent
},
947 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
948 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
952 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
953 * for a popup window with WS_VISIBLE style set
955 static const struct message WmShowVisiblePopupSeq_2
[] = {
956 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
959 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
960 * for a popup window with WS_VISIBLE style set
962 static const struct message WmShowVisiblePopupSeq_3
[] = {
963 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
964 { HCBT_ACTIVATE
, hook
},
965 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
966 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
967 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
968 { WM_NCACTIVATE
, sent
},
969 { WM_ACTIVATE
, sent
|wparam
, 1 },
970 { HCBT_SETFOCUS
, hook
},
971 { WM_KILLFOCUS
, sent
|parent
},
972 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
973 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
974 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
975 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
976 { WM_SETFOCUS
, sent
|defwinproc
},
977 { WM_GETTEXT
, sent
|optional
},
978 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_SHOWWINDOW
},
981 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
983 static const struct message WmShowPopupExtremeLocationSeq
[] = {
984 { HCBT_CREATEWND
, hook
},
985 { WM_NCCREATE
, sent
},
986 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
988 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
989 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
991 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
992 { WM_WINDOWPOSCHANGING
, sent
},
993 { HCBT_ACTIVATE
, hook
},
994 { WM_WINDOWPOSCHANGING
, sent
|optional
},
995 { WM_QUERYNEWPALETTE
, sent
|optional
},
996 { WM_ACTIVATEAPP
, sent
},
997 { WM_NCACTIVATE
, sent
},
998 { WM_ACTIVATE
, sent
},
999 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1000 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1001 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1002 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1003 { HCBT_SETFOCUS
, hook
},
1004 { WM_SETFOCUS
, sent
|defwinproc
},
1005 { WM_NCPAINT
, sent
|wparam
, 1 },
1006 { WM_ERASEBKGND
, sent
},
1007 { WM_WINDOWPOSCHANGED
, sent
},
1008 /* occasionally received on test machines */
1009 { WM_NCPAINT
, sent
|optional
},
1010 { WM_ERASEBKGND
, sent
|optional
},
1013 /* CreateWindow (for a popup window with WS_VISIBLE style set)
1015 static const struct message WmShowPopupFirstDrawSeq_1
[] = {
1016 { HCBT_CREATEWND
, hook
},
1017 { WM_NCCREATE
, sent
},
1018 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1019 { WM_CREATE
, sent
},
1020 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1021 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1023 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1024 { WM_WINDOWPOSCHANGING
, sent
},
1025 { HCBT_ACTIVATE
, hook
},
1026 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1027 { WM_QUERYNEWPALETTE
, sent
|optional
},
1028 { WM_ACTIVATEAPP
, sent
},
1029 { WM_NCACTIVATE
, sent
},
1030 { WM_ACTIVATE
, sent
},
1031 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1032 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1033 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1034 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1035 { HCBT_SETFOCUS
, hook
},
1036 { WM_SETFOCUS
, sent
|defwinproc
},
1037 { WM_NCPAINT
, sent
|wparam
, 1 },
1038 { WM_ERASEBKGND
, sent
},
1039 { WM_WINDOWPOSCHANGED
, sent
},
1041 /* occasionally received on test machines */
1042 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1043 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1046 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1048 static const struct message WmShowPopupFirstDrawSeq_2
[] = {
1049 { HCBT_CREATEWND
, hook
},
1050 { WM_NCCREATE
, sent
},
1051 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1052 { WM_CREATE
, sent
},
1053 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1054 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1056 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1057 { WM_GETMINMAXINFO
, sent
},
1058 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_STATECHANGED
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
1059 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
1060 { HCBT_ACTIVATE
, hook
},
1061 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1062 { WM_NCPAINT
, sent
|optional
|wparam
, 1 },
1063 { WM_ERASEBKGND
, sent
|optional
},
1064 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1065 { WM_QUERYNEWPALETTE
, sent
|optional
},
1066 { WM_ACTIVATEAPP
, sent
},
1067 { WM_NCACTIVATE
, sent
},
1068 { WM_ACTIVATE
, sent
},
1069 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1070 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1071 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1072 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1073 { HCBT_SETFOCUS
, hook
},
1074 { WM_SETFOCUS
, sent
|defwinproc
},
1075 { WM_NCPAINT
, sent
|wparam
, 1 },
1076 { WM_ERASEBKGND
, sent
},
1077 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1078 { WM_MOVE
, sent
|defwinproc
},
1079 { WM_SIZE
, sent
|defwinproc
, 0 },
1081 /* occasionally received on test machines */
1082 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1083 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1086 static const struct message WmFirstDrawSetWindowPosSeq1
[] = {
1087 { HCBT_CREATEWND
, hook
},
1088 { WM_NCCREATE
, sent
},
1089 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1090 { WM_CREATE
, sent
},
1091 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1092 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1094 { WM_WINDOWPOSCHANGING
, sent
},
1095 { HCBT_ACTIVATE
, hook
},
1096 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1097 { WM_QUERYNEWPALETTE
, sent
|optional
},
1098 { WM_ACTIVATEAPP
, sent
},
1099 { WM_NCACTIVATE
, sent
},
1100 { WM_ACTIVATE
, sent
},
1101 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1102 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1103 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1104 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1105 { HCBT_SETFOCUS
, hook
},
1106 { WM_SETFOCUS
, sent
|defwinproc
},
1107 { WM_NCPAINT
, sent
|wparam
, 1 },
1108 { WM_ERASEBKGND
, sent
},
1109 { WM_WINDOWPOSCHANGED
, sent
},
1110 { WM_MOVE
, sent
|defwinproc
},
1113 static const struct message WmFirstDrawSetWindowPosSeq2
[] = {
1114 { HCBT_CREATEWND
, hook
},
1115 { WM_NCCREATE
, sent
},
1116 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1117 { WM_CREATE
, sent
},
1118 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1119 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1121 { WM_WINDOWPOSCHANGING
, sent
},
1122 { HCBT_ACTIVATE
, hook
},
1123 { WM_QUERYNEWPALETTE
, sent
|optional
},
1124 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1125 { WM_ACTIVATEAPP
, sent
},
1126 { WM_NCACTIVATE
, sent
},
1127 { WM_ACTIVATE
, sent
},
1128 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1129 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1130 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1131 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1132 { HCBT_SETFOCUS
, hook
},
1133 { WM_SETFOCUS
, sent
|defwinproc
},
1134 { WM_WINDOWPOSCHANGED
, sent
},
1135 { WM_MOVE
, sent
|defwinproc
},
1138 static const struct message WmFirstDrawSetWindowPosSeq3
[] = {
1139 { HCBT_CREATEWND
, hook
},
1140 { WM_NCCREATE
, sent
},
1141 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1142 { WM_CREATE
, sent
},
1143 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1144 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1146 { HCBT_ACTIVATE
, hook
|optional
},
1147 /* Probably shouldn't happen, but not part of this test */
1148 { WM_QUERYNEWPALETTE
, sent
|optional
},
1149 { WM_ACTIVATEAPP
, sent
|optional
},
1150 { WM_NCACTIVATE
, sent
|optional
},
1151 { WM_ACTIVATE
, sent
|optional
},
1152 { HCBT_SETFOCUS
, hook
|optional
},
1153 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
1156 static const struct message WmFirstDrawSetWindowPosSeq4
[] = {
1157 { HCBT_CREATEWND
, hook
},
1158 { WM_NCCREATE
, sent
},
1159 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1160 { WM_CREATE
, sent
},
1161 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1162 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1164 { WM_WINDOWPOSCHANGING
, sent
},
1165 { HCBT_ACTIVATE
, hook
},
1166 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1167 { WM_QUERYNEWPALETTE
, sent
|optional
},
1168 { WM_ACTIVATEAPP
, sent
},
1169 { WM_NCACTIVATE
, sent
},
1170 { WM_ACTIVATE
, sent
},
1171 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1172 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1173 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1174 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1175 { HCBT_SETFOCUS
, hook
},
1176 { WM_SETFOCUS
, sent
|defwinproc
},
1177 { WM_NCPAINT
, sent
|wparam
, 1 },
1178 { WM_ERASEBKGND
, sent
},
1179 { WM_WINDOWPOSCHANGED
, sent
},
1182 static const struct message WmFirstDrawSetWindowPosSeq5
[] = {
1183 { HCBT_CREATEWND
, hook
},
1184 { WM_NCCREATE
, sent
},
1185 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1186 { WM_CREATE
, sent
},
1187 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1188 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1190 { WM_WINDOWPOSCHANGING
, sent
},
1191 { HCBT_ACTIVATE
, hook
},
1192 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1193 { WM_QUERYNEWPALETTE
, sent
|optional
},
1194 { WM_ACTIVATEAPP
, sent
},
1195 { WM_NCACTIVATE
, sent
},
1196 { WM_ACTIVATE
, sent
},
1197 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1198 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1199 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1200 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1201 { HCBT_SETFOCUS
, hook
},
1202 { WM_SETFOCUS
, sent
|defwinproc
},
1203 { WM_WINDOWPOSCHANGED
, sent
},
1206 static const struct message WmFirstDrawChildSeq1
[] = {
1209 static const struct message WmFirstDrawChildSeq2
[] = {
1210 { WM_NCPAINT
, sent
|wparam
, 1 },
1211 { WM_ERASEBKGND
, sent
},
1212 /* occasionally received on test machines */
1213 { WM_NCPAINT
, sent
|optional
},
1214 { WM_ERASEBKGND
, sent
|optional
},
1217 /* CreateWindow (for child window, not initially visible) */
1218 static const struct message WmCreateChildSeq
[] = {
1219 { HCBT_CREATEWND
, hook
},
1220 { WM_NCCREATE
, sent
},
1221 /* child is inserted into parent's child list after WM_NCCREATE returns */
1222 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1223 { WM_CREATE
, sent
},
1224 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1225 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1227 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1230 /* CreateWindow (for maximized child window, not initially visible) */
1231 static const struct message WmCreateMaximizedChildSeq
[] = {
1232 { HCBT_CREATEWND
, hook
},
1233 { WM_NCCREATE
, sent
},
1234 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1235 { WM_CREATE
, sent
},
1236 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1237 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1239 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1240 { WM_GETMINMAXINFO
, sent
},
1241 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
1242 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1243 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1244 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1245 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1246 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1249 /* CreateWindow (for a child window, initially visible) */
1250 static const struct message WmCreateVisibleChildSeq
[] = {
1251 { HCBT_CREATEWND
, hook
},
1252 { WM_NCCREATE
, sent
},
1253 /* child is inserted into parent's child list after WM_NCCREATE returns */
1254 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1255 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1256 { WM_CREATE
, sent
},
1257 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1258 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1260 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1261 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1262 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1263 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1264 { WM_ERASEBKGND
, sent
|parent
|optional
},
1265 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1266 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
1267 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1270 /* ShowWindow(SW_SHOW) for a not visible child window */
1271 static const struct message WmShowChildSeq
[] = {
1272 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1273 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1274 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1275 { WM_ERASEBKGND
, sent
|parent
|optional
},
1276 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1279 /* ShowWindow(SW_HIDE) for a visible child window */
1280 static const struct message WmHideChildSeq
[] = {
1281 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1282 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1283 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1284 { WM_ERASEBKGND
, sent
|parent
|optional
},
1285 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1288 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1289 static const struct message WmHideChildSeq2
[] = {
1290 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1291 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1292 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1293 { WM_ERASEBKGND
, sent
|parent
|optional
},
1294 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1297 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1298 * for a not visible child window
1300 static const struct message WmShowChildSeq_2
[] = {
1301 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1302 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1303 { WM_CHILDACTIVATE
, sent
},
1304 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1307 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1308 * for a not visible child window
1310 static const struct message WmShowChildSeq_3
[] = {
1311 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1312 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1313 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1316 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1317 * for a visible child window with a caption
1319 static const struct message WmShowChildSeq_4
[] = {
1320 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1321 { WM_CHILDACTIVATE
, sent
},
1324 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1325 static const struct message WmShowChildInvisibleParentSeq_1
[] = {
1326 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1327 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1328 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1329 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1330 { WM_CHILDACTIVATE
, sent
|optional
},
1331 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1332 { WM_MOVE
, sent
|defwinproc
},
1333 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1334 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1335 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1336 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1337 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1338 { WM_GETTEXT
, sent
|optional
},
1341 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1342 static const struct message WmShowChildInvisibleParentSeq_1r
[] = {
1343 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1346 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1347 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
1348 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1349 { WM_GETMINMAXINFO
, sent
},
1350 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
1351 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1352 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1353 { WM_CHILDACTIVATE
, sent
},
1354 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1355 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1356 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1359 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1360 static const struct message WmShowChildInvisibleParentSeq_2r
[] = {
1361 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1364 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1365 static const struct message WmShowChildInvisibleParentSeq_3
[] = {
1366 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1367 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1368 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1369 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1370 { WM_CHILDACTIVATE
, sent
},
1371 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1372 { WM_MOVE
, sent
|defwinproc
},
1373 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1374 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1375 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1376 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1377 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1378 { WM_GETTEXT
, sent
|optional
},
1381 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1382 static const struct message WmShowChildInvisibleParentSeq_3r
[] = {
1383 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1386 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1387 static const struct message WmShowChildInvisibleParentSeq_4
[] = {
1388 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1389 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1390 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1391 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1392 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1393 { WM_MOVE
, sent
|defwinproc
},
1394 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1395 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1396 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1397 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1398 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1399 { WM_GETTEXT
, sent
|optional
},
1402 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1403 static const struct message WmShowChildInvisibleParentSeq_4r
[] = {
1404 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1407 /* ShowWindow(SW_SHOW) for child with invisible parent */
1408 static const struct message WmShowChildInvisibleParentSeq_5
[] = {
1409 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1412 /* ShowWindow(SW_HIDE) for child with invisible parent */
1413 static const struct message WmHideChildInvisibleParentSeq
[] = {
1414 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1417 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1418 static const struct message WmShowChildInvisibleParentSeq_6
[] = {
1419 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1420 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1421 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1424 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1425 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
1426 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1427 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1428 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1431 /* DestroyWindow for a visible child window */
1432 static const struct message WmDestroyChildSeq
[] = {
1433 { HCBT_DESTROYWND
, hook
},
1434 { 0x0090, sent
|optional
},
1435 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1436 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1437 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1438 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1439 { WM_ERASEBKGND
, sent
|parent
|optional
},
1440 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1441 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
1442 { WM_KILLFOCUS
, sent
},
1443 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1444 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
1445 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1446 { WM_SETFOCUS
, sent
|parent
},
1447 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1448 { WM_DESTROY
, sent
},
1449 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
1450 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
1451 { WM_NCDESTROY
, sent
},
1454 /* visible child window destroyed by thread exit */
1455 static const struct message WmExitThreadSeq
[] = {
1456 { WM_NCDESTROY
, sent
}, /* actually in grandchild */
1457 { WM_PAINT
, sent
|parent
},
1458 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
1461 /* DestroyWindow for a visible child window with invisible parent */
1462 static const struct message WmDestroyInvisibleChildSeq
[] = {
1463 { HCBT_DESTROYWND
, hook
},
1464 { 0x0090, sent
|optional
},
1465 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1466 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1467 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1468 { WM_DESTROY
, sent
},
1469 { WM_NCDESTROY
, sent
},
1472 /* Resizing child window with MoveWindow (32) */
1473 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1474 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1475 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1476 { WM_ERASEBKGND
, sent
|parent
|optional
},
1477 { WM_ERASEBKGND
, sent
|optional
},
1478 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1479 { WM_MOVE
, sent
|defwinproc
},
1480 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1481 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1484 /* Creation of a custom dialog (32) */
1485 static const struct message WmCreateCustomDialogSeq
[] = {
1486 { HCBT_CREATEWND
, hook
},
1487 { WM_GETMINMAXINFO
, sent
},
1488 { WM_NCCREATE
, sent
},
1489 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1490 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1491 { WM_CREATE
, sent
},
1492 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1493 { WM_NOTIFYFORMAT
, sent
|optional
},
1494 { WM_QUERYUISTATE
, sent
|optional
},
1495 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1496 { WM_GETMINMAXINFO
, sent
|optional
},
1497 { WM_NCCALCSIZE
, sent
|optional
},
1498 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1499 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1500 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1501 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1502 { HCBT_ACTIVATE
, hook
},
1503 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1506 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1508 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1510 { WM_NCACTIVATE
, sent
},
1511 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1512 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1513 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1514 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1515 { WM_ACTIVATE
, sent
|wparam
, 1 },
1516 { WM_GETTEXT
, sent
|optional
},
1517 { WM_KILLFOCUS
, sent
|parent
},
1518 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1519 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1520 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1521 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1522 { WM_SETFOCUS
, sent
},
1523 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1524 { WM_NCPAINT
, sent
|wparam
, 1 },
1525 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1526 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1527 { WM_ERASEBKGND
, sent
},
1528 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1529 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1530 { WM_GETTEXT
, sent
|optional
},
1531 { WM_GETTEXT
, sent
|optional
},
1532 { WM_NCCALCSIZE
, sent
|optional
},
1533 { WM_NCPAINT
, sent
|optional
},
1534 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1535 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1536 { WM_ERASEBKGND
, sent
|optional
},
1537 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1538 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1539 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1543 /* Calling EndDialog for a custom dialog (32) */
1544 static const struct message WmEndCustomDialogSeq
[] = {
1545 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1546 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1547 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1548 { WM_GETTEXT
, sent
|optional
},
1549 { HCBT_ACTIVATE
, hook
},
1550 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1551 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1552 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1553 { WM_ACTIVATE
, sent
|wparam
, 0 },
1554 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1555 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1556 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1557 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1558 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1559 { HCBT_SETFOCUS
, hook
},
1560 { WM_KILLFOCUS
, sent
},
1561 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1562 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1563 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1564 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1565 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1568 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1569 static const struct message WmShowCustomDialogSeq
[] = {
1570 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1571 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1572 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1573 { HCBT_ACTIVATE
, hook
},
1574 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1576 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1578 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1579 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1580 { WM_NCACTIVATE
, sent
},
1581 { WM_ACTIVATE
, sent
|wparam
, 1 },
1582 { WM_GETTEXT
, sent
|optional
},
1584 { WM_KILLFOCUS
, sent
|parent
},
1585 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1586 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1587 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1588 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1589 { WM_SETFOCUS
, sent
},
1590 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1591 { WM_NCPAINT
, sent
|wparam
, 1 },
1592 { WM_ERASEBKGND
, sent
},
1593 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1594 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1597 /* Creation and destruction of a modal dialog (32) */
1598 static const struct message WmModalDialogSeq
[] = {
1599 { WM_CANCELMODE
, sent
|parent
},
1600 { HCBT_SETFOCUS
, hook
},
1601 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1602 { WM_KILLFOCUS
, sent
|parent
},
1603 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1604 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1605 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1606 { HCBT_CREATEWND
, hook
},
1607 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1608 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1609 { WM_SETFONT
, sent
},
1610 { WM_INITDIALOG
, sent
},
1611 { WM_CHANGEUISTATE
, sent
|optional
},
1612 { WM_UPDATEUISTATE
, sent
|optional
},
1613 { WM_SHOWWINDOW
, sent
},
1614 { HCBT_ACTIVATE
, hook
},
1615 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1616 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1617 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1618 { WM_NCACTIVATE
, sent
},
1619 { WM_GETTEXT
, sent
|optional
},
1620 { WM_ACTIVATE
, sent
|wparam
, 1 },
1621 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1622 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1623 { WM_NCPAINT
, sent
|optional
},
1624 { WM_GETTEXT
, sent
|optional
},
1625 { WM_ERASEBKGND
, sent
|optional
},
1626 { WM_CTLCOLORDLG
, sent
|optional
},
1627 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1628 { WM_GETTEXT
, sent
|optional
},
1629 { WM_NCCALCSIZE
, sent
|optional
},
1630 { WM_NCPAINT
, sent
|optional
},
1631 { WM_GETTEXT
, sent
|optional
},
1632 { WM_ERASEBKGND
, sent
|optional
},
1633 { WM_CTLCOLORDLG
, sent
|optional
},
1634 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1635 { WM_PAINT
, sent
|optional
},
1636 { WM_CTLCOLORBTN
, sent
|optional
},
1637 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1638 { WM_ENTERIDLE
, sent
|parent
|optional
},
1639 { WM_ENTERIDLE
, sent
|parent
|optional
},
1640 { WM_ENTERIDLE
, sent
|parent
|optional
},
1641 { WM_ENTERIDLE
, sent
|parent
|optional
},
1642 { WM_ENTERIDLE
, sent
|parent
|optional
},
1643 { WM_ENTERIDLE
, sent
|parent
|optional
},
1644 { WM_ENTERIDLE
, sent
|parent
|optional
},
1645 { WM_ENTERIDLE
, sent
|parent
|optional
},
1646 { WM_ENTERIDLE
, sent
|parent
|optional
},
1647 { WM_ENTERIDLE
, sent
|parent
|optional
},
1648 { WM_ENTERIDLE
, sent
|parent
|optional
},
1649 { WM_ENTERIDLE
, sent
|parent
|optional
},
1650 { WM_ENTERIDLE
, sent
|parent
|optional
},
1651 { WM_ENTERIDLE
, sent
|parent
|optional
},
1652 { WM_ENTERIDLE
, sent
|parent
|optional
},
1653 { WM_ENTERIDLE
, sent
|parent
|optional
},
1654 { WM_ENTERIDLE
, sent
|parent
|optional
},
1655 { WM_ENTERIDLE
, sent
|parent
|optional
},
1656 { WM_ENTERIDLE
, sent
|parent
|optional
},
1657 { WM_ENTERIDLE
, sent
|parent
|optional
},
1659 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1660 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1661 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1662 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1663 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1664 { WM_GETTEXT
, sent
|optional
},
1665 { HCBT_ACTIVATE
, hook
},
1666 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1667 { WM_GETTEXT
, sent
|optional
},
1668 { WM_ACTIVATE
, sent
|wparam
, 0 },
1669 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1670 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1671 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1672 { HCBT_SETFOCUS
, hook
},
1673 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1674 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1675 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1676 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1677 { HCBT_DESTROYWND
, hook
},
1678 { 0x0090, sent
|optional
},
1679 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1680 { WM_DESTROY
, sent
},
1681 { WM_NCDESTROY
, sent
},
1684 static const struct message WmModalDialogSeq_2
[] = {
1685 { WM_CANCELMODE
, sent
},
1686 { HCBT_SETFOCUS
, hook
},
1687 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1688 { WM_KILLFOCUS
, sent
},
1689 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1690 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1691 { WM_ENABLE
, sent
|wparam
, 0 },
1692 { HCBT_CREATEWND
, hook
},
1693 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1694 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1695 { WM_SETFONT
, sent
},
1696 { WM_INITDIALOG
, sent
},
1697 { WM_CHANGEUISTATE
, sent
|optional
},
1698 { WM_UPDATEUISTATE
, sent
|optional
},
1699 { WM_ENABLE
, sent
|wparam
, 1 },
1700 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1701 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1702 { WM_CHANGEUISTATE
, sent
|optional
},
1703 { WM_UPDATEUISTATE
, sent
|optional
},
1704 { HCBT_DESTROYWND
, hook
},
1705 { 0x0090, sent
|optional
},
1706 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1707 { WM_DESTROY
, sent
},
1708 { WM_NCDESTROY
, sent
},
1711 /* SetMenu for NonVisible windows with size change*/
1712 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1713 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1714 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1715 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1716 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1717 { WM_MOVE
, sent
|defwinproc
},
1718 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1719 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1720 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1721 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1722 { WM_GETTEXT
, sent
|optional
},
1723 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1726 /* SetMenu for NonVisible windows with no size change */
1727 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1728 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1729 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1730 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1731 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1734 /* SetMenu for Visible windows with size change */
1735 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1736 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1737 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1738 { 0x0093, sent
|defwinproc
|optional
},
1739 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1740 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1741 { 0x0093, sent
|defwinproc
|optional
},
1742 { 0x0093, sent
|defwinproc
|optional
},
1743 { 0x0091, sent
|defwinproc
|optional
},
1744 { 0x0092, sent
|defwinproc
|optional
},
1745 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1746 { WM_ERASEBKGND
, sent
|optional
},
1747 { WM_ACTIVATE
, sent
|optional
},
1748 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1749 { WM_MOVE
, sent
|defwinproc
},
1750 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1751 { 0x0093, sent
|optional
},
1752 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1753 { 0x0093, sent
|defwinproc
|optional
},
1754 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1755 { 0x0093, sent
|defwinproc
|optional
},
1756 { 0x0093, sent
|defwinproc
|optional
},
1757 { 0x0091, sent
|defwinproc
|optional
},
1758 { 0x0092, sent
|defwinproc
|optional
},
1759 { WM_ERASEBKGND
, sent
|optional
},
1760 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1761 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1764 /* SetMenu for Visible windows with no size change */
1765 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1766 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1767 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1768 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1769 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1770 { WM_ERASEBKGND
, sent
|optional
},
1771 { WM_ACTIVATE
, sent
|optional
},
1772 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1773 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1776 /* DrawMenuBar for a visible window */
1777 static const struct message WmDrawMenuBarSeq
[] =
1779 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1780 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1781 { 0x0093, sent
|defwinproc
|optional
},
1782 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1783 { 0x0093, sent
|defwinproc
|optional
},
1784 { 0x0093, sent
|defwinproc
|optional
},
1785 { 0x0091, sent
|defwinproc
|optional
},
1786 { 0x0092, sent
|defwinproc
|optional
},
1787 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1788 { WM_ERASEBKGND
, sent
|optional
},
1789 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1790 { 0x0093, sent
|optional
},
1791 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1795 static const struct message WmSetRedrawFalseSeq
[] =
1797 { WM_SETREDRAW
, sent
|wparam
, 0 },
1801 static const struct message WmSetRedrawTrueSeq
[] =
1803 { WM_SETREDRAW
, sent
|wparam
, 1 },
1807 static const struct message WmEnableWindowSeq_1
[] =
1809 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1810 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1811 { HCBT_SETFOCUS
, hook
|optional
},
1812 { WM_KILLFOCUS
, sent
|optional
},
1813 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
1817 static const struct message WmEnableWindowSeq_2
[] =
1819 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1820 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1824 static const struct message WmEnableWindowSeq_3
[] =
1826 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1827 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
1831 static const struct message WmEnableWindowSeq_4
[] =
1833 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1837 static const struct message WmGetScrollRangeSeq
[] =
1839 { SBM_GETRANGE
, sent
},
1842 static const struct message WmGetScrollInfoSeq
[] =
1844 { SBM_GETSCROLLINFO
, sent
},
1847 static const struct message WmSetScrollRangeSeq
[] =
1849 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1850 sends SBM_SETSCROLLINFO.
1852 { SBM_SETSCROLLINFO
, sent
},
1855 /* SetScrollRange for a window without a non-client area */
1856 static const struct message WmSetScrollRangeHSeq_empty
[] =
1858 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 0 },
1861 static const struct message WmSetScrollRangeVSeq_empty
[] =
1863 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 0 },
1866 static const struct message WmSetScrollRangeHVSeq
[] =
1868 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1869 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1870 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1871 { WM_ERASEBKGND
, sent
|optional
},
1872 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1873 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1874 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1877 /* SetScrollRange for a window with a non-client area */
1878 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
1880 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1881 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1882 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1883 { WM_NCPAINT
, sent
|optional
},
1884 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1885 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1886 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1887 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1888 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1889 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1890 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1891 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1892 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1893 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1894 { WM_ERASEBKGND
, sent
|optional
},
1895 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
1896 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
1897 { WM_SIZE
, sent
|defwinproc
|optional
},
1898 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1899 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1900 { WM_GETTEXT
, sent
|optional
},
1901 { WM_GETTEXT
, sent
|optional
},
1902 { WM_GETTEXT
, sent
|optional
},
1903 { WM_GETTEXT
, sent
|optional
},
1906 /* test if we receive the right sequence of messages */
1907 /* after calling ShowWindow( SW_SHOWNA) */
1908 static const struct message WmSHOWNAChildInvisParInvis
[] = {
1909 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1912 static const struct message WmSHOWNAChildVisParInvis
[] = {
1913 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1916 static const struct message WmSHOWNAChildVisParVis
[] = {
1917 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1918 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1921 static const struct message WmSHOWNAChildInvisParVis
[] = {
1922 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1923 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1924 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1925 { WM_ERASEBKGND
, sent
|optional
},
1926 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
1929 static const struct message WmSHOWNATopVisible
[] = {
1930 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1931 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1932 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1933 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1934 { WM_ERASEBKGND
, sent
|optional
},
1935 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1938 static const struct message WmSHOWNATopInvisible
[] = {
1939 { WM_NOTIFYFORMAT
, sent
|optional
},
1940 { WM_QUERYUISTATE
, sent
|optional
},
1941 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1942 { WM_GETMINMAXINFO
, sent
|optional
},
1943 { WM_NCCALCSIZE
, sent
|optional
},
1944 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1945 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1946 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1947 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1948 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1949 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1950 { WM_ERASEBKGND
, sent
|optional
},
1951 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1952 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1953 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1954 { WM_ERASEBKGND
, sent
|optional
},
1955 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1956 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1961 static const struct message WmTrackPopupMenu
[] = {
1962 { HCBT_CREATEWND
, hook
},
1963 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1964 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1965 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1966 { 0x0093, sent
|optional
},
1967 { 0x0094, sent
|optional
},
1968 { 0x0094, sent
|optional
},
1969 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1970 { WM_CAPTURECHANGED
, sent
},
1971 { HCBT_DESTROYWND
, hook
},
1972 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1973 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1974 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1978 static const struct message WmTrackPopupMenuEsc
[] = {
1982 static const struct message WmTrackPopupMenuCapture
[] = {
1983 { HCBT_CREATEWND
, hook
},
1984 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1985 { WM_CAPTURECHANGED
, sent
},
1986 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1987 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1988 { 0x0093, sent
|optional
},
1989 { 0x0094, sent
|optional
},
1990 { 0x0094, sent
|optional
},
1991 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1992 { WM_CAPTURECHANGED
, sent
},
1993 { HCBT_DESTROYWND
, hook
},
1994 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1995 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1996 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2000 static const struct message WmTrackPopupMenuEmpty
[] = {
2001 { HCBT_CREATEWND
, hook
},
2002 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2003 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2004 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2005 { 0x0093, sent
|optional
},
2006 { 0x0094, sent
|optional
},
2007 { 0x0094, sent
|optional
},
2008 { WM_CAPTURECHANGED
, sent
},
2009 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2010 { HCBT_DESTROYWND
, hook
},
2011 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2015 static const struct message WmTrackPopupMenuAbort
[] = {
2016 { HCBT_CREATEWND
, hook
},
2017 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2018 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2019 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2020 { 0x0093, sent
|optional
},
2021 { 0x0094, sent
|optional
},
2022 { 0x0094, sent
|optional
},
2023 { WM_CAPTURECHANGED
, sent
},
2024 { HCBT_DESTROYWND
, hook
},
2025 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2026 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2027 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2031 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
2032 static int sequence_cnt
, sequence_size
;
2033 static struct recvd_message
* sequence
;
2034 static int log_all_parent_messages
;
2035 static CRITICAL_SECTION sequence_cs
;
2037 /* user32 functions */
2038 static HWND (WINAPI
*pGetAncestor
)(HWND
,UINT
);
2039 static BOOL (WINAPI
*pGetMenuInfo
)(HMENU
,LPCMENUINFO
);
2040 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
2041 static BOOL (WINAPI
*pSetMenuInfo
)(HMENU
,LPCMENUINFO
);
2042 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
2043 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
2044 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
2045 static BOOL (WINAPI
*pGetMonitorInfoA
)(HMONITOR
,LPMONITORINFO
);
2046 static HMONITOR (WINAPI
*pMonitorFromPoint
)(POINT
,DWORD
);
2047 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
2048 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
2049 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
2050 static UINT_PTR (WINAPI
*pSetCoalescableTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
, ULONG
);
2051 /* kernel32 functions */
2052 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
2054 static void init_procs(void)
2056 HMODULE user32
= GetModuleHandleA("user32.dll");
2057 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
2059 #define GET_PROC(dll, func) \
2060 p ## func = (void*)GetProcAddress(dll, #func); \
2062 trace("GetProcAddress(%s) failed\n", #func); \
2065 GET_PROC(user32
, GetAncestor
)
2066 GET_PROC(user32
, GetMenuInfo
)
2067 GET_PROC(user32
, NotifyWinEvent
)
2068 GET_PROC(user32
, SetMenuInfo
)
2069 GET_PROC(user32
, SetWinEventHook
)
2070 GET_PROC(user32
, TrackMouseEvent
)
2071 GET_PROC(user32
, UnhookWinEvent
)
2072 GET_PROC(user32
, GetMonitorInfoA
)
2073 GET_PROC(user32
, MonitorFromPoint
)
2074 GET_PROC(user32
, UpdateLayeredWindow
)
2075 GET_PROC(user32
, SetSystemTimer
)
2076 GET_PROC(user32
, KillSystemTimer
)
2077 GET_PROC(user32
, SetCoalescableTimer
)
2079 GET_PROC(kernel32
, GetCPInfoExA
)
2084 static const char *get_winpos_flags(UINT flags
)
2086 static char buffer
[300];
2089 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2090 DUMP( SWP_SHOWWINDOW
);
2091 DUMP( SWP_HIDEWINDOW
);
2092 DUMP( SWP_NOACTIVATE
);
2093 DUMP( SWP_FRAMECHANGED
);
2094 DUMP( SWP_NOCOPYBITS
);
2095 DUMP( SWP_NOOWNERZORDER
);
2096 DUMP( SWP_NOSENDCHANGING
);
2097 DUMP( SWP_DEFERERASE
);
2098 DUMP( SWP_ASYNCWINDOWPOS
);
2099 DUMP( SWP_NOZORDER
);
2100 DUMP( SWP_NOREDRAW
);
2103 DUMP( SWP_NOCLIENTSIZE
);
2104 DUMP( SWP_NOCLIENTMOVE
);
2105 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
2110 static BOOL
ignore_message( UINT message
)
2112 /* these are always ignored */
2113 return (message
>= 0xc000 ||
2114 message
== WM_GETICON
||
2115 message
== WM_GETOBJECT
||
2116 message
== WM_TIMECHANGE
||
2117 message
== WM_DISPLAYCHANGE
||
2118 message
== WM_DEVICECHANGE
||
2119 message
== WM_DWMNCRENDERINGCHANGED
);
2122 static unsigned hash_Ly_W(const WCHAR
*str
)
2127 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2132 static unsigned hash_Ly(const char *str
)
2137 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2142 #define add_message(msg) add_message_(__LINE__,msg);
2143 static void add_message_(int line
, const struct recvd_message
*msg
)
2145 struct recvd_message
*seq
;
2147 EnterCriticalSection( &sequence_cs
);
2151 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
) );
2153 if (sequence_cnt
== sequence_size
)
2156 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof(*sequence
) );
2160 seq
= &sequence
[sequence_cnt
++];
2161 seq
->hwnd
= msg
->hwnd
;
2162 seq
->message
= msg
->message
;
2163 seq
->flags
= msg
->flags
;
2164 seq
->wParam
= msg
->wParam
;
2165 seq
->lParam
= msg
->lParam
;
2167 seq
->descr
= msg
->descr
;
2169 LeaveCriticalSection( &sequence_cs
);
2173 if (msg
->flags
& hook
)
2175 static const char * const CBT_code_name
[10] =
2183 "HCBT_CLICKSKIPPED",
2188 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
2190 sprintf( seq
->output
, "%s: hook %d (%s) wp %08lx lp %08lx",
2191 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
2193 else if (msg
->flags
& winevent_hook
)
2195 sprintf( seq
->output
, "%s: winevent %p %08x %08lx %08lx",
2196 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2200 switch (msg
->message
)
2202 case WM_WINDOWPOSCHANGING
:
2203 case WM_WINDOWPOSCHANGED
:
2205 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
2207 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s",
2208 msg
->descr
, msg
->hwnd
,
2209 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
2210 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
2211 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
2212 get_winpos_flags(winpos
->flags
) );
2214 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2215 * in the high word for internal purposes
2217 seq
->wParam
= winpos
->flags
& 0xffff;
2218 /* We are not interested in the flags that don't match under XP and Win9x */
2219 seq
->wParam
&= ~SWP_NOZORDER
;
2225 DRAW_ITEM_STRUCT di
;
2226 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
2228 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2229 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
2230 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
2233 di
.u
.item
.type
= dis
->CtlType
;
2234 di
.u
.item
.ctl_id
= dis
->CtlID
;
2235 if (dis
->CtlType
== ODT_LISTBOX
||
2236 dis
->CtlType
== ODT_COMBOBOX
||
2237 dis
->CtlType
== ODT_MENU
)
2238 di
.u
.item
.item_id
= dis
->itemID
;
2239 di
.u
.item
.action
= dis
->itemAction
;
2240 di
.u
.item
.state
= dis
->itemState
;
2242 seq
->lParam
= di
.u
.lp
;
2246 case WM_MEASUREITEM
:
2248 MEASURE_ITEM_STRUCT mi
;
2249 MEASUREITEMSTRUCT
*mis
= (MEASUREITEMSTRUCT
*)msg
->lParam
;
2250 BOOL is_unicode_data
= TRUE
;
2252 sprintf( seq
->output
, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx",
2253 msg
->descr
, msg
->hwnd
, mis
->CtlType
, mis
->CtlID
,
2254 mis
->itemID
, mis
->itemData
);
2256 if (mis
->CtlType
== ODT_LISTBOX
)
2258 HWND ctrl
= GetDlgItem(msg
->hwnd
, mis
->CtlID
);
2259 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2263 mi
.u
.item
.CtlType
= mis
->CtlType
;
2264 mi
.u
.item
.CtlID
= mis
->CtlID
;
2265 mi
.u
.item
.itemID
= mis
->itemID
;
2266 mi
.u
.item
.wParam
= msg
->wParam
;
2267 seq
->wParam
= mi
.u
.wp
;
2268 if (is_unicode_data
)
2269 seq
->lParam
= mis
->itemData
? hash_Ly_W((const WCHAR
*)mis
->itemData
) : 0;
2271 seq
->lParam
= mis
->itemData
? hash_Ly((const char *)mis
->itemData
) : 0;
2275 case WM_COMPAREITEM
:
2277 COMPAREITEMSTRUCT
*cis
= (COMPAREITEMSTRUCT
*)msg
->lParam
;
2278 HWND ctrl
= GetDlgItem(msg
->hwnd
, cis
->CtlID
);
2279 BOOL is_unicode_data
= TRUE
;
2281 ok(msg
->wParam
== cis
->CtlID
, "expected %#x, got %#lx\n", cis
->CtlID
, msg
->wParam
);
2282 ok(cis
->hwndItem
== ctrl
, "expected %p, got %p\n", ctrl
, cis
->hwndItem
);
2283 ok((int)cis
->itemID1
>= 0, "expected >= 0, got %d\n", cis
->itemID1
);
2284 ok((int)cis
->itemID2
== -1, "expected -1, got %d\n", cis
->itemID2
);
2286 sprintf( seq
->output
, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx",
2287 msg
->descr
, msg
->hwnd
, cis
->CtlType
, cis
->CtlID
,
2288 cis
->itemID1
, cis
->itemData1
, cis
->itemID2
, cis
->itemData2
);
2290 if (cis
->CtlType
== ODT_LISTBOX
)
2291 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2293 if (is_unicode_data
)
2295 seq
->wParam
= cis
->itemData1
? hash_Ly_W((const WCHAR
*)cis
->itemData1
) : 0;
2296 seq
->lParam
= cis
->itemData2
? hash_Ly_W((const WCHAR
*)cis
->itemData2
) : 0;
2300 seq
->wParam
= cis
->itemData1
? hash_Ly((const char *)cis
->itemData1
) : 0;
2301 seq
->lParam
= cis
->itemData2
? hash_Ly((const char *)cis
->itemData2
) : 0;
2307 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
2308 sprintf( seq
->output
, "%s: %p %04x wp %08lx lp %08lx",
2309 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2311 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
2312 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
2317 /* try to make sure pending X events have been processed before continuing */
2318 static void flush_events(void)
2322 int min_timeout
= 100;
2323 DWORD time
= GetTickCount() + diff
;
2327 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
2328 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2329 diff
= time
- GetTickCount();
2333 static void flush_sequence(void)
2335 EnterCriticalSection( &sequence_cs
);
2336 HeapFree(GetProcessHeap(), 0, sequence
);
2338 sequence_cnt
= sequence_size
= 0;
2339 LeaveCriticalSection( &sequence_cs
);
2342 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
2344 const struct recvd_message
*actual
= sequence
;
2345 unsigned int count
= 0;
2347 trace_(file
, line
)("Failed sequence %s:\n", context
);
2348 while (expected
->message
&& actual
->message
)
2350 if (actual
->output
[0])
2352 if (expected
->flags
& hook
)
2354 trace_(file
, line
)( " %u: expected: hook %04x - actual: %s\n",
2355 count
, expected
->message
, actual
->output
);
2357 else if (expected
->flags
& winevent_hook
)
2359 trace_(file
, line
)( " %u: expected: winevent %04x - actual: %s\n",
2360 count
, expected
->message
, actual
->output
);
2362 else if (expected
->flags
& kbd_hook
)
2364 trace_(file
, line
)( " %u: expected: kbd %04x - actual: %s\n",
2365 count
, expected
->message
, actual
->output
);
2369 trace_(file
, line
)( " %u: expected: msg %04x - actual: %s\n",
2370 count
, expected
->message
, actual
->output
);
2374 if (expected
->message
== actual
->message
)
2376 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) &&
2377 (expected
->flags
& optional
))
2379 /* don't match messages if their defwinproc status differs */
2388 /* silently drop winevent messages if there is no support for them */
2389 else if ((expected
->flags
& optional
) || ((expected
->flags
& winevent_hook
) && !hEvent_hook
))
2399 /* optional trailing messages */
2400 while (expected
->message
&& ((expected
->flags
& optional
) ||
2401 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2403 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2408 if (expected
->message
)
2410 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2414 while (actual
->message
&& actual
->output
[0])
2416 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
2422 #define ok_sequence( exp, contx, todo) \
2423 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2426 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2427 const char *file
, int line
)
2429 static const struct recvd_message end_of_sequence
;
2430 const struct message
*expected
= expected_list
;
2431 const struct recvd_message
*actual
;
2432 int failcount
= 0, dump
= 0;
2433 unsigned int count
= 0;
2435 add_message(&end_of_sequence
);
2439 while (expected
->message
&& actual
->message
)
2441 if (expected
->message
== actual
->message
&&
2442 !((expected
->flags
^ actual
->flags
) & (hook
|winevent_hook
|kbd_hook
)))
2444 if (expected
->flags
& wparam
)
2446 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2450 if (strcmp(winetest_platform
, "wine")) dump
++;
2451 ok_( file
, line
) (FALSE
,
2452 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2453 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2458 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2459 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2460 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2461 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2465 if (expected
->flags
& lparam
)
2467 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2471 if (strcmp(winetest_platform
, "wine")) dump
++;
2472 ok_( file
, line
) (FALSE
,
2473 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2474 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2479 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2480 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2481 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2482 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2485 if ((expected
->flags
& optional
) &&
2486 ((expected
->flags
^ actual
->flags
) & (defwinproc
|parent
)))
2488 /* don't match optional messages if their defwinproc or parent status differs */
2493 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2497 if (strcmp(winetest_platform
, "wine")) dump
++;
2498 ok_( file
, line
) (FALSE
,
2499 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2500 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2505 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2506 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2507 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2508 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2511 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2512 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n",
2513 context
, count
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2514 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2516 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2517 "%s: %u: the msg 0x%04x should have been %s\n",
2518 context
, count
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2519 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2521 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2522 "%s: %u: the msg 0x%04x was expected in %s\n",
2523 context
, count
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2524 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2526 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
2527 "%s: %u: the msg 0x%04x should have been sent by a hook\n",
2528 context
, count
, expected
->message
);
2529 if ((expected
->flags
& hook
) != (actual
->flags
& hook
)) dump
++;
2531 ok_( file
, line
) ((expected
->flags
& winevent_hook
) == (actual
->flags
& winevent_hook
),
2532 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n",
2533 context
, count
, expected
->message
);
2534 if ((expected
->flags
& winevent_hook
) != (actual
->flags
& winevent_hook
)) dump
++;
2536 ok_( file
, line
) ((expected
->flags
& kbd_hook
) == (actual
->flags
& kbd_hook
),
2537 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n",
2538 context
, count
, expected
->message
);
2539 if ((expected
->flags
& kbd_hook
) != (actual
->flags
& kbd_hook
)) dump
++;
2544 /* silently drop hook messages if there is no support for them */
2545 else if ((expected
->flags
& optional
) ||
2546 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2547 ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2548 ((expected
->flags
& kbd_hook
) && !hKBD_hook
))
2554 if (strcmp(winetest_platform
, "wine")) dump
++;
2555 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2556 context
, count
, expected
->message
, actual
->message
);
2562 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2563 context
, count
, expected
->message
, actual
->message
);
2571 /* skip all optional trailing messages */
2572 while (expected
->message
&& ((expected
->flags
& optional
) ||
2573 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2574 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2580 if (expected
->message
|| actual
->message
) {
2582 if (strcmp(winetest_platform
, "wine")) dump
++;
2583 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2584 context
, count
, expected
->message
, actual
->message
);
2590 if (expected
->message
|| actual
->message
)
2593 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2594 context
, count
, expected
->message
, actual
->message
);
2597 if( todo
&& !failcount
) /* succeeded yet marked todo */
2599 if (!strcmp(winetest_platform
, "wine")) dump
++;
2600 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
2604 if (dump
) dump_sequence(expected_list
, context
, file
, line
);
2608 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
2610 /******************************** MDI test **********************************/
2612 /* CreateWindow for MDI frame window, initially visible */
2613 static const struct message WmCreateMDIframeSeq
[] = {
2614 { HCBT_CREATEWND
, hook
},
2615 { WM_GETMINMAXINFO
, sent
},
2616 { WM_NCCREATE
, sent
},
2617 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2618 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
2619 { WM_CREATE
, sent
},
2620 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2621 { WM_NOTIFYFORMAT
, sent
|optional
},
2622 { WM_QUERYUISTATE
, sent
|optional
},
2623 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2624 { WM_GETMINMAXINFO
, sent
|optional
},
2625 { WM_NCCALCSIZE
, sent
|optional
},
2626 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2627 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2628 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2629 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2630 { HCBT_ACTIVATE
, hook
},
2631 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
2632 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2633 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2634 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2635 { WM_NCACTIVATE
, sent
},
2636 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2637 { WM_ACTIVATE
, sent
|wparam
, 1 },
2638 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2639 { HCBT_SETFOCUS
, hook
},
2640 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2641 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2642 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2643 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2644 /* Win9x adds SWP_NOZORDER below */
2645 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2646 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2647 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2648 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2652 /* DestroyWindow for MDI frame window, initially visible */
2653 static const struct message WmDestroyMDIframeSeq
[] = {
2654 { HCBT_DESTROYWND
, hook
},
2655 { 0x0090, sent
|optional
},
2656 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2657 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2658 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2659 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2660 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
2661 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2662 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
2663 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
2664 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2665 { WM_DESTROY
, sent
},
2666 { WM_NCDESTROY
, sent
},
2669 /* CreateWindow for MDI client window, initially visible */
2670 static const struct message WmCreateMDIclientSeq
[] = {
2671 { HCBT_CREATEWND
, hook
},
2672 { WM_NCCREATE
, sent
},
2673 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2674 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2675 { WM_CREATE
, sent
},
2676 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2677 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2678 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2680 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
2681 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2682 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2683 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2684 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2687 /* ShowWindow(SW_SHOW) for MDI client window */
2688 static const struct message WmShowMDIclientSeq
[] = {
2689 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2690 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2691 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2692 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2695 /* ShowWindow(SW_HIDE) for MDI client window */
2696 static const struct message WmHideMDIclientSeq
[] = {
2697 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2698 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2699 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
2700 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
2701 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2704 /* DestroyWindow for MDI client window, initially visible */
2705 static const struct message WmDestroyMDIclientSeq
[] = {
2706 { HCBT_DESTROYWND
, hook
},
2707 { 0x0090, sent
|optional
},
2708 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
2709 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2710 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2711 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2712 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2713 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2714 { WM_DESTROY
, sent
},
2715 { WM_NCDESTROY
, sent
},
2718 /* CreateWindow for MDI child window, initially visible */
2719 static const struct message WmCreateMDIchildVisibleSeq
[] = {
2720 { HCBT_CREATEWND
, hook
},
2721 { WM_NCCREATE
, sent
},
2722 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2723 { WM_CREATE
, sent
},
2724 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2725 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2727 /* Win2k sends wparam set to
2728 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2729 * while Win9x doesn't bother to set child window id according to
2730 * CLIENTCREATESTRUCT.idFirstChild
2732 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2733 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2734 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2735 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2736 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2737 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2738 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2739 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2740 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2742 /* Win9x: message sequence terminates here. */
2744 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2745 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2746 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2747 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2748 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2749 { WM_SETFOCUS
, sent
}, /* in MDI client */
2750 { HCBT_SETFOCUS
, hook
},
2751 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2752 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2753 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2754 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2755 { WM_SETFOCUS
, sent
|defwinproc
},
2756 { WM_MDIACTIVATE
, sent
|defwinproc
},
2759 /* WM_CHILDACTIVATE sent to disabled window */
2760 static const struct message WmChildActivateDisabledWindowSeq
[] = {
2761 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2764 /* WM_CHILDACTIVATE sent to enabled window */
2765 static const struct message WmChildActivateWindowSeq
[] = {
2766 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2767 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 },
2768 { WM_MDIACTIVATE
, sent
|defwinproc
},
2769 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2770 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2771 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2772 { HCBT_SETFOCUS
, hook
},
2773 { WM_KILLFOCUS
, sent
|defwinproc
},
2774 { WM_SETFOCUS
, sent
},
2775 { HCBT_SETFOCUS
, hook
},
2776 { WM_KILLFOCUS
, sent
},
2777 { WM_SETFOCUS
, sent
|defwinproc
},
2778 { WM_MDIACTIVATE
, sent
|defwinproc
},
2781 /* CreateWindow for MDI child window with invisible parent */
2782 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
2783 { HCBT_CREATEWND
, hook
},
2784 { WM_GETMINMAXINFO
, sent
},
2785 { WM_NCCREATE
, sent
},
2786 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2787 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2788 { WM_CREATE
, sent
},
2789 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2790 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2792 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2793 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2794 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
2795 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2796 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2797 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2799 /* Win9x: message sequence terminates here. */
2801 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2802 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2803 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2804 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2805 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2806 { WM_SETFOCUS
, sent
}, /* in MDI client */
2807 { HCBT_SETFOCUS
, hook
},
2808 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2809 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2810 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2811 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2812 { WM_SETFOCUS
, sent
|defwinproc
},
2813 { WM_MDIACTIVATE
, sent
|defwinproc
},
2816 /* DestroyWindow for MDI child window, initially visible */
2817 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
2818 { HCBT_DESTROYWND
, hook
},
2819 /* Win2k sends wparam set to
2820 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2821 * while Win9x doesn't bother to set child window id according to
2822 * CLIENTCREATESTRUCT.idFirstChild
2824 { 0x0090, sent
|optional
},
2825 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2826 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2827 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2828 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2829 { WM_ERASEBKGND
, sent
|parent
|optional
},
2830 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2832 /* { WM_DESTROY, sent }
2833 * Win9x: message sequence terminates here.
2836 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2837 { WM_KILLFOCUS
, sent
},
2838 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2839 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2840 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2841 { WM_SETFOCUS
, sent
}, /* in MDI client */
2843 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2844 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2845 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2846 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2847 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2848 { WM_SETFOCUS
, sent
}, /* in MDI client */
2850 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2852 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2853 { WM_KILLFOCUS
, sent
},
2854 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2855 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2856 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2857 { WM_SETFOCUS
, sent
}, /* in MDI client */
2859 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2860 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2861 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2862 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2863 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2864 { WM_SETFOCUS
, sent
}, /* in MDI client */
2866 { WM_DESTROY
, sent
},
2868 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2869 { WM_KILLFOCUS
, sent
},
2870 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2871 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2872 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2873 { WM_SETFOCUS
, sent
}, /* in MDI client */
2875 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2876 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2877 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2878 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2879 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2880 { WM_SETFOCUS
, sent
}, /* in MDI client */
2882 { WM_NCDESTROY
, sent
},
2885 /* CreateWindow for MDI child window, initially invisible */
2886 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
2887 { HCBT_CREATEWND
, hook
},
2888 { WM_NCCREATE
, sent
},
2889 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2890 { WM_CREATE
, sent
},
2891 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2892 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2894 /* Win2k sends wparam set to
2895 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2896 * while Win9x doesn't bother to set child window id according to
2897 * CLIENTCREATESTRUCT.idFirstChild
2899 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2902 /* DestroyWindow for MDI child window, initially invisible */
2903 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
2904 { HCBT_DESTROYWND
, hook
},
2905 /* Win2k sends wparam set to
2906 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2907 * while Win9x doesn't bother to set child window id according to
2908 * CLIENTCREATESTRUCT.idFirstChild
2910 { 0x0090, sent
|optional
},
2911 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2912 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2913 { WM_DESTROY
, sent
},
2914 { WM_NCDESTROY
, sent
},
2915 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
2916 { WM_PARENTNOTIFY
, sent
|wparam
|optional
, WM_DESTROY
}, /* MDI client */
2919 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
2920 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
2921 { HCBT_CREATEWND
, hook
},
2922 { WM_NCCREATE
, sent
},
2923 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2924 { WM_CREATE
, sent
},
2925 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2926 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2928 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2929 { WM_GETMINMAXINFO
, sent
},
2930 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2931 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2932 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2933 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2935 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2936 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2937 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2938 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2939 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2940 /* Win2k sends wparam set to
2941 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2942 * while Win9x doesn't bother to set child window id according to
2943 * CLIENTCREATESTRUCT.idFirstChild
2945 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2946 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2947 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2948 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2949 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2950 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2951 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2952 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2953 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
2955 /* Win9x: message sequence terminates here. */
2957 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
2958 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
2959 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2960 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2961 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2962 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2963 { HCBT_SETFOCUS
, hook
|optional
},
2964 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
2965 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2966 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2967 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2968 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
2969 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
2971 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2972 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2973 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2974 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2977 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
2978 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
2979 /* restore the 1st MDI child */
2980 { WM_SETREDRAW
, sent
|wparam
, 0 },
2981 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
2982 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
2983 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2984 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2985 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2986 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2988 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2989 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2990 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2991 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2992 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2993 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
2994 /* create the 2nd MDI child */
2995 { HCBT_CREATEWND
, hook
},
2996 { WM_NCCREATE
, sent
},
2997 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2998 { WM_CREATE
, sent
},
2999 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3000 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3002 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3003 { WM_GETMINMAXINFO
, sent
},
3004 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3005 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3006 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3007 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3008 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3010 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3011 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3012 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3013 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3014 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3015 /* Win2k sends wparam set to
3016 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3017 * while Win9x doesn't bother to set child window id according to
3018 * CLIENTCREATESTRUCT.idFirstChild
3020 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3021 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3022 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3023 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3024 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3025 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3026 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3027 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3029 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3030 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3032 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3034 /* Win9x: message sequence terminates here. */
3036 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3037 { HCBT_SETFOCUS
, hook
},
3038 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
3039 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
3040 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3041 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3042 { WM_SETFOCUS
, sent
}, /* in MDI client */
3043 { HCBT_SETFOCUS
, hook
},
3044 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3045 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3046 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3047 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3048 { WM_SETFOCUS
, sent
|defwinproc
},
3050 { WM_MDIACTIVATE
, sent
|defwinproc
},
3052 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3053 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3054 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3055 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3058 /* WM_MDICREATE MDI child window, initially visible and maximized */
3059 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
3060 { WM_MDICREATE
, sent
},
3061 { HCBT_CREATEWND
, hook
},
3062 { WM_NCCREATE
, sent
},
3063 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3064 { WM_CREATE
, sent
},
3065 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3066 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3068 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3069 { WM_GETMINMAXINFO
, sent
},
3070 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3071 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3072 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3073 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3076 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3077 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3078 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3079 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3080 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3082 /* Win2k sends wparam set to
3083 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3084 * while Win9x doesn't bother to set child window id according to
3085 * CLIENTCREATESTRUCT.idFirstChild
3087 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3088 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3089 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3091 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3093 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3094 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3095 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3097 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3098 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3100 /* Win9x: message sequence terminates here. */
3102 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3103 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3104 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3105 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3106 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
3107 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
3108 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3109 { HCBT_SETFOCUS
, hook
|optional
},
3110 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3111 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3112 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3113 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3114 { WM_SETFOCUS
, sent
|defwinproc
},
3116 { WM_MDIACTIVATE
, sent
|defwinproc
},
3119 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3120 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3121 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3122 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3125 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3126 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3127 { 0x0093, sent
|defwinproc
|optional
},
3128 { 0x0093, sent
|defwinproc
|optional
},
3129 { 0x0093, sent
|defwinproc
|optional
},
3130 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3131 { WM_MOVE
, sent
|defwinproc
},
3132 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3135 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3136 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3137 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3138 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3141 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3142 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3143 { 0x0093, sent
|optional
},
3144 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3145 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3147 { 0x0093, sent
|optional
},
3148 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3149 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3150 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
3151 { 0x0093, sent
|defwinproc
|optional
},
3152 { 0x0093, sent
|defwinproc
|optional
},
3153 { 0x0093, sent
|defwinproc
|optional
},
3154 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3155 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3159 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3160 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
3161 { HCBT_CREATEWND
, hook
},
3162 { WM_GETMINMAXINFO
, sent
},
3163 { WM_NCCREATE
, sent
},
3164 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3165 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
3166 { WM_CREATE
, sent
},
3167 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3168 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3169 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3170 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
3171 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3173 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3174 { WM_GETMINMAXINFO
, sent
},
3175 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3176 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3177 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3178 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3179 { WM_MOVE
, sent
|defwinproc
},
3180 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3182 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3183 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3184 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3185 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3186 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
3187 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3188 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3189 /* Win2k sends wparam set to
3190 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3191 * while Win9x doesn't bother to set child window id according to
3192 * CLIENTCREATESTRUCT.idFirstChild
3194 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3197 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3198 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
3199 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
3200 { HCBT_SYSCOMMAND
, hook
},
3201 { WM_CLOSE
, sent
|defwinproc
},
3202 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3204 /* bring the 1st MDI child to top */
3205 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
3206 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
3208 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3210 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
3211 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3212 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3214 /* maximize the 1st MDI child */
3215 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3216 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3217 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3218 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3219 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3220 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3221 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3223 /* restore the 2nd MDI child */
3224 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
3225 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
3226 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3227 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3229 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3231 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3232 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3234 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3236 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
3238 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3239 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3240 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3241 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3242 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3244 /* bring the 1st MDI child to top */
3245 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3246 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3247 { HCBT_SETFOCUS
, hook
},
3248 { WM_KILLFOCUS
, sent
|defwinproc
},
3249 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
3250 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3251 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3252 { WM_SETFOCUS
, sent
}, /* in MDI client */
3253 { HCBT_SETFOCUS
, hook
},
3254 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3255 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3256 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3257 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3258 { WM_SETFOCUS
, sent
|defwinproc
},
3259 { WM_MDIACTIVATE
, sent
|defwinproc
},
3260 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3262 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3263 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3264 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3265 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3266 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3267 { WM_MDIREFRESHMENU
, sent
},
3269 { HCBT_DESTROYWND
, hook
},
3270 /* Win2k sends wparam set to
3271 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3272 * while Win9x doesn't bother to set child window id according to
3273 * CLIENTCREATESTRUCT.idFirstChild
3275 { 0x0090, sent
|defwinproc
|optional
},
3276 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3277 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
3278 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3279 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3280 { WM_ERASEBKGND
, sent
|parent
|optional
},
3281 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3283 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3284 { WM_DESTROY
, sent
|defwinproc
},
3285 { WM_NCDESTROY
, sent
|defwinproc
},
3288 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3289 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
3290 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3291 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3292 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3293 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3294 { WM_ERASEBKGND
, sent
|parent
|optional
},
3295 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3297 { HCBT_SETFOCUS
, hook
},
3298 { WM_KILLFOCUS
, sent
},
3299 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3300 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3301 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3302 { WM_SETFOCUS
, sent
}, /* in MDI client */
3303 { HCBT_SETFOCUS
, hook
},
3304 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3305 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3306 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3307 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3308 { WM_SETFOCUS
, sent
},
3311 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3312 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3313 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3314 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3317 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3318 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3319 { 0x0093, sent
|defwinproc
|optional
},
3320 { 0x0093, sent
|defwinproc
|optional
},
3321 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3322 { WM_MOVE
, sent
|defwinproc
},
3323 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3326 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3327 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3328 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3329 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3332 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3333 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3334 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3335 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3338 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3339 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3340 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3341 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3344 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3345 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3346 { 0x0093, sent
|defwinproc
|optional
},
3347 { 0x0093, sent
|defwinproc
|optional
},
3348 { 0x0093, sent
|defwinproc
|optional
},
3349 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3350 { WM_MOVE
, sent
|defwinproc
},
3351 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3354 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3355 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3356 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3357 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3360 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3361 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3362 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3363 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3364 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3365 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3367 { 0x0093, sent
|defwinproc
|optional
},
3368 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
3369 { 0x0093, sent
|defwinproc
|optional
},
3370 { 0x0093, sent
|defwinproc
|optional
},
3371 { 0x0093, sent
|defwinproc
|optional
},
3372 { 0x0093, sent
|optional
},
3374 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3375 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3376 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3377 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3378 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3381 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3382 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3383 { 0x0093, sent
|defwinproc
|optional
},
3384 { 0x0093, sent
|defwinproc
|optional
},
3385 { 0x0093, sent
|defwinproc
|optional
},
3386 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3387 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3388 { 0x0093, sent
|optional
},
3390 { WM_NCACTIVATE
, sent
|wparam
, 0 },
3391 { WM_MDIACTIVATE
, sent
},
3393 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3394 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3395 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3397 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3399 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3400 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3401 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3404 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3405 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3406 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3407 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3410 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3411 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3412 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3413 { WM_MOVE
, sent
|defwinproc
},
3414 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3417 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3418 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3419 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3420 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3421 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3422 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3423 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3424 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3425 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3427 { HCBT_SETFOCUS
, hook
},
3428 { WM_KILLFOCUS
, sent
},
3429 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3430 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3431 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3432 { WM_SETFOCUS
, sent
}, /* in MDI client */
3434 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3436 { HCBT_DESTROYWND
, hook
},
3437 /* Win2k sends wparam set to
3438 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3439 * while Win9x doesn't bother to set child window id according to
3440 * CLIENTCREATESTRUCT.idFirstChild
3442 { 0x0090, sent
|optional
},
3443 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3445 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3446 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3447 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3448 { WM_ERASEBKGND
, sent
|parent
|optional
},
3449 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3451 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3452 { WM_DESTROY
, sent
},
3453 { WM_NCDESTROY
, sent
},
3456 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3457 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3458 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3459 { WM_GETMINMAXINFO
, sent
},
3460 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3461 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3462 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3463 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3465 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3466 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3467 { HCBT_SETFOCUS
, hook
|optional
},
3468 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3469 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3470 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3471 { HCBT_SETFOCUS
, hook
|optional
},
3472 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3473 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3474 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3475 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3476 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3477 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3478 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3479 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3481 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3482 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3483 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3484 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3485 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3488 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3489 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3490 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3491 { WM_GETMINMAXINFO
, sent
},
3492 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
3493 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3494 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3495 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3496 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3498 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3499 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3500 { HCBT_SETFOCUS
, hook
|optional
},
3501 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3502 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3503 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3504 { HCBT_SETFOCUS
, hook
|optional
},
3505 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3506 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3507 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3508 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3509 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3510 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3511 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3512 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3515 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3516 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3517 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3518 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3519 { WM_GETMINMAXINFO
, sent
},
3520 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3521 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3522 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3523 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3524 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3525 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3526 { WM_MOVE
, sent
|defwinproc
},
3527 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3529 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3530 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3531 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3532 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3533 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3534 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3536 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3537 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3538 { 0x0093, sent
|defwinproc
|optional
},
3539 { 0x0094, sent
|defwinproc
|optional
},
3540 { 0x0094, sent
|defwinproc
|optional
},
3541 { 0x0094, sent
|defwinproc
|optional
},
3542 { 0x0094, sent
|defwinproc
|optional
},
3543 { 0x0093, sent
|defwinproc
|optional
},
3544 { 0x0093, sent
|defwinproc
|optional
},
3545 { 0x0091, sent
|defwinproc
|optional
},
3546 { 0x0092, sent
|defwinproc
|optional
},
3547 { 0x0092, sent
|defwinproc
|optional
},
3548 { 0x0092, sent
|defwinproc
|optional
},
3549 { 0x0092, sent
|defwinproc
|optional
},
3550 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3551 { WM_MOVE
, sent
|defwinproc
},
3552 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3553 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3555 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3556 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3557 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3558 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3560 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3561 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3562 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3563 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3564 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3565 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3566 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3567 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3568 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3569 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3571 { 0x0093, sent
|optional
},
3572 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3573 { 0x0093, sent
|defwinproc
|optional
},
3574 { 0x0093, sent
|defwinproc
|optional
},
3575 { 0x0093, sent
|defwinproc
|optional
},
3576 { 0x0091, sent
|defwinproc
|optional
},
3577 { 0x0092, sent
|defwinproc
|optional
},
3578 { 0x0092, sent
|defwinproc
|optional
},
3579 { 0x0092, sent
|defwinproc
|optional
},
3580 { 0x0092, sent
|defwinproc
|optional
},
3581 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3582 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3583 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3586 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3587 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3588 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3589 { WM_GETMINMAXINFO
, sent
},
3590 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3591 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3592 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3593 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3594 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3596 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3597 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3598 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3599 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3600 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3603 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3604 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3605 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3606 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3607 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3608 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3609 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3610 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3612 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3613 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3614 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3615 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3616 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3619 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3620 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3621 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3622 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3623 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3624 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3625 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3626 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3627 { WM_MOVE
, sent
|defwinproc
},
3628 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3629 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3630 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3631 { HCBT_SETFOCUS
, hook
},
3632 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3633 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3634 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3635 { WM_SETFOCUS
, sent
},
3638 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3639 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
3640 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
3641 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3642 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3643 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3644 { WM_MOVE
, sent
|defwinproc
},
3645 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
3646 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
3647 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3648 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3649 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3650 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
}, /* MDI client */
3653 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3654 static const struct message WmRestoreMDIchildInvisibleSeq
[] = {
3655 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3656 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3657 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3658 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3659 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3660 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3661 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3663 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3664 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3665 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3666 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3667 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3671 static HWND mdi_client
;
3672 static WNDPROC old_mdi_client_proc
;
3674 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3676 struct recvd_message msg
;
3678 /* do not log painting messages */
3679 if (message
!= WM_PAINT
&&
3680 message
!= WM_NCPAINT
&&
3681 message
!= WM_SYNCPAINT
&&
3682 message
!= WM_ERASEBKGND
&&
3683 message
!= WM_NCHITTEST
&&
3684 message
!= WM_GETTEXT
&&
3685 message
!= WM_MDIGETACTIVE
&&
3686 !ignore_message( message
))
3689 msg
.message
= message
;
3690 msg
.flags
= sent
|wparam
|lparam
;
3691 msg
.wParam
= wParam
;
3692 msg
.lParam
= lParam
;
3693 msg
.descr
= "mdi client";
3697 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
3700 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3702 static LONG defwndproc_counter
= 0;
3704 struct recvd_message msg
;
3706 /* do not log painting messages */
3707 if (message
!= WM_PAINT
&&
3708 message
!= WM_NCPAINT
&&
3709 message
!= WM_SYNCPAINT
&&
3710 message
!= WM_ERASEBKGND
&&
3711 message
!= WM_NCHITTEST
&&
3712 message
!= WM_GETTEXT
&&
3713 !ignore_message( message
))
3717 case WM_MDIACTIVATE
:
3719 HWND active
, client
= GetParent(hwnd
);
3721 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
3723 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
3724 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
3726 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
3732 msg
.message
= message
;
3733 msg
.flags
= sent
|wparam
|lparam
;
3734 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3735 msg
.wParam
= wParam
;
3736 msg
.lParam
= lParam
;
3737 msg
.descr
= "mdi child";
3741 defwndproc_counter
++;
3742 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
3743 defwndproc_counter
--;
3748 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3750 static LONG defwndproc_counter
= 0;
3752 struct recvd_message msg
;
3754 /* do not log painting messages */
3755 if (message
!= WM_PAINT
&&
3756 message
!= WM_NCPAINT
&&
3757 message
!= WM_SYNCPAINT
&&
3758 message
!= WM_ERASEBKGND
&&
3759 message
!= WM_NCHITTEST
&&
3760 message
!= WM_GETTEXT
&&
3761 !ignore_message( message
))
3764 msg
.message
= message
;
3765 msg
.flags
= sent
|wparam
|lparam
;
3766 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3767 msg
.wParam
= wParam
;
3768 msg
.lParam
= lParam
;
3769 msg
.descr
= "mdi frame";
3773 defwndproc_counter
++;
3774 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
3775 defwndproc_counter
--;
3780 static BOOL
mdi_RegisterWindowClasses(void)
3785 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
3788 cls
.hInstance
= GetModuleHandleA(0);
3790 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
3791 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
3792 cls
.lpszMenuName
= NULL
;
3793 cls
.lpszClassName
= "MDI_frame_class";
3794 if (!RegisterClassA(&cls
)) return FALSE
;
3796 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
3797 cls
.lpszClassName
= "MDI_child_class";
3798 if (!RegisterClassA(&cls
)) return FALSE
;
3800 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
3801 old_mdi_client_proc
= cls
.lpfnWndProc
;
3802 cls
.hInstance
= GetModuleHandleA(0);
3803 cls
.lpfnWndProc
= mdi_client_hook_proc
;
3804 cls
.lpszClassName
= "MDI_client_class";
3805 if (!RegisterClassA(&cls
)) assert(0);
3810 static void test_mdi_messages(void)
3812 MDICREATESTRUCTA mdi_cs
;
3813 CLIENTCREATESTRUCT client_cs
;
3814 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
3817 HMENU hMenu
= CreateMenu();
3820 if (!mdi_RegisterWindowClasses()) assert(0);
3824 trace("creating MDI frame window\n");
3825 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
3826 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
3827 WS_MAXIMIZEBOX
| WS_VISIBLE
,
3828 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
3829 GetDesktopWindow(), hMenu
,
3830 GetModuleHandleA(0), NULL
);
3832 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
3834 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3835 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
3837 trace("creating MDI client window\n");
3838 GetClientRect(mdi_frame
, &rc
);
3839 client_cs
.hWindowMenu
= 0;
3840 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
3841 mdi_client
= CreateWindowExA(0, "MDI_client_class",
3843 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
3844 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
3845 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
3847 SetWindowLongA(mdi_client
, 0, 0xdeadbeef);
3849 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
3850 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3851 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
3853 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3854 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3855 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3860 trace("creating invisible MDI child window\n");
3861 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3863 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3864 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3868 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
3869 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
3871 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3872 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3874 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3875 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3877 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3878 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3879 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3881 ShowWindow(mdi_child
, SW_HIDE
);
3882 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
3885 ShowWindow(mdi_child
, SW_SHOW
);
3886 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
3888 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3889 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3891 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3892 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3894 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3895 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3896 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3898 DestroyWindow(mdi_child
);
3901 trace("creating visible MDI child window\n");
3902 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3903 WS_CHILD
| WS_VISIBLE
,
3904 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3905 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3907 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
3909 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3910 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3912 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3913 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3915 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3916 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3917 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3920 DestroyWindow(mdi_child
);
3921 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3923 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3924 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3926 /* Win2k: MDI client still returns a just destroyed child as active
3927 * Win9x: MDI client returns 0
3929 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3930 ok(active_child
== mdi_child
|| /* win2k */
3931 !active_child
, /* win9x */
3932 "wrong active MDI child %p\n", active_child
);
3933 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3937 trace("creating invisible MDI child window\n");
3938 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3940 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3941 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3943 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
3945 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
3946 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
3948 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3949 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3951 /* Win2k: MDI client still returns a just destroyed child as active
3952 * Win9x: MDI client returns mdi_child2
3954 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3955 ok(active_child
== mdi_child
|| /* win2k */
3956 active_child
== mdi_child2
, /* win9x */
3957 "wrong active MDI child %p\n", active_child
);
3958 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3961 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3962 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
3964 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3965 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3967 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3968 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3969 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3972 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3973 ok(GetFocus() == mdi_child2
|| /* win2k */
3974 GetFocus() == 0, /* win9x */
3975 "wrong focus window %p\n", GetFocus());
3980 ShowWindow(mdi_child2
, SW_HIDE
);
3981 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3983 ShowWindow(mdi_child2
, SW_RESTORE
);
3984 ok_sequence(WmRestoreMDIchildInvisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
3987 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3988 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3990 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3991 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3992 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3998 ShowWindow(mdi_child2
, SW_HIDE
);
3999 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4001 ShowWindow(mdi_child2
, SW_SHOW
);
4002 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
4004 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4005 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4007 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4008 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
4010 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4011 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4013 ShowWindow(mdi_child2
, SW_RESTORE
);
4014 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
4016 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4017 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4019 ShowWindow(mdi_child2
, SW_MINIMIZE
);
4020 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", TRUE
);
4022 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4023 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4025 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4026 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4027 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4030 ShowWindow(mdi_child2
, SW_RESTORE
);
4031 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
4033 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4034 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4036 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4037 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4038 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4044 ShowWindow(mdi_child2
, SW_HIDE
);
4045 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4047 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4048 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4050 DestroyWindow(mdi_child2
);
4051 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
4053 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4054 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4056 trace("Testing WM_CHILDACTIVATE\n");
4058 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4059 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_DISABLED
,
4060 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4061 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4063 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4064 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
,
4065 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4066 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4068 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4069 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4070 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4073 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4074 ok_sequence(WmChildActivateDisabledWindowSeq
, "WM_CHILDACTIVATE sent to disabled window", FALSE
);
4076 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4077 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4078 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4081 EnableWindow(mdi_child
, TRUE
);
4083 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4084 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4085 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4088 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4089 ok_sequence(WmChildActivateWindowSeq
, "WM_CHILDACTIVATE sent to enabled window", FALSE
);
4091 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4092 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4093 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4096 DestroyWindow(mdi_child
);
4097 DestroyWindow(mdi_child2
);
4100 /* test for maximized MDI children */
4101 trace("creating maximized visible MDI child window 1\n");
4102 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4103 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4104 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4105 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4107 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
4108 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4110 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4111 ok(GetFocus() == mdi_child
|| /* win2k */
4112 GetFocus() == 0, /* win9x */
4113 "wrong focus window %p\n", GetFocus());
4115 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4116 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4117 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4120 trace("creating maximized visible MDI child window 2\n");
4121 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4122 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4123 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4124 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4126 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4127 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4128 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4130 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4131 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4133 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4134 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4135 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4138 trace("destroying maximized visible MDI child window 2\n");
4139 DestroyWindow(mdi_child2
);
4140 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4142 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4144 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4145 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4147 /* Win2k: MDI client still returns a just destroyed child as active
4148 * Win9x: MDI client returns 0
4150 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4151 ok(active_child
== mdi_child2
|| /* win2k */
4152 !active_child
, /* win9x */
4153 "wrong active MDI child %p\n", active_child
);
4156 ShowWindow(mdi_child
, SW_MAXIMIZE
);
4157 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4160 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4161 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4163 trace("re-creating maximized visible MDI child window 2\n");
4164 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4165 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4166 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4167 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4169 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4170 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4171 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4173 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4174 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4176 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4177 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4178 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4181 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
4182 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
4183 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
4185 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4186 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4187 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4189 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4190 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4191 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4194 DestroyWindow(mdi_child
);
4195 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4197 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4198 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4200 /* Win2k: MDI client still returns a just destroyed child as active
4201 * Win9x: MDI client returns 0
4203 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4204 ok(active_child
== mdi_child
|| /* win2k */
4205 !active_child
, /* win9x */
4206 "wrong active MDI child %p\n", active_child
);
4209 trace("creating maximized invisible MDI child window\n");
4210 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4211 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
4212 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4213 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4215 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
4216 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4217 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
4218 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
4220 /* Win2k: MDI client still returns a just destroyed child as active
4221 * Win9x: MDI client returns 0
4223 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4224 ok(active_child
== mdi_child
|| /* win2k */
4225 !active_child
|| active_child
== mdi_child2
, /* win9x */
4226 "wrong active MDI child %p\n", active_child
);
4229 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4230 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4231 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
4232 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4233 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4234 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4236 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4237 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4238 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4241 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4244 /* end of test for maximized MDI children */
4247 trace("creating maximized visible MDI child window 1(Switch test)\n");
4248 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4249 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4250 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4251 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4253 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
4254 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
4256 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4257 ok(GetFocus() == mdi_child
|| /* win2k */
4258 GetFocus() == 0, /* win9x */
4259 "wrong focus window %p(Switch test)\n", GetFocus());
4261 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4262 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4263 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4266 trace("creating maximized visible MDI child window 2(Switch test)\n");
4267 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4268 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4269 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4270 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4272 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
4274 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
4275 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
4277 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4278 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
4280 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4281 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
4282 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4285 trace("Switch child window.\n");
4286 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
4287 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
4288 trace("end of test for switch maximized MDI children\n");
4291 /* Prepare for switching test of not maximized MDI children */
4292 ShowWindow( mdi_child
, SW_NORMAL
);
4293 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
4294 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
4295 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
4296 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4299 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
4300 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
4301 trace("end of test for switch not maximized MDI children\n");
4304 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4307 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4312 /* end of tests for switch maximized/not maximized MDI children */
4314 mdi_cs
.szClass
= "MDI_child_Class";
4315 mdi_cs
.szTitle
= "MDI child";
4316 mdi_cs
.hOwner
= GetModuleHandleA(0);
4319 mdi_cs
.cx
= CW_USEDEFAULT
;
4320 mdi_cs
.cy
= CW_USEDEFAULT
;
4321 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
4323 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
4324 ok(mdi_child
!= 0, "MDI child creation failed\n");
4325 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
4327 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
4329 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4330 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4332 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
4333 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4334 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4336 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4337 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4338 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4341 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4342 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
4344 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
4345 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4346 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4351 val
= GetWindowLongA(mdi_client
, 0);
4352 ok(val
== 0xdeadbeef || broken(val
== 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val
);
4353 DestroyWindow(mdi_client
);
4354 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4356 /* test maximization of MDI child with invisible parent */
4357 client_cs
.hWindowMenu
= 0;
4358 mdi_client
= CreateWindowA("MDI_client_class",
4360 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
4362 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4363 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
4365 ShowWindow(mdi_client
, SW_HIDE
);
4366 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
4368 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4369 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
4371 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4372 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
4374 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
4375 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
4376 zoomed
= IsZoomed(mdi_child
);
4377 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4379 ShowWindow(mdi_client
, SW_SHOW
);
4380 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
4382 DestroyWindow(mdi_child
);
4383 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
4385 /* end of test for maximization of MDI child with invisible parent */
4387 DestroyWindow(mdi_client
);
4388 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4390 DestroyWindow(mdi_frame
);
4391 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
4393 /************************* End of MDI test **********************************/
4395 static void test_WM_SETREDRAW(HWND hwnd
)
4397 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4402 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
4403 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
4405 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
4406 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
4409 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
4410 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
4412 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4413 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
4415 /* restore original WS_VISIBLE state */
4416 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4422 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4424 struct recvd_message msg
;
4426 if (ignore_message( message
)) return 0;
4432 case WM_NCMOUSEMOVE
:
4433 case WM_NCMOUSELEAVE
:
4441 msg
.message
= message
;
4442 msg
.flags
= sent
|wparam
|lparam
;
4443 msg
.wParam
= wParam
;
4444 msg
.lParam
= lParam
;
4445 msg
.descr
= "dialog";
4448 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
4449 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
4453 static INT_PTR CALLBACK
TestModalDlgProc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4455 struct recvd_message msg
;
4457 if (ignore_message( message
)) return 0;
4463 case WM_NCMOUSEMOVE
:
4464 case WM_NCMOUSELEAVE
:
4472 msg
.message
= message
;
4473 msg
.flags
= sent
|wparam
|lparam
;
4474 msg
.wParam
= wParam
;
4475 msg
.lParam
= lParam
;
4476 msg
.descr
= "dialog";
4479 if (message
== WM_INITDIALOG
) EndDialog( hwnd
, 0 );
4483 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4485 DWORD style
, exstyle
;
4489 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4490 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4491 /* do not be confused by WS_DLGFRAME set */
4492 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4494 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4495 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4497 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4498 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4499 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4500 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
4502 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
4504 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4505 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4506 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4508 /* a subsequent call should do nothing */
4509 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4510 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4511 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4515 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
4516 ok( ret
, "GetScrollRange(%d) error %d\n", ctl
, GetLastError());
4517 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4518 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
4519 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
4522 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4524 DWORD style
, exstyle
;
4528 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4529 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4530 /* do not be confused by WS_DLGFRAME set */
4531 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4533 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4534 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4536 si
.cbSize
= sizeof(si
);
4537 si
.fMask
= SIF_RANGE
;
4540 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4541 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4542 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4544 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4546 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4547 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4548 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4550 /* a subsequent call should do nothing */
4551 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4552 if (style
& WS_HSCROLL
)
4553 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4554 else if (style
& WS_VSCROLL
)
4555 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4557 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4559 si
.fMask
= SIF_PAGE
;
4561 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4562 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4566 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4567 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4569 si
.fMask
= SIF_RANGE
;
4570 si
.nMin
= 0xdeadbeef;
4571 si
.nMax
= 0xdeadbeef;
4572 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4573 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4574 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4575 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4576 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4579 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4580 static void test_scroll_messages(HWND hwnd
)
4591 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4592 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4593 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4594 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4595 /* values of min and max are undefined */
4598 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4599 ok( ret
, "SetScrollRange error %d\n", GetLastError());
4600 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4601 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4606 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4607 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4608 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4609 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4610 /* values of min and max are undefined */
4613 si
.cbSize
= sizeof(si
);
4614 si
.fMask
= SIF_RANGE
;
4617 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4618 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4619 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4622 si
.fMask
= SIF_PAGE
;
4624 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4625 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4626 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4631 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4632 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4633 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4636 si
.fMask
= SIF_RANGE
;
4637 si
.nMin
= 0xdeadbeef;
4638 si
.nMax
= 0xdeadbeef;
4639 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
4640 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4641 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
4642 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4643 /* values of min and max are undefined */
4646 /* set WS_HSCROLL */
4647 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4648 /* clear WS_HSCROLL */
4649 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4651 /* set WS_HSCROLL */
4652 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4653 /* clear WS_HSCROLL */
4654 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4656 /* set WS_VSCROLL */
4657 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4658 /* clear WS_VSCROLL */
4659 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4661 /* set WS_VSCROLL */
4662 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4663 /* clear WS_VSCROLL */
4664 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4667 static void test_showwindow(void)
4672 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4673 100, 100, 200, 200, 0, 0, 0, NULL
);
4674 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4675 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4676 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
4677 ok (hchild
!= 0, "Failed to create child\n");
4680 /* ShowWindow( SW_SHOWNA) for invisible top level window */
4681 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
4682 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4683 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
4685 /* ShowWindow( SW_SHOWNA) for now visible top level window */
4686 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
4687 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4688 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
4689 /* back to invisible */
4690 ShowWindow(hchild
, SW_HIDE
);
4691 ShowWindow(hwnd
, SW_HIDE
);
4693 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
4694 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
4695 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4696 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
4697 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
4698 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
4700 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
4701 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4702 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
4703 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
4704 ShowWindow( hwnd
, SW_SHOW
);
4706 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
4707 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4708 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
4710 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
4711 ShowWindow( hchild
, SW_HIDE
);
4713 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
4714 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4715 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
4718 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
4719 DestroyWindow(hchild
);
4720 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
4722 DestroyWindow(hwnd
);
4727 * 1. Create invisible maximized popup window.
4728 * 2. Move and resize it.
4729 * 3. Show it maximized.
4731 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4732 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4733 100, 100, 200, 200, 0, 0, 0, NULL
);
4734 ok (hwnd
!= 0, "Failed to create popup window\n");
4735 ok(IsZoomed(hwnd
), "window should be maximized\n");
4736 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4738 GetWindowRect(hwnd
, &rc
);
4739 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4740 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4741 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc
));
4742 /* Reset window's size & position */
4743 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4744 ok(IsZoomed(hwnd
), "window should be maximized\n");
4747 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4748 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4749 ok(IsZoomed(hwnd
), "window should be maximized\n");
4750 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
4752 GetWindowRect(hwnd
, &rc
);
4753 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4754 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4755 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc
));
4756 DestroyWindow(hwnd
);
4759 /* Test again, this time the NC_PAINT message */
4760 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4761 100, 100, 200, 200, 0, 0, 0, NULL
);
4762 ok (hwnd
!= 0, "Failed to create popup window\n");
4763 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4765 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4766 ok_sequence(WmShowMaxPopupResizedSeq_todo
,
4767 "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup TODO", TRUE
);
4768 DestroyWindow(hwnd
);
4772 * 1. Create invisible maximized popup window.
4773 * 2. Show it maximized.
4775 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4776 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4777 100, 100, 200, 200, 0, 0, 0, NULL
);
4778 ok (hwnd
!= 0, "Failed to create popup window\n");
4779 ok(IsZoomed(hwnd
), "window should be maximized\n");
4780 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4782 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4783 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4784 ok(IsZoomed(hwnd
), "window should be maximized\n");
4785 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
4786 DestroyWindow(hwnd
);
4790 * 1. Create visible maximized popup window.
4792 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
4793 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
4794 100, 100, 200, 200, 0, 0, 0, NULL
);
4795 ok (hwnd
!= 0, "Failed to create popup window\n");
4796 ok(IsZoomed(hwnd
), "window should be maximized\n");
4797 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4798 DestroyWindow(hwnd
);
4802 * 1. Create visible popup window.
4805 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
4806 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
4807 100, 100, 200, 200, 0, 0, 0, NULL
);
4808 ok (hwnd
!= 0, "Failed to create popup window\n");
4809 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
4810 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
4812 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
4813 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4814 ok(IsZoomed(hwnd
), "window should be maximized\n");
4815 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
4816 DestroyWindow(hwnd
);
4820 static void test_sys_menu(void)
4826 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4827 100, 100, 200, 200, 0, 0, 0, NULL
);
4828 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4832 /* test existing window without CS_NOCLOSE style */
4833 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4834 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4836 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4837 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4838 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4840 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
4841 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4843 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4844 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4845 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
4847 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
4848 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4850 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4851 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4852 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4854 /* test whether removing WS_SYSMENU destroys a system menu */
4855 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
4856 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
4858 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4859 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4861 DestroyWindow(hwnd
);
4863 /* test new window with CS_NOCLOSE style */
4864 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4865 100, 100, 200, 200, 0, 0, 0, NULL
);
4866 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4868 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4869 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4871 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4872 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4874 DestroyWindow(hwnd
);
4876 /* test new window without WS_SYSMENU style */
4877 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
4878 100, 100, 200, 200, 0, 0, 0, NULL
);
4879 ok(hwnd
!= 0, "Failed to create overlapped window\n");
4881 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4882 ok(!hmenu
, "GetSystemMenu error %d\n", GetLastError());
4884 DestroyWindow(hwnd
);
4887 /* For shown WS_OVERLAPPEDWINDOW */
4888 static const struct message WmSetIcon_1
[] = {
4889 { WM_SETICON
, sent
},
4890 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
4891 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4892 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
4896 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
4897 static const struct message WmSetIcon_2
[] = {
4898 { WM_SETICON
, sent
},
4902 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
4903 static const struct message WmInitEndSession
[] = {
4905 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4909 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
4910 static const struct message WmInitEndSession_2
[] = {
4912 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4916 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
4917 static const struct message WmInitEndSession_3
[] = {
4919 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4923 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
4924 static const struct message WmInitEndSession_4
[] = {
4926 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4930 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
4931 static const struct message WmInitEndSession_5
[] = {
4933 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
4937 static const struct message WmOptionalPaint
[] = {
4938 { WM_PAINT
, sent
|optional
},
4939 { WM_NCPAINT
, sent
|beginpaint
|optional
},
4940 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
4941 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
4945 static const struct message WmZOrder
[] = {
4946 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
4947 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
4948 { HCBT_ACTIVATE
, hook
},
4949 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
4950 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
4951 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
4952 { WM_GETTEXT
, sent
|optional
},
4953 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
4954 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
4955 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
4956 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4957 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4958 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
4959 { HCBT_SETFOCUS
, hook
},
4960 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
4961 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
4962 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
4963 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
4964 { WM_GETTEXT
, sent
|optional
},
4965 { WM_NCCALCSIZE
, sent
|optional
},
4969 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
4974 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
4979 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4980 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4982 PostMessageA(hwnd
, WM_USER
, 0, 0);
4984 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4985 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4987 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4988 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4990 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4991 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4993 PostMessageA(hwnd
, WM_USER
, 0, 0);
4995 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4996 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4998 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
4999 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5001 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
5002 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5003 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
5005 PostMessageA(hwnd
, WM_USER
, 0, 0);
5007 /* new incoming message causes it to become signaled again */
5008 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5009 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
5011 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5012 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5013 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5014 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5016 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
5017 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5018 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5019 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5021 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_INPUTAVAILABLE
);
5022 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5024 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5025 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5027 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
5028 ret
= QueueUserAPC( apc_test_proc
, GetCurrentThread(), 0 );
5029 ok(ret
, "QueueUserAPC failed %u\n", GetLastError());
5031 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, 0 );
5032 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5034 /* but even with MWMO_ALERTABLE window events are preferred */
5035 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5037 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5038 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5040 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5041 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5043 /* the APC call is still queued */
5044 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5045 ok(ret
== WAIT_IO_COMPLETION
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5048 static void test_WM_DEVICECHANGE(HWND hwnd
)
5053 static const WPARAM wparams
[] = {0,
5054 DBT_DEVNODES_CHANGED
,
5055 DBT_QUERYCHANGECONFIG
,
5057 DBT_CONFIGCHANGECANCELED
,
5060 DBT_CONFIGMGPRIVATE
, /* 0x7fff */
5061 DBT_DEVICEARRIVAL
, /* 0x8000 */
5062 DBT_DEVICEQUERYREMOVE
,
5063 DBT_DEVICEQUERYREMOVEFAILED
,
5064 DBT_DEVICEREMOVEPENDING
,
5065 DBT_DEVICEREMOVECOMPLETE
,
5066 DBT_DEVICETYPESPECIFIC
,
5069 for (i
= 0; i
< sizeof(wparams
)/sizeof(wparams
[0]); i
++)
5071 SetLastError(0xdeadbeef);
5072 ret
= PostMessageA(hwnd
, WM_DEVICECHANGE
, wparams
[i
], 0);
5073 if (wparams
[i
] & 0x8000)
5075 ok(ret
== FALSE
, "PostMessage should returned %d\n", ret
);
5076 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY
, "PostMessage error %08x\n", GetLastError());
5080 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5081 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
5082 memset(&msg
, 0, sizeof(msg
));
5083 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5084 ok(msg
.message
== WM_DEVICECHANGE
, "got %04x instead of WM_DEVICECHANGE\n", msg
.message
);
5089 static DWORD CALLBACK
show_window_thread(LPVOID arg
)
5093 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
5094 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5099 /* Helper function to easier test SetWindowPos messages */
5100 #define test_msg_setpos( expected_list, flags, todo ) \
5101 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
5102 static void test_msg_setpos_(const struct message
*expected_list
, UINT flags
, BOOL todo
, const char *file
, int line
)
5108 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5109 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5110 ok (hwnd
!= 0, "Failed to create popup window\n");
5111 SetWindowPos(hwnd
, NULL
, 0, 0, 100, 100, flags
);
5112 ok_sequence_(expected_list
, "SetWindowPos:show_popup_first_show_window", todo
, file
, line
);
5113 DestroyWindow(hwnd
);
5116 /* test if we receive the right sequence of messages */
5117 static void test_messages(void)
5121 HWND hwnd
, hparent
, hchild
;
5122 HWND hchild2
, hbutton
;
5131 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5132 100, 100, 200, 200, 0, 0, 0, NULL
);
5133 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5134 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5136 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5137 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
5138 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
5140 /* test WM_SETREDRAW on a not visible top level window */
5141 test_WM_SETREDRAW(hwnd
);
5143 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5145 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
5146 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
5148 ok(GetActiveWindow() == hwnd
, "window should be active\n");
5149 ok(GetFocus() == hwnd
, "window should have input focus\n");
5150 ShowWindow(hwnd
, SW_HIDE
);
5152 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5154 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5155 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5157 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5159 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5160 hthread
= CreateThread(NULL
, 0, show_window_thread
, hwnd
, 0, &tid
);
5161 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
5162 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5163 CloseHandle(hthread
);
5165 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5167 ShowWindow(hwnd
, SW_SHOW
);
5169 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
5171 ShowWindow(hwnd
, SW_HIDE
);
5173 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5175 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5177 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
5180 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
5182 ShowWindow(hwnd
, SW_RESTORE
);
5184 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5188 ShowWindow(hwnd
, SW_MINIMIZE
);
5190 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE
);
5193 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
5195 ShowWindow(hwnd
, SW_RESTORE
);
5197 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5201 ShowWindow(hwnd
, SW_SHOW
);
5203 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
5205 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5206 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
5207 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
5208 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
5210 /* test WM_SETREDRAW on a visible top level window */
5211 ShowWindow(hwnd
, SW_SHOW
);
5213 test_WM_SETREDRAW(hwnd
);
5215 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
5216 test_scroll_messages(hwnd
);
5218 /* test resizing and moving */
5219 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
5220 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
5223 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
5224 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
5227 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
5228 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
5232 /* popups don't get WM_GETMINMAXINFO */
5233 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
5234 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5236 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
5237 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
5239 DestroyWindow(hwnd
);
5240 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
5242 /* Test if windows are correctly drawn when first shown */
5244 /* Visible, redraw */
5247 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5248 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5249 ok (hwnd
!= 0, "Failed to create popup window\n");
5250 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5251 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_visible", FALSE
);
5252 DestroyWindow(hwnd
);
5254 /* Invisible, show, message */
5257 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5258 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5259 ok (hwnd
!= 0, "Failed to create popup window\n");
5260 ShowWindow(hwnd
, SW_SHOW
);
5261 SendMessageW(hwnd
, WM_PAINT
, 0, 0);
5262 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_show", FALSE
);
5263 DestroyWindow(hwnd
);
5265 /* Invisible, show maximized, redraw */
5268 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5269 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5270 ok (hwnd
!= 0, "Failed to create popup window\n");
5271 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5272 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5273 ok_sequence(WmShowPopupFirstDrawSeq_2
, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE
);
5274 DestroyWindow(hwnd
);
5276 /* Test SetWindowPos */
5277 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
, FALSE
);
5278 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, 0, FALSE
);
5279 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
,
5280 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_NOZORDER
, FALSE
);
5282 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOSIZE
, FALSE
);
5283 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOMOVE
, FALSE
);
5284 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTSIZE
, FALSE
);
5285 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTMOVE
, FALSE
);
5286 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOZORDER
, FALSE
);
5288 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
, FALSE
);
5289 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTMOVE
, FALSE
);
5290 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTSIZE
, FALSE
);
5291 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOMOVE
, FALSE
);
5292 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOSIZE
, FALSE
);
5293 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOZORDER
, FALSE
);
5295 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
, FALSE
);
5296 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTMOVE
, FALSE
);
5297 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTSIZE
, FALSE
);
5298 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOMOVE
, FALSE
);
5299 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOSIZE
, FALSE
);
5300 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOZORDER
, FALSE
);
5302 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
, FALSE
);
5303 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTMOVE
, FALSE
);
5304 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTSIZE
, FALSE
);
5305 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOMOVE
, FALSE
);
5306 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOSIZE
, FALSE
);
5307 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOZORDER
, FALSE
);
5309 /* Test SetWindowPos with child windows */
5311 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5312 100, 100, 200, 200, 0, 0, 0, NULL
);
5313 ok (hparent
!= 0, "Failed to create parent window\n");
5315 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5316 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5317 ok (hchild
!= 0, "Failed to create child window\n");
5319 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5320 ok_sequence(WmFirstDrawChildSeq1
, /* Expect no messages for the child */
5321 "SetWindowPos:show_popup_first_show_window_child1", FALSE
);
5322 DestroyWindow(hchild
);
5323 DestroyWindow(hparent
);
5326 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
,
5327 100, 100, 200, 200, 0, 0, 0, NULL
);
5328 ok (hparent
!= 0, "Failed to create parent window\n");
5330 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5331 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5332 ok (hchild
!= 0, "Failed to create child window\n");
5334 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5335 ok_sequence(WmFirstDrawChildSeq2
, /* Expect child to be redrawn */
5336 "SetWindowPos:show_popup_first_show_window_child2", FALSE
);
5337 DestroyWindow(hchild
);
5338 DestroyWindow(hparent
);
5340 /* Test message sequence for extreme position and size */
5343 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5344 -10, -10, 10000, 10000, NULL
, 0, 0, NULL
);
5345 ok (hwnd
!= 0, "Failed to create popup window\n");
5346 ok_sequence(WmShowPopupExtremeLocationSeq
, "RedrawWindow:show_popup_extreme_location", TRUE
);
5347 DestroyWindow(hwnd
);
5350 /* Test child windows */
5352 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5353 100, 100, 200, 200, 0, 0, 0, NULL
);
5354 ok (hparent
!= 0, "Failed to create parent window\n");
5357 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
5358 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5359 ok (hchild
!= 0, "Failed to create child window\n");
5360 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
5361 DestroyWindow(hchild
);
5364 /* visible child window with a caption */
5365 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
5366 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
5367 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5368 ok (hchild
!= 0, "Failed to create child window\n");
5369 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
5371 trace("testing scroll APIs on a visible child window %p\n", hchild
);
5372 test_scroll_messages(hchild
);
5374 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5375 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
5377 DestroyWindow(hchild
);
5380 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5381 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5382 ok (hchild
!= 0, "Failed to create child window\n");
5383 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5385 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
5386 100, 100, 50, 50, hparent
, 0, 0, NULL
);
5387 ok (hchild2
!= 0, "Failed to create child2 window\n");
5390 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
5391 0, 100, 50, 50, hchild
, 0, 0, NULL
);
5392 ok (hbutton
!= 0, "Failed to create button window\n");
5394 /* test WM_SETREDRAW on a not visible child window */
5395 test_WM_SETREDRAW(hchild
);
5397 ShowWindow(hchild
, SW_SHOW
);
5398 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5400 /* check parent messages too */
5401 log_all_parent_messages
++;
5402 ShowWindow(hchild
, SW_HIDE
);
5403 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
5404 log_all_parent_messages
--;
5406 ShowWindow(hchild
, SW_SHOW
);
5407 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5409 ShowWindow(hchild
, SW_HIDE
);
5410 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
5412 ShowWindow(hchild
, SW_SHOW
);
5413 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5415 /* test WM_SETREDRAW on a visible child window */
5416 test_WM_SETREDRAW(hchild
);
5418 log_all_parent_messages
++;
5419 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
5420 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
5421 log_all_parent_messages
--;
5423 ShowWindow(hchild
, SW_HIDE
);
5425 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5426 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
5428 ShowWindow(hchild
, SW_HIDE
);
5430 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
5431 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
5433 /* DestroyWindow sequence below expects that a child has focus */
5437 DestroyWindow(hchild
);
5438 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
5439 DestroyWindow(hchild2
);
5440 DestroyWindow(hbutton
);
5443 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
5444 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5445 ok (hchild
!= 0, "Failed to create child popup window\n");
5446 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
5447 DestroyWindow(hchild
);
5449 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5451 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
5452 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5453 ok (hchild
!= 0, "Failed to create popup window\n");
5454 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5455 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5456 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5458 ShowWindow(hchild
, SW_SHOW
);
5459 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5461 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5462 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5464 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5465 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
5466 DestroyWindow(hchild
);
5468 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5469 * changes nothing in message sequences.
5472 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5473 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5474 ok (hchild
!= 0, "Failed to create popup window\n");
5475 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5476 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5477 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5479 ShowWindow(hchild
, SW_SHOW
);
5480 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5482 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5483 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5484 DestroyWindow(hchild
);
5487 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
5488 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5489 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5490 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
5493 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
5494 test_scroll_messages(hwnd
);
5500 SendMessageA(hwnd
, WM_NULL
, 0, 0);
5503 after_end_dialog
= TRUE
;
5504 EndDialog( hwnd
, 0 );
5505 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
5507 DestroyWindow(hwnd
);
5508 after_end_dialog
= FALSE
;
5509 test_def_id
= FALSE
;
5511 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
5512 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5514 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
5515 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
5516 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5518 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
5519 ShowWindow(hwnd
, SW_SHOW
);
5520 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
5524 ret
= DrawMenuBar(hwnd
);
5525 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
5527 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5528 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
5530 DestroyWindow(hwnd
);
5532 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_CHILD
|WS_VISIBLE
,
5533 0, 0, 100, 100, hparent
, 0, GetModuleHandleA(0), NULL
);
5534 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5537 ret
= DrawMenuBar(hwnd
);
5538 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
5540 ok_sequence(WmEmptySeq
, "DrawMenuBar for a child window", FALSE
);
5542 DestroyWindow(hwnd
);
5545 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
5546 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
5548 DestroyWindow(hparent
);
5551 /* Message sequence for SetMenu */
5552 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
5553 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %d\n", GetLastError());
5554 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
5556 hmenu
= CreateMenu();
5557 ok (hmenu
!= 0, "Failed to create menu\n");
5558 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
5559 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5560 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
5561 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5562 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5563 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
5564 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5565 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
5566 ShowWindow(hwnd
, SW_SHOW
);
5567 UpdateWindow( hwnd
);
5570 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5571 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
5572 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
5573 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
5575 UpdateWindow( hwnd
);
5578 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
5580 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5582 DestroyWindow(hwnd
);
5585 /* Message sequence for EnableWindow */
5586 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5587 100, 100, 200, 200, 0, 0, 0, NULL
);
5588 ok (hparent
!= 0, "Failed to create parent window\n");
5589 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5590 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5591 ok (hchild
!= 0, "Failed to create child window\n");
5597 EnableWindow(hparent
, FALSE
);
5598 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
5600 EnableWindow(hparent
, FALSE
);
5601 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(FALSE)", FALSE
);
5603 EnableWindow(hparent
, TRUE
);
5604 ok_sequence(WmEnableWindowSeq_3
, "EnableWindow(TRUE)", FALSE
);
5606 EnableWindow(hparent
, TRUE
);
5607 ok_sequence(WmEnableWindowSeq_4
, "EnableWindow(TRUE)", FALSE
);
5612 test_MsgWaitForMultipleObjects(hparent
);
5613 test_WM_DEVICECHANGE(hparent
);
5615 /* the following test causes an exception in user.exe under win9x */
5616 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
5618 DestroyWindow(hparent
);
5622 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
5623 /* PeekMessage(NULL) fails, but still removes the message */
5624 SetLastError(0xdeadbeef);
5625 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
5626 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
5627 GetLastError() == 0xdeadbeef, /* NT4 */
5628 "last error is %d\n", GetLastError() );
5629 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
5630 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
5632 DestroyWindow(hchild
);
5633 DestroyWindow(hparent
);
5636 /* Message sequences for WM_SETICON */
5637 trace("testing WM_SETICON\n");
5638 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5639 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5641 ShowWindow(hwnd
, SW_SHOW
);
5645 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5646 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
5648 ShowWindow(hwnd
, SW_HIDE
);
5651 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5652 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
5653 DestroyWindow(hwnd
);
5656 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
5657 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5659 ShowWindow(hwnd
, SW_SHOW
);
5663 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5664 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
5666 ShowWindow(hwnd
, SW_HIDE
);
5669 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5670 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
5673 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
5676 todo_wine
win_skip( "Message 0x3b not supported\n" );
5679 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
5680 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res
);
5681 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
5682 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
5683 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res
);
5684 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
5685 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
5686 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res
);
5689 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
5690 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
5691 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res
);
5692 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
5693 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
5694 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res
);
5696 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
5697 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
5698 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res
);
5700 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
5701 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
5702 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res
);
5705 DestroyWindow(hwnd
);
5709 static void test_setwindowpos(void)
5714 const INT winX
= 100;
5715 const INT winY
= 100;
5716 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
5718 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
5719 0, 0, winX
, winY
, 0,
5722 GetWindowRect(hwnd
, &rc
);
5723 expect(sysX
, rc
.right
);
5724 expect(winY
, rc
.bottom
);
5728 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, winX
, winY
, 0);
5729 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
5730 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %ld\n", res
);
5732 GetWindowRect(hwnd
, &rc
);
5733 expect(sysX
, rc
.right
);
5734 expect(winY
, rc
.bottom
);
5735 DestroyWindow(hwnd
);
5738 static void invisible_parent_tests(void)
5740 HWND hparent
, hchild
;
5742 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
5743 100, 100, 200, 200, 0, 0, 0, NULL
);
5744 ok (hparent
!= 0, "Failed to create parent window\n");
5747 /* test showing child with hidden parent */
5749 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5750 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5751 ok (hchild
!= 0, "Failed to create child window\n");
5752 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5754 ShowWindow( hchild
, SW_MINIMIZE
);
5755 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5756 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5757 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5762 ShowWindow( hchild
, SW_MINIMIZE
);
5763 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5765 DestroyWindow(hchild
);
5766 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5767 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5770 ShowWindow( hchild
, SW_MAXIMIZE
);
5771 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5772 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5773 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5778 ShowWindow( hchild
, SW_MAXIMIZE
);
5779 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5781 DestroyWindow(hchild
);
5782 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5783 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5786 ShowWindow( hchild
, SW_RESTORE
);
5787 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
5788 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5789 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5791 DestroyWindow(hchild
);
5792 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5793 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5796 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5797 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5798 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5799 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5804 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5805 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5807 DestroyWindow(hchild
);
5808 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5809 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5812 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
5813 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
5814 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
5815 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5816 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5818 DestroyWindow(hchild
);
5819 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5820 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5823 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5824 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5825 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5826 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5831 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5832 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5834 DestroyWindow(hchild
);
5835 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5836 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5839 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
5840 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
5841 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
5843 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5845 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5847 DestroyWindow(hchild
);
5848 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5849 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5852 ShowWindow( hchild
, SW_SHOWNA
);
5853 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5854 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5855 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5860 ShowWindow( hchild
, SW_SHOWNA
);
5861 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5863 DestroyWindow(hchild
);
5864 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5865 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5868 ShowWindow( hchild
, SW_SHOW
);
5869 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5870 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5871 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5876 ShowWindow( hchild
, SW_SHOW
);
5877 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5879 ShowWindow( hchild
, SW_HIDE
);
5880 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
5881 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5882 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5884 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5885 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
5886 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5887 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5889 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5890 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
5891 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
5892 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5894 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5896 DestroyWindow(hchild
);
5897 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
5899 DestroyWindow(hparent
);
5903 /****************** button message test *************************/
5904 #define ID_BUTTON 0x000e
5906 static const struct message WmSetFocusButtonSeq
[] =
5908 { HCBT_SETFOCUS
, hook
},
5909 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5910 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5911 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5912 { WM_SETFOCUS
, sent
|wparam
, 0 },
5913 { WM_CTLCOLORBTN
, sent
|parent
},
5914 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5915 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5918 static const struct message WmKillFocusButtonSeq
[] =
5920 { HCBT_SETFOCUS
, hook
},
5921 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5922 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5923 { WM_CTLCOLORBTN
, sent
|parent
},
5924 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5925 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5926 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5927 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5929 { WM_CTLCOLORBTN
, sent
|parent
},
5932 static const struct message WmSetFocusStaticSeq
[] =
5934 { HCBT_SETFOCUS
, hook
},
5935 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5936 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5937 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5938 { WM_SETFOCUS
, sent
|wparam
, 0 },
5939 { WM_CTLCOLORSTATIC
, sent
|parent
},
5940 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5941 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
5942 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5945 static const struct message WmKillFocusStaticSeq
[] =
5947 { HCBT_SETFOCUS
, hook
},
5948 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5949 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5950 { WM_CTLCOLORSTATIC
, sent
|parent
},
5951 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5952 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5953 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5954 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5956 { WM_CTLCOLORSTATIC
, sent
|parent
},
5959 static const struct message WmSetFocusOwnerdrawSeq
[] =
5961 { HCBT_SETFOCUS
, hook
},
5962 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5963 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5964 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5965 { WM_SETFOCUS
, sent
|wparam
, 0 },
5966 { WM_CTLCOLORBTN
, sent
|parent
},
5967 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
5968 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5969 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5972 static const struct message WmKillFocusOwnerdrawSeq
[] =
5974 { HCBT_SETFOCUS
, hook
},
5975 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5976 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5977 { WM_CTLCOLORBTN
, sent
|parent
},
5978 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
5979 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5980 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5981 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5982 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5984 { WM_CTLCOLORBTN
, sent
|parent
},
5985 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
5988 static const struct message WmLButtonDownSeq
[] =
5990 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
5991 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
5992 { HCBT_SETFOCUS
, hook
},
5993 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5994 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5995 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5996 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5997 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5998 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
5999 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6000 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6003 static const struct message WmLButtonDownStaticSeq
[] =
6005 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6006 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
6007 { HCBT_SETFOCUS
, hook
},
6008 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6009 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6010 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6011 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6012 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6013 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6014 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6015 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6018 static const struct message WmLButtonUpSeq
[] =
6020 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6021 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6022 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6023 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6024 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6025 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6028 static const struct message WmLButtonUpStaticSeq
[] =
6030 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6031 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6032 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6033 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6034 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6035 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6038 static const struct message WmLButtonUpAutoSeq
[] =
6040 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6041 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6042 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6043 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6044 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6045 { BM_SETCHECK
, sent
|defwinproc
},
6046 { WM_CTLCOLORSTATIC
, sent
|defwinproc
, 0, 0 },
6047 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6050 static const struct message WmLButtonUpBrokenSeq
[] =
6052 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6055 static const struct message WmSetFontButtonSeq
[] =
6057 { WM_SETFONT
, sent
},
6059 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6060 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6061 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
6064 static const struct message WmSetFontStaticSeq
[] =
6066 { WM_SETFONT
, sent
},
6068 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6069 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6072 static const struct message WmSetTextButtonSeq
[] =
6074 { WM_SETTEXT
, sent
},
6075 { WM_CTLCOLORBTN
, sent
|parent
},
6076 { WM_CTLCOLORBTN
, sent
|parent
},
6077 { WM_COMMAND
, sent
|parent
|optional
},
6078 { WM_DRAWITEM
, sent
|parent
|optional
},
6081 static const struct message WmSetTextStaticSeq
[] =
6083 { WM_SETTEXT
, sent
},
6084 { WM_CTLCOLORSTATIC
, sent
|parent
},
6085 { WM_CTLCOLORSTATIC
, sent
|parent
},
6088 static const struct message WmSetTextGroupSeq
[] =
6090 { WM_SETTEXT
, sent
},
6091 { WM_CTLCOLORSTATIC
, sent
|parent
},
6092 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6093 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6096 static const struct message WmSetTextInvisibleSeq
[] =
6098 { WM_SETTEXT
, sent
},
6101 static const struct message WmSetStyleButtonSeq
[] =
6103 { BM_SETSTYLE
, sent
},
6104 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6106 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6107 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6108 { WM_CTLCOLORBTN
, sent
|parent
},
6111 static const struct message WmSetStyleStaticSeq
[] =
6113 { BM_SETSTYLE
, sent
},
6114 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6116 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6117 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6118 { WM_CTLCOLORSTATIC
, sent
|parent
},
6121 static const struct message WmSetStyleUserSeq
[] =
6123 { BM_SETSTYLE
, sent
},
6124 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6126 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6127 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6128 { WM_CTLCOLORBTN
, sent
|parent
},
6129 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
6132 static const struct message WmSetStyleOwnerdrawSeq
[] =
6134 { BM_SETSTYLE
, sent
},
6135 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6137 { WM_NCPAINT
, sent
|optional
}, /* FIXME: Wine sends it */
6138 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6139 { WM_CTLCOLORBTN
, sent
|parent
},
6140 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
6141 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6144 static const struct message WmSetStateButtonSeq
[] =
6146 { BM_SETSTATE
, sent
},
6147 { WM_CTLCOLORBTN
, sent
|parent
},
6148 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6151 static const struct message WmSetStateStaticSeq
[] =
6153 { BM_SETSTATE
, sent
},
6154 { WM_CTLCOLORSTATIC
, sent
|parent
},
6155 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6158 static const struct message WmSetStateUserSeq
[] =
6160 { BM_SETSTATE
, sent
},
6161 { WM_CTLCOLORBTN
, sent
|parent
},
6162 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
6163 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6166 static const struct message WmSetStateOwnerdrawSeq
[] =
6168 { BM_SETSTATE
, sent
},
6169 { WM_CTLCOLORBTN
, sent
|parent
},
6170 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
6171 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6174 static const struct message WmClearStateButtonSeq
[] =
6176 { BM_SETSTATE
, sent
},
6177 { WM_CTLCOLORBTN
, sent
|parent
},
6178 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
6179 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6182 static const struct message WmDisableButtonSeq
[] =
6184 { WM_LBUTTONDOWN
, sent
},
6185 { BM_SETSTATE
, sent
|defwinproc
},
6186 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6187 { WM_CTLCOLORBTN
, sent
|optional
},
6188 { WM_LBUTTONUP
, sent
},
6189 { BM_SETSTATE
, sent
|defwinproc
},
6190 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
},
6191 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6192 { BM_SETCHECK
, sent
|defwinproc
|optional
},
6193 { WM_CTLCOLORBTN
, sent
|optional
},
6194 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6195 { WM_CAPTURECHANGED
, sent
|defwinproc
},
6196 { WM_COMMAND
, sent
},
6199 static const struct message WmClearStateOwnerdrawSeq
[] =
6201 { BM_SETSTATE
, sent
},
6202 { WM_CTLCOLORBTN
, sent
|parent
},
6203 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
6204 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6207 static const struct message WmSetCheckIgnoredSeq
[] =
6209 { BM_SETCHECK
, sent
},
6210 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6213 static const struct message WmSetCheckStaticSeq
[] =
6215 { BM_SETCHECK
, sent
},
6216 { WM_CTLCOLORSTATIC
, sent
|parent
},
6217 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6221 static WNDPROC old_button_proc
;
6223 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6225 static LONG defwndproc_counter
= 0;
6227 struct recvd_message msg
;
6229 if (ignore_message( message
)) return 0;
6237 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
6239 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6245 MSG
*msg
= (MSG
*)lParam
;
6246 lParam
= MAKELPARAM(msg
->message
, msg
->wParam
);
6248 wParam
= (ULONG_PTR
)GetMenu(hwnd
);
6253 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6258 msg
.message
= message
;
6259 msg
.flags
= sent
|wparam
|lparam
;
6260 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6261 msg
.wParam
= wParam
;
6262 msg
.lParam
= lParam
;
6263 msg
.descr
= "button";
6267 defwndproc_counter
++;
6268 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
6269 defwndproc_counter
--;
6274 static void subclass_button(void)
6278 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
6280 old_button_proc
= cls
.lpfnWndProc
;
6282 cls
.hInstance
= GetModuleHandleA(NULL
);
6283 cls
.lpfnWndProc
= button_hook_proc
;
6284 cls
.lpszClassName
= "my_button_class";
6285 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6286 if (!RegisterClassA(&cls
)) assert(0);
6289 static void test_button_messages(void)
6295 const struct message
*setfocus
;
6296 const struct message
*killfocus
;
6297 const struct message
*setstyle
;
6298 const struct message
*setstate
;
6299 const struct message
*clearstate
;
6300 const struct message
*setcheck
;
6301 const struct message
*lbuttondown
;
6302 const struct message
*lbuttonup
;
6303 const struct message
*setfont
;
6304 const struct message
*settext
;
6306 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6307 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6308 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6309 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6310 WmSetTextButtonSeq
},
6311 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
6312 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6313 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6314 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6315 WmSetTextButtonSeq
},
6316 { BS_CHECKBOX
, DLGC_BUTTON
,
6317 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6318 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6319 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6320 WmSetTextStaticSeq
},
6321 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
6322 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6323 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6324 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6325 WmSetTextStaticSeq
},
6326 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6327 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6328 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6329 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6330 WmSetTextStaticSeq
},
6331 { BS_3STATE
, DLGC_BUTTON
,
6332 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6333 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6334 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6335 WmSetTextStaticSeq
},
6336 { BS_AUTO3STATE
, DLGC_BUTTON
,
6337 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6338 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6339 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6340 WmSetTextStaticSeq
},
6341 { BS_GROUPBOX
, DLGC_STATIC
,
6342 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6343 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
,
6344 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6345 WmSetTextGroupSeq
},
6346 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6347 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
6348 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
,
6349 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6350 WmSetTextButtonSeq
},
6351 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6352 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6353 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6354 NULL
/* avoid infinite loop */, WmLButtonUpBrokenSeq
, WmSetFontStaticSeq
,
6355 WmSetTextStaticSeq
},
6356 { BS_OWNERDRAW
, DLGC_BUTTON
,
6357 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
6358 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
,
6359 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6360 WmSetTextButtonSeq
},
6362 LOGFONTA logfont
= { 0 };
6363 HFONT zfont
, hfont2
;
6368 /* selection with VK_SPACE should capture button window */
6369 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
6370 0, 0, 50, 14, 0, 0, 0, NULL
);
6371 ok(hwnd
!= 0, "Failed to create button window\n");
6374 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
6375 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6376 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
6377 DestroyWindow(hwnd
);
6381 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6382 100, 100, 200, 200, 0, 0, 0, NULL
);
6383 ok(parent
!= 0, "Failed to create parent window\n");
6385 memset(&logfont
, 0, sizeof(logfont
));
6386 logfont
.lfHeight
= -12;
6387 logfont
.lfWeight
= FW_NORMAL
;
6388 strcpy(logfont
.lfFaceName
, "Tahoma");
6390 hfont2
= CreateFontIndirectA(&logfont
);
6391 ok(hfont2
!= NULL
, "Failed to create Tahoma font\n");
6393 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
6401 trace("button style %08x\n", button
[i
].style
);
6403 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
6404 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
6405 ok(hwnd
!= 0, "Failed to create button window\n");
6407 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6408 style
&= ~(WS_CHILD
| BS_NOTIFY
);
6409 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6410 if (button
[i
].style
== BS_USERBUTTON
)
6411 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %x\n", style
);
6413 ok(style
== button
[i
].style
, "expected style %x got %x\n", button
[i
].style
, style
);
6415 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
6416 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
6418 ShowWindow(hwnd
, SW_SHOW
);
6425 log_all_parent_messages
++;
6427 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6429 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6430 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6431 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
6434 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6435 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6436 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
6438 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6440 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
6441 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6442 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6443 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
6445 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6446 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
6447 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
6448 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6450 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6451 ok(state
== 0, "expected state 0, got %04x\n", state
);
6455 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
6456 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6457 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6458 ok_sequence(button
[i
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
6460 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6461 ok(state
== 0x0004, "expected state 0x0004, got %04x\n", state
);
6463 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6464 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6465 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6469 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
6470 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6471 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6472 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
6474 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6475 ok(state
== 0, "expected state 0, got %04x\n", state
);
6477 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6478 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6479 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6481 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6482 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
6486 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
6487 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6488 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6489 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
6491 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6492 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
6494 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6495 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6496 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6500 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
6501 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6502 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6503 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
6505 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 1");
6506 sprintf(desc
, "button[%i]: WM_SETTEXT on a visible button", i
);
6507 ok_sequence(button
[i
].settext
, desc
, FALSE
);
6509 ShowWindow(hwnd
, SW_HIDE
);
6513 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 2");
6514 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6515 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6517 ShowWindow(hwnd
, SW_SHOW
);
6518 ShowWindow(parent
, SW_HIDE
);
6522 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 3");
6523 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6524 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6526 ShowWindow(parent
, SW_SHOW
);
6529 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6530 if (button
[i
].style
== BS_PUSHBUTTON
||
6531 button
[i
].style
== BS_DEFPUSHBUTTON
||
6532 button
[i
].style
== BS_GROUPBOX
||
6533 button
[i
].style
== BS_USERBUTTON
||
6534 button
[i
].style
== BS_OWNERDRAW
)
6535 ok(state
== BST_UNCHECKED
, "expected check 0, got %04x\n", state
);
6537 ok(state
== BST_CHECKED
, "expected check 1, got %04x\n", state
);
6539 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6540 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6541 if (button
[i
].style
== BS_RADIOBUTTON
||
6542 button
[i
].style
== BS_AUTORADIOBUTTON
)
6543 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04x | WS_TABSTOP got %04x\n", button
[i
].style
, style
);
6545 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6547 log_all_parent_messages
--;
6549 DestroyWindow(hwnd
);
6551 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
6552 0, 0, 50, 14, 0, 0, 0, NULL
);
6553 ok(hwnd
!= 0, "Failed to create button window\n");
6555 SetForegroundWindow(hwnd
);
6558 SetActiveWindow(hwnd
);
6562 if (button
[i
].lbuttondown
)
6564 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
6565 sprintf(desc
, "button[%i]: WM_LBUTTONDOWN on a button", i
);
6566 ok_sequence(button
[i
].lbuttondown
, desc
, FALSE
);
6569 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
6570 sprintf(desc
, "button[%i]: WM_LBUTTONUP on a button", i
);
6571 ok_sequence(button
[i
].lbuttonup
, desc
, FALSE
);
6574 zfont
= GetStockObject(DEFAULT_GUI_FONT
);
6575 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
6577 sprintf(desc
, "button[%i]: WM_SETFONT on a button", i
);
6578 ok_sequence(button
[i
].setfont
, desc
, FALSE
);
6580 /* Test that original font is not selected back after painting */
6581 hdc
= CreateCompatibleDC(0);
6583 prevfont
= SelectObject(hdc
, hfont2
);
6584 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
6585 SendMessageA(hwnd
, WM_PRINTCLIENT
, (WPARAM
)hdc
, 0);
6586 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i
);
6587 SelectObject(hdc
, prevfont
);
6589 prevfont
= SelectObject(hdc
, hfont2
);
6590 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
6591 SendMessageA(hwnd
, WM_PAINT
, (WPARAM
)hdc
, 0);
6592 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PAINT\n", i
);
6593 SelectObject(hdc
, prevfont
);
6597 DestroyWindow(hwnd
);
6600 DeleteObject(hfont2
);
6601 DestroyWindow(parent
);
6603 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
6605 parent
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6606 100, 100, 200, 200, 0, 0, 0, NULL
);
6607 ok (hwnd
!= 0, "Failed to create overlapped window\n");
6609 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON
| WS_VISIBLE
| WS_CHILD
,
6610 0, 0, 50, 14, parent
, 0, 0, NULL
);
6612 EnableWindow(hwnd
, FALSE
);
6614 SendMessageA(hwnd
, WM_LBUTTONDOWN
, MK_LBUTTON
, 0);
6615 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
6616 ok_sequence(WmDisableButtonSeq
, "Mouseclick on a disabled button", FALSE
);
6618 DestroyWindow(hwnd
);
6619 DestroyWindow(parent
);
6622 #define ID_RADIO1 501
6623 #define ID_RADIO2 502
6624 #define ID_RADIO3 503
6627 static const struct message auto_radio_button_BM_CLICK
[] =
6629 { BM_CLICK
, sent
|wparam
|lparam
, 0, 0 },
6630 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6631 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
6632 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
6633 { WM_CTLCOLORSTATIC
, sent
|parent
},
6634 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6635 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6636 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
6637 { WM_CTLCOLORSTATIC
, sent
|parent
},
6638 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6639 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
6640 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
6641 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
6642 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO1
},
6643 { WM_CTLCOLORSTATIC
, sent
|parent
},
6644 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6645 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
6646 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO3
},
6647 { WM_CTLCOLORSTATIC
, sent
|parent
},
6648 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6649 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
6650 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6651 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6652 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO2
, BN_CLICKED
) },
6653 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6654 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6655 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6659 static const struct message auto_radio_button_VK_UP_child
[] =
6661 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_UP
, 0 },
6662 { WM_KEYUP
, sent
|wparam
|lparam
, VK_UP
, 0 },
6666 static const struct message auto_radio_button_VK_UP_parent
[] =
6668 { WM_KEYDOWN
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
6669 { WM_KEYUP
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
6673 static const struct message auto_radio_button_VK_UP_dialog
[] =
6675 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6677 /* optional trailer seen on some windows setups */
6678 { WM_CHANGEUISTATE
, sent
|optional
},
6679 { WM_UPDATEUISTATE
, sent
|optional
},
6680 { WM_UPDATEUISTATE
, sent
|optional
},
6681 { WM_UPDATEUISTATE
, sent
|optional
},
6682 { WM_UPDATEUISTATE
, sent
|optional
},
6683 { WM_UPDATEUISTATE
, sent
|optional
},
6684 { WM_UPDATEUISTATE
, sent
|optional
},
6685 { WM_UPDATEUISTATE
, sent
|optional
},
6686 { WM_UPDATEUISTATE
, sent
|optional
},
6687 { WM_UPDATEUISTATE
, sent
|optional
},
6688 { WM_UPDATEUISTATE
, sent
|optional
},
6689 { WM_UPDATEUISTATE
, sent
|optional
},
6690 { WM_UPDATEUISTATE
, sent
|optional
},
6691 { WM_UPDATEUISTATE
, sent
|optional
},
6692 { WM_UPDATEUISTATE
, sent
|optional
},
6693 { WM_UPDATEUISTATE
, sent
|optional
},
6694 { WM_UPDATEUISTATE
, sent
|optional
},
6695 { WM_UPDATEUISTATE
, sent
|optional
},
6696 { WM_UPDATEUISTATE
, sent
|optional
},
6697 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6698 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6699 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6700 { WM_UPDATEUISTATE
, sent
|optional
},
6701 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6702 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6703 { WM_UPDATEUISTATE
, sent
|optional
},
6704 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
6705 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
6706 { WM_UPDATEUISTATE
, sent
|optional
},
6707 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6708 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6712 static const struct message auto_radio_button_VK_DOWN_dialog
[] =
6714 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6715 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
6716 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6717 { HCBT_SETFOCUS
, hook
},
6718 { WM_KILLFOCUS
, sent
, 0, 0 },
6719 { WM_CTLCOLORSTATIC
, sent
|parent
},
6720 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO3
, BN_KILLFOCUS
) },
6721 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6722 { WM_SETFOCUS
, sent
, 0, 0 },
6723 { WM_CTLCOLORSTATIC
, sent
|parent
},
6724 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_SETFOCUS
) },
6725 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
6726 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6727 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6728 { DM_GETDEFID
, sent
|parent
, 0, 0 },
6729 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
6730 { BM_CLICK
, sent
|wparam
|lparam
, 1, 0 },
6731 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6732 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
6733 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
6734 { WM_CTLCOLORSTATIC
, sent
|parent
},
6735 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6736 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6737 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO1
},
6738 { WM_CTLCOLORSTATIC
, sent
|parent
},
6739 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6740 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
6741 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
6742 { WM_CTLCOLORSTATIC
, sent
|parent
},
6743 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6744 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
6745 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO3
},
6746 { WM_CTLCOLORSTATIC
, sent
|parent
},
6747 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6748 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
6749 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
6750 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
6751 { WM_CTLCOLORSTATIC
, sent
|parent
},
6752 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6753 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6754 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6755 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
6756 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6757 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6758 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6760 { WM_CTLCOLORSTATIC
, sent
|parent
},
6764 static const struct message auto_radio_button_VK_DOWN_radio3
[] =
6766 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
6767 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO2
},
6768 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO3
},
6769 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6770 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
6771 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6772 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6773 { WM_GETDLGCODE
, sent
|wparam
|lparam
|parent
, 0, 0 },
6774 { WM_USER
, sent
|parent
, 0, 0 },
6775 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
6779 static const struct message auto_radio_button_VK_UP_radio1
[] =
6781 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6785 static INT_PTR WINAPI
radio_test_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
6787 ParentMsgCheckProcA(hwnd
, msg
, wp
, lp
);
6791 static void test_autoradio_BM_CLICK(void)
6793 HWND parent
, radio1
, radio2
, radio3
;
6800 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc
, 0);
6801 ok(parent
!= 0, "failed to create parent window\n");
6803 radio1
= GetDlgItem(parent
, ID_RADIO1
);
6804 radio2
= GetDlgItem(parent
, ID_RADIO2
);
6805 radio3
= GetDlgItem(parent
, ID_RADIO3
);
6807 /* this avoids focus messages in the generated sequence */
6813 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6814 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6815 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6816 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6817 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6818 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6820 SendMessageA(radio1
, BM_SETCHECK
, BST_CHECKED
, 0);
6822 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6823 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6824 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6825 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6826 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6827 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6829 SendMessageA(radio2
, BM_SETCHECK
, BST_CHECKED
, 0);
6831 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6832 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6833 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6834 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6835 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6836 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6838 SendMessageA(radio3
, BM_SETCHECK
, BST_CHECKED
, 0);
6840 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6841 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6842 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6843 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6844 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6845 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6847 GetWindowRect(radio2
, &rc
);
6848 SetCursorPos(rc
.left
+1, rc
.top
+1);
6853 log_all_parent_messages
++;
6855 SendMessageA(radio2
, BM_CLICK
, 0, 0);
6856 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6857 ok_sequence(auto_radio_button_BM_CLICK
, "BM_CLICK on auto-radio button", FALSE
);
6859 log_all_parent_messages
--;
6861 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6862 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6863 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6864 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6865 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6866 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6868 DestroyWindow(parent
);
6871 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)
6872 static void test_radio_dbg(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
, int line
)
6876 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6877 ok_(__FILE__
,line
)(ret
== state1
? BST_CHECKED
: BST_UNCHECKED
, "got %08x\n", ret
);
6878 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6879 ok_(__FILE__
,line
)(ret
== state2
? BST_CHECKED
: BST_UNCHECKED
, "got %08x\n", ret
);
6880 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6881 ok_(__FILE__
,line
)(ret
== state3
? BST_CHECKED
: BST_UNCHECKED
, "got %08x\n", ret
);
6884 static void set_radio(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
)
6886 SendMessageA(radio1
, BM_SETCHECK
, state1
? BST_CHECKED
: BST_UNCHECKED
, 0);
6887 SendMessageA(radio2
, BM_SETCHECK
, state2
? BST_CHECKED
: BST_UNCHECKED
, 0);
6888 SendMessageA(radio3
, BM_SETCHECK
, state3
? BST_CHECKED
: BST_UNCHECKED
, 0);
6891 static void test_autoradio_kbd_move(void)
6893 HWND parent
, radio1
, radio2
, radio3
, hwnd
;
6900 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc
, 0);
6901 ok(parent
!= 0, "failed to create parent window\n");
6903 radio1
= GetDlgItem(parent
, ID_RADIO1
);
6904 radio2
= GetDlgItem(parent
, ID_RADIO2
);
6905 radio3
= GetDlgItem(parent
, ID_RADIO3
);
6910 test_radio(radio1
, 0, radio2
, 0, radio3
, 0);
6911 set_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6912 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6919 log_all_parent_messages
++;
6921 SendMessageA(radio3
, WM_KEYDOWN
, VK_UP
, 0);
6922 SendMessageA(radio3
, WM_KEYUP
, VK_UP
, 0);
6923 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6924 ok_sequence(auto_radio_button_VK_UP_child
, "press/release VK_UP on auto-radio button", FALSE
);
6926 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6931 DefDlgProcA(parent
, WM_KEYDOWN
, VK_UP
, 0);
6932 DefDlgProcA(parent
, WM_KEYUP
, VK_UP
, 0);
6933 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6934 ok_sequence(auto_radio_button_VK_UP_parent
, "press/release VK_UP on dialog", FALSE
);
6936 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6939 GetWindowRect(radio3
, &rc
);
6945 msg
.message
= WM_KEYDOWN
;
6948 msg
.pt
.x
= rc
.left
+ 1;
6949 msg
.pt
.y
= rc
.top
+ 1;
6950 ret
= IsDialogMessageA(parent
, &msg
);
6951 ok(ret
, "IsDialogMessage should return TRUE\n");
6952 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6953 if (0) /* actual message sequence is different on every run in some Windows setups */
6954 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #1", FALSE
);
6955 /* what really matters is that nothing has changed */
6956 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6958 set_radio(radio1
, 0, radio2
, 1, radio3
, 1);
6959 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
6964 ret
= IsDialogMessageA(parent
, &msg
);
6965 ok(ret
, "IsDialogMessage should return TRUE\n");
6966 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6967 if (0) /* actual message sequence is different on every run in some Windows setups */
6968 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #2", FALSE
);
6969 /* what really matters is that nothing has changed */
6970 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
6972 /* switch from radio3 ro radio1 */
6974 GetWindowRect(radio3
, &rc
);
6980 msg
.message
= WM_KEYDOWN
;
6981 msg
.wParam
= VK_DOWN
;
6983 msg
.pt
.x
= rc
.left
+ 1;
6984 msg
.pt
.y
= rc
.top
+ 1;
6985 ret
= IsDialogMessageA(parent
, &msg
);
6986 ok(ret
, "IsDialogMessage should return TRUE\n");
6987 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6988 ok_sequence(auto_radio_button_VK_DOWN_dialog
, "IsDialogMessage(VK_DOWN)", TRUE
);
6990 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
6993 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
6994 GetWindowRect(radio1
, &rc
);
6997 msg
.message
= WM_KEYDOWN
;
6998 msg
.wParam
= VK_DOWN
;
7000 msg
.pt
.x
= rc
.left
+ 1;
7001 msg
.pt
.y
= rc
.top
+ 1;
7002 ret
= IsDialogMessageA(parent
, &msg
);
7003 ok(ret
, "IsDialogMessage should return TRUE\n");
7004 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7005 ok_sequence(auto_radio_button_VK_DOWN_radio3
, "down to radio3", TRUE
);
7007 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7010 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7016 msg
.message
= WM_KEYDOWN
;
7019 msg
.pt
.x
= rc
.left
+ 1;
7020 msg
.pt
.y
= rc
.top
+ 1;
7021 ret
= IsDialogMessageA(parent
, &msg
);
7022 ok(ret
, "IsDialogMessage should return TRUE\n");
7023 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7024 ok_sequence(auto_radio_button_VK_UP_radio1
, "up to radio1", TRUE
);
7026 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7029 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7035 msg
.message
= WM_KEYDOWN
;
7038 msg
.pt
.x
= rc
.left
+ 1;
7039 msg
.pt
.y
= rc
.top
+ 1;
7040 ret
= IsDialogMessageA(parent
, &msg
);
7041 ok(ret
, "IsDialogMessage should return TRUE\n");
7042 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7043 if (0) /* actual message sequence is different on every run in some Windows setups */
7044 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #3", FALSE
);
7045 /* what really matters is that nothing has changed */
7046 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7048 log_all_parent_messages
--;
7050 DestroyWindow(parent
);
7053 /****************** static message test *************************/
7054 static const struct message WmSetFontStaticSeq2
[] =
7056 { WM_SETFONT
, sent
},
7057 { WM_PAINT
, sent
|defwinproc
|optional
},
7058 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
7059 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
7063 static WNDPROC old_static_proc
;
7065 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7067 static LONG defwndproc_counter
= 0;
7069 struct recvd_message msg
;
7071 if (ignore_message( message
)) return 0;
7074 msg
.message
= message
;
7075 msg
.flags
= sent
|wparam
|lparam
;
7076 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7077 msg
.wParam
= wParam
;
7078 msg
.lParam
= lParam
;
7079 msg
.descr
= "static";
7082 defwndproc_counter
++;
7083 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
7084 defwndproc_counter
--;
7089 static void subclass_static(void)
7093 if (!GetClassInfoA(0, "static", &cls
)) assert(0);
7095 old_static_proc
= cls
.lpfnWndProc
;
7097 cls
.hInstance
= GetModuleHandleA(NULL
);
7098 cls
.lpfnWndProc
= static_hook_proc
;
7099 cls
.lpszClassName
= "my_static_class";
7100 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7101 if (!RegisterClassA(&cls
)) assert(0);
7104 static void test_static_messages(void)
7106 /* FIXME: make as comprehensive as the button message test */
7111 const struct message
*setfont
;
7113 { SS_LEFT
, DLGC_STATIC
,
7114 WmSetFontStaticSeq2
}
7122 for (i
= 0; i
< sizeof(static_ctrl
)/sizeof(static_ctrl
[0]); i
++)
7124 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
7125 0, 0, 50, 14, 0, 0, 0, NULL
);
7126 ok(hwnd
!= 0, "Failed to create static window\n");
7128 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
7129 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
7131 ShowWindow(hwnd
, SW_SHOW
);
7136 trace("static style %08x\n", static_ctrl
[i
].style
);
7137 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
7138 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
7140 DestroyWindow(hwnd
);
7144 /****************** ComboBox message test *************************/
7145 #define ID_COMBOBOX 0x000f
7147 static const struct message SetCurSelComboSeq
[] =
7149 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7150 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7151 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7152 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7153 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7154 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7155 { LB_GETTEXT
, sent
|wparam
, 0 },
7156 { WM_CTLCOLOREDIT
, sent
|parent
},
7157 { LB_GETITEMDATA
, sent
|wparam
|lparam
, 0, 0 },
7158 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_COMBOBOX
, 0x100010f3 },
7162 static const struct message SetCurSelComboSeq2
[] =
7164 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7165 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7166 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7167 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7168 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7169 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7170 { LB_GETTEXT
, sent
|wparam
, 0 },
7174 static const struct message SetCurSelComboSeq_edit
[] =
7176 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7177 { WM_SETTEXT
, sent
|wparam
, 0 },
7178 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
7182 static const struct message WmKeyDownComboSeq
[] =
7184 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7185 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
7186 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
7187 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
7188 { WM_CTLCOLOREDIT
, sent
|parent
},
7189 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7193 static const struct message WmSetPosComboSeq
[] =
7195 { WM_WINDOWPOSCHANGING
, sent
},
7196 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
7197 { WM_CHILDACTIVATE
, sent
},
7198 { WM_WINDOWPOSCHANGED
, sent
},
7199 { WM_MOVE
, sent
|defwinproc
},
7200 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7201 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
7202 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
7203 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
7204 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7208 static const struct message WMSetFocusComboBoxSeq
[] =
7210 { WM_SETFOCUS
, sent
},
7211 { WM_KILLFOCUS
, sent
|parent
},
7212 { WM_SETFOCUS
, sent
},
7213 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7214 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7215 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7216 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7217 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7221 static const struct message SetFocusButtonSeq
[] =
7223 { WM_KILLFOCUS
, sent
},
7224 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7225 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7226 { WM_LBUTTONUP
, sent
|defwinproc
},
7227 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7228 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7229 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7230 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7231 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7232 { WM_CTLCOLORBTN
, sent
|parent
},
7236 static const struct message SetFocusComboBoxSeq
[] =
7238 { WM_CTLCOLORBTN
, sent
|parent
},
7239 { WM_SETFOCUS
, sent
},
7240 { WM_KILLFOCUS
, sent
|defwinproc
},
7241 { WM_SETFOCUS
, sent
},
7242 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7243 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7244 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7245 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7246 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7250 static const struct message SetFocusButtonSeq2
[] =
7252 { WM_KILLFOCUS
, sent
},
7253 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7254 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7255 { WM_LBUTTONUP
, sent
|defwinproc
},
7256 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7257 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7258 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
7259 { WM_CTLCOLOREDIT
, sent
|parent
},
7260 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7261 { WM_CTLCOLORBTN
, sent
|parent
},
7265 static WNDPROC old_combobox_proc
, edit_window_proc
, lbox_window_proc
;
7267 static LRESULT CALLBACK
combobox_edit_subclass_proc(HWND hwnd
, UINT message
,
7268 WPARAM wParam
, LPARAM lParam
)
7270 static LONG defwndproc_counter
= 0;
7272 struct recvd_message msg
;
7274 /* do not log painting messages */
7275 if (message
!= WM_PAINT
&&
7276 message
!= WM_NCPAINT
&&
7277 message
!= WM_SYNCPAINT
&&
7278 message
!= WM_ERASEBKGND
&&
7279 message
!= WM_NCHITTEST
&&
7280 message
!= WM_GETTEXT
&&
7281 !ignore_message( message
))
7284 msg
.message
= message
;
7285 msg
.flags
= sent
|wparam
|lparam
;
7286 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7287 msg
.wParam
= wParam
;
7288 msg
.lParam
= lParam
;
7289 msg
.descr
= "combo edit";
7293 defwndproc_counter
++;
7294 ret
= CallWindowProcA(edit_window_proc
, hwnd
, message
, wParam
, lParam
);
7295 defwndproc_counter
--;
7300 static LRESULT CALLBACK
combobox_lbox_subclass_proc(HWND hwnd
, UINT message
,
7301 WPARAM wParam
, LPARAM lParam
)
7303 static LONG defwndproc_counter
= 0;
7305 struct recvd_message msg
;
7307 /* do not log painting messages */
7308 if (message
!= WM_PAINT
&&
7309 message
!= WM_NCPAINT
&&
7310 message
!= WM_SYNCPAINT
&&
7311 message
!= WM_ERASEBKGND
&&
7312 message
!= WM_NCHITTEST
&&
7313 !ignore_message( message
))
7316 msg
.message
= message
;
7317 msg
.flags
= sent
|wparam
|lparam
;
7318 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7319 msg
.wParam
= wParam
;
7320 msg
.lParam
= lParam
;
7321 msg
.descr
= "combo lbox";
7325 defwndproc_counter
++;
7326 ret
= CallWindowProcA(lbox_window_proc
, hwnd
, message
, wParam
, lParam
);
7327 defwndproc_counter
--;
7332 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7334 static LONG defwndproc_counter
= 0;
7336 struct recvd_message msg
;
7338 /* do not log painting messages */
7339 if (message
!= WM_PAINT
&&
7340 message
!= WM_NCPAINT
&&
7341 message
!= WM_SYNCPAINT
&&
7342 message
!= WM_ERASEBKGND
&&
7343 message
!= WM_NCHITTEST
&&
7344 message
!= WM_GETTEXT
&&
7345 !ignore_message( message
))
7348 msg
.message
= message
;
7349 msg
.flags
= sent
|wparam
|lparam
;
7350 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7351 msg
.wParam
= wParam
;
7352 msg
.lParam
= lParam
;
7353 msg
.descr
= "combo";
7357 defwndproc_counter
++;
7358 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
7359 defwndproc_counter
--;
7364 static void subclass_combobox(void)
7368 if (!GetClassInfoA(0, "ComboBox", &cls
)) assert(0);
7370 old_combobox_proc
= cls
.lpfnWndProc
;
7372 cls
.hInstance
= GetModuleHandleA(NULL
);
7373 cls
.lpfnWndProc
= combobox_hook_proc
;
7374 cls
.lpszClassName
= "my_combobox_class";
7375 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7376 if (!RegisterClassA(&cls
)) assert(0);
7379 static void test_combobox_messages(void)
7381 HWND parent
, combo
, button
, edit
, lbox
;
7383 COMBOBOXINFO cbInfo
;
7386 subclass_combobox();
7388 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7389 100, 100, 200, 200, 0, 0, 0, NULL
);
7390 ok(parent
!= 0, "Failed to create parent window\n");
7393 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
7394 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
7395 ok(combo
!= 0, "Failed to create combobox window\n");
7397 UpdateWindow(combo
);
7399 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
7400 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", ret
);
7402 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
7403 ok(ret
== 0, "expected 0, got %ld\n", ret
);
7404 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
7405 ok(ret
== 1, "expected 1, got %ld\n", ret
);
7406 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
7407 ok(ret
== 2, "expected 2, got %ld\n", ret
);
7409 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
7413 log_all_parent_messages
++;
7414 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
7415 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
7416 log_all_parent_messages
--;
7417 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
7420 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
7421 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
7423 DestroyWindow(combo
);
7424 DestroyWindow(parent
);
7426 /* Start again. Test combobox text selection when getting and losing focus */
7427 parent
= CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7428 10, 10, 300, 300, NULL
, NULL
, NULL
, NULL
);
7429 ok(parent
!= 0, "Failed to create parent window\n");
7431 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWN
,
7432 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
7433 ok(combo
!= 0, "Failed to create combobox window\n");
7435 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
7436 SetLastError(0xdeadbeef);
7437 res
= GetComboBoxInfo(combo
, &cbInfo
);
7438 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError());
7439 edit
= cbInfo
.hwndItem
;
7441 edit_window_proc
= (WNDPROC
)SetWindowLongPtrA(edit
, GWLP_WNDPROC
,
7442 (ULONG_PTR
)combobox_edit_subclass_proc
);
7444 button
= CreateWindowExA(0, "Button", "OK", WS_CHILD
| WS_VISIBLE
| BS_DEFPUSHBUTTON
,
7445 5, 50, 100, 20, parent
, NULL
,
7446 (HINSTANCE
)GetWindowLongPtrA(parent
, GWLP_HINSTANCE
), NULL
);
7447 ok(button
!= 0, "Failed to create button window\n");
7450 log_all_parent_messages
++;
7451 SendMessageA(combo
, WM_SETFOCUS
, 0, (LPARAM
)edit
);
7452 log_all_parent_messages
--;
7453 ok_sequence(WMSetFocusComboBoxSeq
, "WM_SETFOCUS on a ComboBox", TRUE
);
7456 log_all_parent_messages
++;
7458 log_all_parent_messages
--;
7459 ok_sequence(SetFocusButtonSeq
, "SetFocus on a Button", TRUE
);
7461 SendMessageA(combo
, WM_SETTEXT
, 0, (LPARAM
)"Wine Test");
7464 log_all_parent_messages
++;
7466 log_all_parent_messages
--;
7467 ok_sequence(SetFocusComboBoxSeq
, "SetFocus on a ComboBox", TRUE
);
7470 log_all_parent_messages
++;
7472 log_all_parent_messages
--;
7473 ok_sequence(SetFocusButtonSeq2
, "SetFocus on a Button (2)", TRUE
);
7476 SendMessageA(combo
, WM_SETREDRAW
, FALSE
, 0);
7478 log_all_parent_messages
++;
7479 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
7480 log_all_parent_messages
--;
7481 ok_sequence(SetCurSelComboSeq_edit
, "CB_SETCURSEL on a ComboBox with edit control", FALSE
);
7483 DestroyWindow(button
);
7484 DestroyWindow(combo
);
7486 combo
= CreateWindowExA(0, "my_combobox_class", "test",
7487 WS_CHILD
| WS_VISIBLE
| CBS_OWNERDRAWFIXED
| CBS_DROPDOWNLIST
,
7488 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
7489 ok(combo
!= 0, "Failed to create combobox window\n");
7491 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
7492 ok(ret
== 0, "expected 0, got %ld\n", ret
);
7494 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
7495 SetLastError(0xdeadbeef);
7496 res
= GetComboBoxInfo(combo
, &cbInfo
);
7497 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError());
7498 lbox
= cbInfo
.hwndList
;
7499 lbox_window_proc
= (WNDPROC
)SetWindowLongPtrA(lbox
, GWLP_WNDPROC
,
7500 (ULONG_PTR
)combobox_lbox_subclass_proc
);
7503 log_all_parent_messages
++;
7504 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
7505 log_all_parent_messages
--;
7506 ok_sequence(SetCurSelComboSeq
, "CB_SETCURSEL on a ComboBox", FALSE
);
7508 ShowWindow(combo
, SW_HIDE
);
7510 log_all_parent_messages
++;
7511 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
7512 log_all_parent_messages
--;
7513 ok_sequence(SetCurSelComboSeq2
, "CB_SETCURSEL on a ComboBox", FALSE
);
7515 DestroyWindow(combo
);
7516 DestroyWindow(parent
);
7519 /****************** WM_IME_KEYDOWN message test *******************/
7521 static const struct message WmImeKeydownMsgSeq_0
[] =
7523 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
7524 { WM_CHAR
, wparam
, 'A' },
7528 static const struct message WmImeKeydownMsgSeq_1
[] =
7530 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
7531 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
7535 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7537 struct recvd_message msg
;
7540 msg
.message
= message
;
7541 msg
.flags
= wparam
|lparam
;
7542 msg
.wParam
= wParam
;
7543 msg
.lParam
= lParam
;
7544 msg
.descr
= "wmime_keydown";
7547 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7550 static void register_wmime_keydown_class(void)
7554 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
7555 cls
.lpfnWndProc
= wmime_keydown_procA
;
7556 cls
.hInstance
= GetModuleHandleA(0);
7557 cls
.lpszClassName
= "wmime_keydown_class";
7558 if (!RegisterClassA(&cls
)) assert(0);
7561 static void test_wmime_keydown_message(void)
7566 trace("Message sequences by WM_IME_KEYDOWN\n");
7568 register_wmime_keydown_class();
7569 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
7570 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
7575 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
7576 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
7577 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
7579 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
7581 TranslateMessage(&msg
);
7582 DispatchMessageA(&msg
);
7584 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
7586 DestroyWindow(hwnd
);
7589 /************* painting message test ********************/
7591 void dump_region(HRGN hrgn
)
7594 RGNDATA
*data
= NULL
;
7599 printf( "null region\n" );
7602 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
7603 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
7604 GetRegionData( hrgn
, size
, data
);
7605 printf("%d rects:", data
->rdh
.nCount
);
7606 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
7607 printf( " %s", wine_dbgstr_rect( rect
));
7609 HeapFree( GetProcessHeap(), 0, data
);
7612 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
7616 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
7617 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
7619 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
7620 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
7621 if (ret
== NULLREGION
)
7623 ok( !hrgn
, "Update region shouldn't be empty\n" );
7627 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
7629 ok( 0, "Regions are different\n" );
7630 if (winetest_debug
> 0)
7632 printf( "Update region: " );
7633 dump_region( update
);
7634 printf( "Wanted region: " );
7635 dump_region( hrgn
);
7639 GetRgnBox( update
, &r1
);
7640 GetUpdateRect( hwnd
, &r2
, FALSE
);
7641 ok( EqualRect( &r1
, &r2
), "Rectangles are different: %s / %s\n", wine_dbgstr_rect( &r1
),
7642 wine_dbgstr_rect( &r2
));
7644 DeleteObject( tmp
);
7645 DeleteObject( update
);
7648 static const struct message WmInvalidateRgn
[] = {
7649 { WM_NCPAINT
, sent
},
7650 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7654 static const struct message WmGetUpdateRect
[] = {
7655 { WM_NCPAINT
, sent
},
7656 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7661 static const struct message WmInvalidateFull
[] = {
7662 { WM_NCPAINT
, sent
|wparam
, 1 },
7663 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7667 static const struct message WmInvalidateErase
[] = {
7668 { WM_NCPAINT
, sent
|wparam
, 1 },
7669 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7670 { WM_ERASEBKGND
, sent
},
7674 static const struct message WmInvalidatePaint
[] = {
7676 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
7677 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7681 static const struct message WmInvalidateErasePaint
[] = {
7683 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
7684 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7685 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7689 static const struct message WmInvalidateErasePaint2
[] = {
7691 { WM_NCPAINT
, sent
|beginpaint
},
7692 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7693 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7697 static const struct message WmErase
[] = {
7698 { WM_ERASEBKGND
, sent
},
7702 static const struct message WmPaint
[] = {
7707 static const struct message WmParentOnlyPaint
[] = {
7708 { WM_PAINT
, sent
|parent
},
7712 static const struct message WmInvalidateParent
[] = {
7713 { WM_NCPAINT
, sent
|parent
},
7714 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
7715 { WM_ERASEBKGND
, sent
|parent
},
7719 static const struct message WmInvalidateParentChild
[] = {
7720 { WM_NCPAINT
, sent
|parent
},
7721 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
7722 { WM_ERASEBKGND
, sent
|parent
},
7723 { WM_NCPAINT
, sent
},
7724 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7725 { WM_ERASEBKGND
, sent
},
7729 static const struct message WmInvalidateParentChild2
[] = {
7730 { WM_ERASEBKGND
, sent
|parent
},
7731 { WM_NCPAINT
, sent
},
7732 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7733 { WM_ERASEBKGND
, sent
},
7737 static const struct message WmParentPaint
[] = {
7738 { WM_PAINT
, sent
|parent
},
7743 static const struct message WmParentPaintNc
[] = {
7744 { WM_PAINT
, sent
|parent
},
7746 { WM_NCPAINT
, sent
|beginpaint
},
7747 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7748 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7752 static const struct message WmChildPaintNc
[] = {
7754 { WM_NCPAINT
, sent
|beginpaint
},
7755 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7756 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7760 static const struct message WmParentErasePaint
[] = {
7761 { WM_PAINT
, sent
|parent
},
7762 { WM_NCPAINT
, sent
|parent
|beginpaint
},
7763 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
7764 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
7766 { WM_NCPAINT
, sent
|beginpaint
},
7767 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7768 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7772 static const struct message WmParentOnlyNcPaint
[] = {
7773 { WM_PAINT
, sent
|parent
},
7774 { WM_NCPAINT
, sent
|parent
|beginpaint
},
7775 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
7779 static const struct message WmSetParentStyle
[] = {
7780 { WM_STYLECHANGING
, sent
|parent
},
7781 { WM_STYLECHANGED
, sent
|parent
},
7785 static void test_paint_messages(void)
7791 HWND hparent
, hchild
;
7792 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
7793 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
7794 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
7795 100, 100, 200, 200, 0, 0, 0, NULL
);
7796 ok (hwnd
!= 0, "Failed to create overlapped window\n");
7798 ShowWindow( hwnd
, SW_SHOW
);
7799 UpdateWindow( hwnd
);
7803 check_update_rgn( hwnd
, 0 );
7804 SetRectRgn( hrgn
, 10, 10, 20, 20 );
7805 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7806 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7807 check_update_rgn( hwnd
, hrgn
);
7808 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
7809 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
7810 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7811 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
7812 check_update_rgn( hwnd
, hrgn
);
7813 /* validate everything */
7814 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7815 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7816 check_update_rgn( hwnd
, 0 );
7818 /* test empty region */
7819 SetRectRgn( hrgn
, 10, 10, 10, 15 );
7820 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7821 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7822 check_update_rgn( hwnd
, 0 );
7823 /* test empty rect */
7824 SetRect( &rect
, 10, 10, 10, 15 );
7825 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
7826 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7827 check_update_rgn( hwnd
, 0 );
7829 /* flush pending messages */
7833 GetClientRect( hwnd
, &rect
);
7834 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
7835 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
7836 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
7838 trace("testing InvalidateRect(0, NULL, FALSE)\n");
7839 SetRectEmpty( &rect
);
7840 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) should fail\n");
7841 check_update_rgn( hwnd
, hrgn
);
7842 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7844 ok_sequence( WmPaint
, "Paint", FALSE
);
7845 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7846 check_update_rgn( hwnd
, 0 );
7848 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
7849 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
7851 trace("testing ValidateRect(0, NULL)\n");
7852 SetRectEmpty( &rect
);
7853 if (ValidateRect(0, &rect
) && /* not supported on Win9x */
7854 GetUpdateRect(hwnd
, NULL
, FALSE
)) /* or >= Win 8 */
7856 check_update_rgn( hwnd
, hrgn
);
7857 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7859 ok_sequence( WmPaint
, "Paint", FALSE
);
7860 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7861 check_update_rgn( hwnd
, 0 );
7864 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
7865 SetLastError(0xdeadbeef);
7866 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
7867 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
7868 "wrong error code %d\n", GetLastError());
7869 check_update_rgn( hwnd
, 0 );
7871 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7873 trace("testing ValidateRgn(0, NULL)\n");
7874 SetLastError(0xdeadbeef);
7875 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
7876 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
7877 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
7878 "wrong error code %d\n", GetLastError());
7879 check_update_rgn( hwnd
, 0 );
7881 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7883 trace("testing UpdateWindow(NULL)\n");
7884 SetLastError(0xdeadbeef);
7885 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
7886 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
7887 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
7888 "wrong error code %d\n", GetLastError());
7889 check_update_rgn( hwnd
, 0 );
7891 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7893 /* now with frame */
7894 SetRectRgn( hrgn
, -5, -5, 20, 20 );
7896 /* flush pending messages */
7899 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7900 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
7902 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
7903 check_update_rgn( hwnd
, hrgn
);
7906 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
7907 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
7910 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
7911 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
7913 GetClientRect( hwnd
, &rect
);
7914 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
7915 check_update_rgn( hwnd
, hrgn
);
7918 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
7919 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7922 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
7923 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
7924 check_update_rgn( hwnd
, 0 );
7927 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
7928 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
7929 check_update_rgn( hwnd
, 0 );
7932 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7933 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7934 SetRectRgn( hrgn
, 0, 0, 50, 100 );
7935 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
7936 SetRectRgn( hrgn
, 50, 0, 100, 100 );
7937 check_update_rgn( hwnd
, hrgn
);
7938 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
7939 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
7940 check_update_rgn( hwnd
, 0 );
7943 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7944 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
7945 SetRectRgn( hrgn
, 0, 0, 100, 50 );
7946 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
7947 ok_sequence( WmErase
, "Erase", FALSE
);
7948 SetRectRgn( hrgn
, 0, 50, 100, 100 );
7949 check_update_rgn( hwnd
, hrgn
);
7952 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7953 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
7954 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7955 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
7956 ok_sequence( WmPaint
, "Paint", FALSE
);
7959 SetRectRgn( hrgn
, -4, -4, -2, -2 );
7960 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7961 SetRectRgn( hrgn
, -200, -200, -198, -198 );
7962 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
7963 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
7966 SetRectRgn( hrgn
, -4, -4, -2, -2 );
7967 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7968 SetRectRgn( hrgn
, -4, -4, -3, -3 );
7969 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
7970 SetRectRgn( hrgn
, 0, 0, 1, 1 );
7971 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
7972 ok_sequence( WmPaint
, "Paint", FALSE
);
7975 SetRectRgn( hrgn
, -4, -4, -1, -1 );
7976 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7977 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
7978 /* make sure no WM_PAINT was generated */
7980 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
7983 SetRectRgn( hrgn
, -4, -4, -1, -1 );
7984 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7985 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
7987 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
7989 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
7990 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
7991 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
7992 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
7993 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
7994 /* this will send WM_NCPAINT and validate the non client area */
7995 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
7996 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
7998 DispatchMessageA( &msg
);
8000 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
8002 DestroyWindow( hwnd
);
8004 /* now test with a child window */
8006 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
8007 100, 100, 200, 200, 0, 0, 0, NULL
);
8008 ok (hparent
!= 0, "Failed to create parent window\n");
8010 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
8011 10, 10, 100, 100, hparent
, 0, 0, NULL
);
8012 ok (hchild
!= 0, "Failed to create child window\n");
8014 ShowWindow( hparent
, SW_SHOW
);
8015 UpdateWindow( hparent
);
8016 UpdateWindow( hchild
);
8019 log_all_parent_messages
++;
8021 SetRect( &rect
, 0, 0, 50, 50 );
8022 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8023 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8024 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
8026 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8028 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
8029 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
8030 check_update_rgn( hchild
, hrgn
);
8031 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8032 check_update_rgn( hparent
, hrgn
);
8033 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8034 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
8035 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8036 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8039 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
8041 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8042 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8043 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
8044 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8045 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8047 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8048 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8049 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
8051 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8053 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8054 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8055 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
8057 /* flush all paint messages */
8061 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
8062 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8063 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8064 check_update_rgn( hparent
, hrgn
);
8065 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8066 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8067 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8068 check_update_rgn( hparent
, hrgn
);
8070 /* flush all paint messages */
8072 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8075 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
8076 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8077 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8078 check_update_rgn( hparent
, hrgn
);
8079 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8080 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8081 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
8082 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
8083 check_update_rgn( hparent
, hrgn
);
8084 /* flush all paint messages */
8088 /* same as above but parent gets completely validated */
8089 SetRect( &rect
, 20, 20, 30, 30 );
8090 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8091 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8092 check_update_rgn( hparent
, hrgn
);
8093 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8094 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8095 check_update_rgn( hparent
, 0 ); /* no update region */
8097 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
8099 /* make sure RDW_VALIDATE on child doesn't have the same effect */
8101 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8102 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8103 check_update_rgn( hparent
, hrgn
);
8104 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
8105 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8106 check_update_rgn( hparent
, hrgn
);
8108 /* same as above but normal WM_PAINT doesn't validate parent */
8110 SetRect( &rect
, 20, 20, 30, 30 );
8111 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8112 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8113 check_update_rgn( hparent
, hrgn
);
8114 /* no WM_PAINT in child while parent still pending */
8115 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8116 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8117 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8118 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
8121 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8122 /* no WM_PAINT in child while parent still pending */
8123 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8124 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8125 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
8126 /* now that parent is valid child should get WM_PAINT */
8127 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8128 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8129 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8130 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
8132 /* same thing with WS_CLIPCHILDREN in parent */
8134 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8135 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8136 /* changing style invalidates non client area, but we need to invalidate something else to see it */
8137 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
8138 ok_sequence( WmEmptySeq
, "No message", FALSE
);
8139 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
8140 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
8143 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8144 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8145 check_update_rgn( hparent
, hrgn
);
8146 /* no WM_PAINT in child while parent still pending */
8147 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8148 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8149 /* WM_PAINT in parent first */
8150 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8151 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
8153 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
8155 SetRect( &rect
, 0, 0, 30, 30 );
8156 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
8157 SetRectRgn( hrgn
, 0, 0, 30, 30 );
8158 check_update_rgn( hparent
, hrgn
);
8160 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
8162 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8164 SetRect( &rect
, -10, 0, 30, 30 );
8165 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8166 SetRect( &rect
, 0, 0, 20, 20 );
8167 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8168 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8169 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
8171 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8173 SetRect( &rect
, -10, 0, 30, 30 );
8174 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8175 SetRect( &rect
, 0, 0, 100, 100 );
8176 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8177 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8178 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
8179 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8180 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
8182 /* WS_CLIPCHILDREN doesn't exclude children from update region */
8184 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
8185 GetClientRect( hparent
, &rect
);
8186 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8187 check_update_rgn( hparent
, hrgn
);
8190 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8191 GetClientRect( hparent
, &rect
);
8192 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8193 check_update_rgn( hparent
, hrgn
);
8196 /* test RDW_INTERNALPAINT behavior */
8199 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
8201 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8203 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
8205 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8207 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8209 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8211 assert( GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
);
8212 UpdateWindow( hparent
);
8215 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
8216 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8217 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8218 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8220 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
8222 UpdateWindow( hparent
);
8225 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
8226 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8227 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8228 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8230 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8232 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8233 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8234 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8236 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8238 assert( !(GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
) );
8239 UpdateWindow( hparent
);
8242 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
8243 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8244 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8245 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8247 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
8249 UpdateWindow( hparent
);
8252 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
8253 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8254 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8255 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8257 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8259 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
8260 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
8262 UpdateWindow( hparent
);
8265 trace("testing SetWindowPos(-10000, -10000) on child\n");
8266 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
8267 check_update_rgn( hchild
, 0 );
8270 #if 0 /* this one doesn't pass under Wine yet */
8271 UpdateWindow( hparent
);
8274 trace("testing ShowWindow(SW_MINIMIZE) on child\n");
8275 ShowWindow( hchild
, SW_MINIMIZE
);
8276 check_update_rgn( hchild
, 0 );
8280 UpdateWindow( hparent
);
8283 trace("testing SetWindowPos(-10000, -10000) on parent\n");
8284 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
8285 check_update_rgn( hparent
, 0 );
8288 log_all_parent_messages
--;
8289 DestroyWindow( hparent
);
8290 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
8292 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
8294 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
8295 100, 100, 200, 200, 0, 0, 0, NULL
);
8296 ok (hparent
!= 0, "Failed to create parent window\n");
8298 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
8299 10, 10, 100, 100, hparent
, 0, 0, NULL
);
8300 ok (hchild
!= 0, "Failed to create child window\n");
8302 ShowWindow( hparent
, SW_SHOW
);
8303 UpdateWindow( hparent
);
8304 UpdateWindow( hchild
);
8308 /* moving child outside of parent boundaries changes update region */
8309 SetRect( &rect
, 0, 0, 40, 40 );
8310 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8311 SetRectRgn( hrgn
, 0, 0, 40, 40 );
8312 check_update_rgn( hchild
, hrgn
);
8313 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
8314 SetRectRgn( hrgn
, 10, 0, 40, 40 );
8315 check_update_rgn( hchild
, hrgn
);
8316 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
8317 SetRectRgn( hrgn
, 10, 10, 40, 40 );
8318 check_update_rgn( hchild
, hrgn
);
8320 /* moving parent off-screen does too */
8321 SetRect( &rect
, 0, 0, 100, 100 );
8322 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
8323 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8324 check_update_rgn( hparent
, hrgn
);
8325 SetRectRgn( hrgn
, 10, 10, 40, 40 );
8326 check_update_rgn( hchild
, hrgn
);
8327 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
8328 GetUpdateRect( hparent
, &rect2
, FALSE
);
8329 if (!EqualRect( &rect2
, &rect
)) /* Win 8 and later don't crop update to screen */
8334 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8335 check_update_rgn( hparent
, hrgn
);
8336 SetRectRgn( hrgn
, rect
.left
+ 10, rect
.top
+ 10, 40, 40 );
8337 check_update_rgn( hchild
, hrgn
);
8339 /* invalidated region is cropped by the parent rects */
8340 SetRect( &rect
, 0, 0, 50, 50 );
8341 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8342 SetRectRgn( hrgn
, rect2
.left
+ 10, rect2
.top
+ 10, 50, 50 );
8343 check_update_rgn( hchild
, hrgn
);
8345 DestroyWindow( hparent
);
8346 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
8349 DeleteObject( hrgn
);
8350 DeleteObject( hrgn2
);
8361 static DWORD WINAPI
thread_proc(void *param
)
8364 struct wnd_event
*wnd_event
= param
;
8366 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
8367 100, 100, 200, 200, 0, 0, 0, NULL
);
8368 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
8370 SetEvent(wnd_event
->start_event
);
8372 while (GetMessageA(&msg
, 0, 0, 0))
8374 TranslateMessage(&msg
);
8375 DispatchMessageA(&msg
);
8378 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
8383 static DWORD CALLBACK
create_grand_child_thread( void *param
)
8385 struct wnd_event
*wnd_event
= param
;
8389 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
8390 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
8391 ok (hchild
!= 0, "Failed to create child window\n");
8394 SetEvent( wnd_event
->start_event
);
8398 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
8399 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
8400 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8405 static DWORD CALLBACK
create_child_thread( void *param
)
8407 struct wnd_event
*wnd_event
= param
;
8408 struct wnd_event child_event
;
8412 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
8413 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
8414 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
8415 SetFocus( child_event
.hwnd
);
8418 child_event
.start_event
= wnd_event
->start_event
;
8419 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
8422 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
8423 if (ret
!= 1) break;
8424 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8426 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
8427 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
8431 static const char manifest_dep
[] =
8432 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
8433 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
8434 " <file name=\"testdep.dll\" />"
8437 static const char manifest_main
[] =
8438 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
8439 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
8441 " <dependentAssembly>"
8442 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
8443 " </dependentAssembly>"
8447 static void create_manifest_file(const char *filename
, const char *manifest
)
8449 WCHAR path
[MAX_PATH
];
8453 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
8454 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
8455 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
8456 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
8460 static HANDLE
test_create(const char *file
)
8462 WCHAR path
[MAX_PATH
];
8466 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
8467 memset(&actctx
, 0, sizeof(ACTCTXW
));
8468 actctx
.cbSize
= sizeof(ACTCTXW
);
8469 actctx
.lpSource
= path
;
8471 handle
= pCreateActCtxW(&actctx
);
8472 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %u\n", GetLastError());
8474 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%d\n", actctx
.cbSize
);
8475 ok(actctx
.dwFlags
== 0, "dwFlags=%d\n", actctx
.dwFlags
);
8476 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
8477 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
8478 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
8479 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
8480 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
8481 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
8482 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
8487 static void test_interthread_messages(void)
8489 HANDLE hThread
, context
, handle
, event
;
8495 int len
, expected_len
;
8496 struct wnd_event wnd_event
;
8499 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
8500 if (!wnd_event
.start_event
)
8502 win_skip("skipping interthread message test under win9x\n");
8506 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
8507 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8509 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8511 CloseHandle(wnd_event
.start_event
);
8513 SetLastError(0xdeadbeef);
8514 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
8515 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
8516 "wrong error code %d\n", GetLastError());
8518 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
8519 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
8521 expected_len
= lstrlenA("window caption text");
8522 memset(buf
, 0, sizeof(buf
));
8523 SetLastError(0xdeadbeef);
8524 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
8525 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
8526 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
8528 msg
.hwnd
= wnd_event
.hwnd
;
8529 msg
.message
= WM_GETTEXT
;
8530 msg
.wParam
= sizeof(buf
);
8531 msg
.lParam
= (LPARAM
)buf
;
8532 memset(buf
, 0, sizeof(buf
));
8533 SetLastError(0xdeadbeef);
8534 len
= DispatchMessageA(&msg
);
8535 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
8536 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len
, GetLastError());
8538 /* the following test causes an exception in user.exe under win9x */
8539 msg
.hwnd
= wnd_event
.hwnd
;
8540 msg
.message
= WM_TIMER
;
8542 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
8543 SetLastError(0xdeadbeef);
8544 len
= DispatchMessageA(&msg
);
8545 ok(!len
&& GetLastError() == 0xdeadbeef,
8546 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len
, GetLastError());
8548 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
8549 ok( ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
8551 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8552 CloseHandle(hThread
);
8554 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
8556 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8557 100, 100, 200, 200, 0, 0, 0, NULL
);
8558 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
8561 log_all_parent_messages
++;
8562 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
8563 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
8564 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
8567 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
8568 if (ret
!= 1) break;
8569 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8571 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
8572 /* now wait for the thread without processing messages; this shouldn't deadlock */
8573 SetEvent( wnd_event
.stop_event
);
8574 ret
= WaitForSingleObject( hThread
, 5000 );
8575 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
8576 CloseHandle( hThread
);
8578 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
8579 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
8580 CloseHandle( wnd_event
.grand_child
);
8582 CloseHandle( wnd_event
.start_event
);
8583 CloseHandle( wnd_event
.stop_event
);
8585 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
8586 log_all_parent_messages
--;
8587 DestroyWindow( wnd_event
.hwnd
);
8589 /* activation context tests */
8590 if (!pActivateActCtx
)
8592 win_skip("Activation contexts are not supported, skipping\n");
8596 create_manifest_file("testdep1.manifest", manifest_dep
);
8597 create_manifest_file("main.manifest", manifest_main
);
8599 context
= test_create("main.manifest");
8600 DeleteFileA("testdep1.manifest");
8601 DeleteFileA("main.manifest");
8603 handle
= (void*)0xdeadbeef;
8604 ret
= pGetCurrentActCtx(&handle
);
8605 ok(ret
, "GetCurrentActCtx failed: %u\n", GetLastError());
8606 ok(handle
== 0, "active context %p\n", handle
);
8608 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
8609 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
8610 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8611 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8612 CloseHandle(wnd_event
.start_event
);
8614 /* context is activated after thread creation, so it doesn't inherit it by default */
8615 ret
= pActivateActCtx(context
, &cookie
);
8616 ok(ret
, "activation failed: %u\n", GetLastError());
8619 ret
= pGetCurrentActCtx(&handle
);
8620 ok(ret
, "GetCurrentActCtx failed: %u\n", GetLastError());
8621 ok(handle
!= 0, "active context %p\n", handle
);
8622 pReleaseActCtx(handle
);
8624 /* destination window will test for active context */
8625 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
8626 ok(ret
, "thread window returned %d\n", ret
);
8628 event
= CreateEventW(NULL
, 0, 0, NULL
);
8629 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
8630 ok(ret
, "thread window returned %d\n", ret
);
8631 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8634 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
8635 ok(ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
8637 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8638 CloseHandle(hThread
);
8640 ret
= pDeactivateActCtx(0, cookie
);
8641 ok(ret
, "DeactivateActCtx failed: %u\n", GetLastError());
8642 pReleaseActCtx(context
);
8646 static const struct message WmVkN
[] = {
8647 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8648 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8649 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
8650 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
8651 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
8652 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8653 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8654 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8657 static const struct message WmShiftVkN
[] = {
8658 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8659 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8660 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8661 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8662 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8663 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
8664 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
8665 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
8666 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8667 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8668 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8669 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8670 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8671 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8674 static const struct message WmCtrlVkN
[] = {
8675 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8676 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8677 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8678 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8679 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8680 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
8681 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
8682 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
8683 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8684 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8685 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8686 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8687 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8688 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8691 static const struct message WmCtrlVkN_2
[] = {
8692 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8693 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8694 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8695 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8696 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8697 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
8698 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8699 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8700 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8701 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8702 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8703 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8706 static const struct message WmAltVkN
[] = {
8707 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8708 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8709 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8710 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8711 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8712 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
8713 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
8714 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
8715 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
8716 { HCBT_SYSCOMMAND
, hook
},
8717 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8718 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8719 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
8720 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
8721 { WM_INITMENU
, sent
|defwinproc
},
8722 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8723 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
8724 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
8725 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8726 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
8727 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8728 { WM_EXITMENULOOP
, sent
|defwinproc
},
8729 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
8730 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
8731 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8732 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8733 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8734 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8735 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8736 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8739 static const struct message WmAltVkN_2
[] = {
8740 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8741 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8742 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8743 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8744 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8745 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
8746 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8747 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8748 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8749 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8750 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8751 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8754 static const struct message WmCtrlAltVkN
[] = {
8755 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8756 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8757 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8758 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8759 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8760 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8761 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8762 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8763 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
8764 { WM_CHAR
, optional
},
8765 { WM_CHAR
, sent
|optional
},
8766 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8767 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8768 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8769 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8770 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8771 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8772 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8773 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8774 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8777 static const struct message WmCtrlShiftVkN
[] = {
8778 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8779 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8780 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8781 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8782 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8783 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8784 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8785 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8786 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
8787 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8788 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8789 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8790 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8791 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8792 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8793 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8794 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8795 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8798 static const struct message WmCtrlAltShiftVkN
[] = {
8799 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8800 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8801 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8802 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8803 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8804 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8805 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
8806 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
8807 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
8808 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8809 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8810 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
8811 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8812 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8813 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8814 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
8815 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
8816 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
8817 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8818 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8819 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8820 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8821 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8822 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8825 static const struct message WmAltPressRelease
[] = {
8826 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8827 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8828 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8829 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8830 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8831 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8832 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
8833 { HCBT_SYSCOMMAND
, hook
},
8834 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8835 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8836 { WM_INITMENU
, sent
|defwinproc
},
8837 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8838 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8839 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8841 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
8843 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8844 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
8845 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8846 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
8847 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8848 { WM_EXITMENULOOP
, sent
|defwinproc
},
8849 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8850 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8851 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8854 static const struct message WmShiftMouseButton
[] = {
8855 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8856 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8857 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8858 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
8859 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
8860 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
8861 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
8862 { WM_LBUTTONUP
, wparam
, MK_SHIFT
, 0 },
8863 { WM_LBUTTONUP
, sent
|wparam
, MK_SHIFT
, 0 },
8864 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8865 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8866 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8869 static const struct message WmF1Seq
[] = {
8870 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
8871 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
8872 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
8873 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
8874 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
8875 { WM_HELP
, sent
|defwinproc
},
8876 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
8877 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
8878 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
8881 static const struct message WmVkAppsSeq
[] = {
8882 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
8883 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
8884 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
8885 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
8886 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
8887 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
8888 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
8889 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
8892 static const struct message WmVkF10Seq
[] = {
8893 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8894 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
8895 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
8896 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8897 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8898 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8899 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
8900 { HCBT_SYSCOMMAND
, hook
},
8901 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8902 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8903 { WM_INITMENU
, sent
|defwinproc
},
8904 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8905 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8906 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8908 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
8910 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8911 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8912 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
8913 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8914 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
8915 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8916 { WM_EXITMENULOOP
, sent
|defwinproc
},
8917 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8918 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8919 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8922 static const struct message WmShiftF10Seq
[] = {
8923 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8924 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8925 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
8926 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8927 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
8928 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
8929 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
8930 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8931 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8932 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8933 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
8934 { HCBT_SYSCOMMAND
, hook
},
8935 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8936 { WM_INITMENU
, sent
|defwinproc
},
8937 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8938 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
8939 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
8940 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8941 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
8942 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8943 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
8944 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
8945 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
8949 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
8953 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
8955 struct recvd_message log_msg
;
8957 /* ignore some unwanted messages */
8958 if (msg
.message
== WM_MOUSEMOVE
||
8959 msg
.message
== WM_TIMER
||
8960 ignore_message( msg
.message
))
8963 log_msg
.hwnd
= msg
.hwnd
;
8964 log_msg
.message
= msg
.message
;
8965 log_msg
.flags
= wparam
|lparam
;
8966 log_msg
.wParam
= msg
.wParam
;
8967 log_msg
.lParam
= msg
.lParam
;
8968 log_msg
.descr
= "accel";
8969 add_message(&log_msg
);
8971 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
8973 TranslateMessage(&msg
);
8974 DispatchMessageA(&msg
);
8979 static void test_accelerators(void)
8985 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8986 100, 100, 200, 200, 0, 0, 0, NULL
);
8995 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
8997 state
= GetKeyState(VK_SHIFT
);
8998 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
8999 state
= GetKeyState(VK_CAPITAL
);
9000 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
9002 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
9003 assert(hAccel
!= 0);
9006 pump_msg_loop(hwnd
, 0);
9009 trace("testing VK_N press/release\n");
9011 keybd_event('N', 0, 0, 0);
9012 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9013 pump_msg_loop(hwnd
, hAccel
);
9014 if (!sequence_cnt
) /* we didn't get any message */
9016 skip( "queuing key events not supported\n" );
9019 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
9021 trace("testing Shift+VK_N press/release\n");
9023 keybd_event(VK_SHIFT
, 0, 0, 0);
9024 keybd_event('N', 0, 0, 0);
9025 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9026 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9027 pump_msg_loop(hwnd
, hAccel
);
9028 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
9030 trace("testing Ctrl+VK_N press/release\n");
9032 keybd_event(VK_CONTROL
, 0, 0, 0);
9033 keybd_event('N', 0, 0, 0);
9034 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9035 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9036 pump_msg_loop(hwnd
, hAccel
);
9037 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
9039 trace("testing Alt+VK_N press/release\n");
9041 keybd_event(VK_MENU
, 0, 0, 0);
9042 keybd_event('N', 0, 0, 0);
9043 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9044 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9045 pump_msg_loop(hwnd
, hAccel
);
9046 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
9048 trace("testing Ctrl+Alt+VK_N press/release 1\n");
9050 keybd_event(VK_CONTROL
, 0, 0, 0);
9051 keybd_event(VK_MENU
, 0, 0, 0);
9052 keybd_event('N', 0, 0, 0);
9053 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9054 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9055 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9056 pump_msg_loop(hwnd
, hAccel
);
9057 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
9059 ret
= DestroyAcceleratorTable(hAccel
);
9060 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
9062 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
9063 assert(hAccel
!= 0);
9065 trace("testing VK_N press/release\n");
9067 keybd_event('N', 0, 0, 0);
9068 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9069 pump_msg_loop(hwnd
, hAccel
);
9070 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
9072 trace("testing Shift+VK_N press/release\n");
9074 keybd_event(VK_SHIFT
, 0, 0, 0);
9075 keybd_event('N', 0, 0, 0);
9076 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9077 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9078 pump_msg_loop(hwnd
, hAccel
);
9079 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
9081 trace("testing Ctrl+VK_N press/release 2\n");
9083 keybd_event(VK_CONTROL
, 0, 0, 0);
9084 keybd_event('N', 0, 0, 0);
9085 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9086 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9087 pump_msg_loop(hwnd
, hAccel
);
9088 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
9090 trace("testing Alt+VK_N press/release 2\n");
9092 keybd_event(VK_MENU
, 0, 0, 0);
9093 keybd_event('N', 0, 0, 0);
9094 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9095 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9096 pump_msg_loop(hwnd
, hAccel
);
9097 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
9099 trace("testing Ctrl+Alt+VK_N press/release 2\n");
9101 keybd_event(VK_CONTROL
, 0, 0, 0);
9102 keybd_event(VK_MENU
, 0, 0, 0);
9103 keybd_event('N', 0, 0, 0);
9104 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9105 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9106 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9107 pump_msg_loop(hwnd
, hAccel
);
9108 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
9110 trace("testing Ctrl+Shift+VK_N press/release\n");
9112 keybd_event(VK_CONTROL
, 0, 0, 0);
9113 keybd_event(VK_SHIFT
, 0, 0, 0);
9114 keybd_event('N', 0, 0, 0);
9115 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9116 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9117 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9118 pump_msg_loop(hwnd
, hAccel
);
9119 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
9121 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
9123 keybd_event(VK_CONTROL
, 0, 0, 0);
9124 keybd_event(VK_MENU
, 0, 0, 0);
9125 keybd_event(VK_SHIFT
, 0, 0, 0);
9126 keybd_event('N', 0, 0, 0);
9127 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9128 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9129 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9130 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9131 pump_msg_loop(hwnd
, hAccel
);
9132 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
9134 ret
= DestroyAcceleratorTable(hAccel
);
9135 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
9138 trace("testing Alt press/release\n");
9140 keybd_event(VK_MENU
, 0, 0, 0);
9141 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9142 keybd_event(VK_MENU
, 0, 0, 0);
9143 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9144 pump_msg_loop(hwnd
, 0);
9145 /* this test doesn't pass in Wine for managed windows */
9146 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
9148 trace("testing VK_F1 press/release\n");
9149 keybd_event(VK_F1
, 0, 0, 0);
9150 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
9151 pump_msg_loop(hwnd
, 0);
9152 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
9154 trace("testing VK_APPS press/release\n");
9155 keybd_event(VK_APPS
, 0, 0, 0);
9156 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
9157 pump_msg_loop(hwnd
, 0);
9158 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
9160 trace("testing VK_F10 press/release\n");
9161 keybd_event(VK_F10
, 0, 0, 0);
9162 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9163 keybd_event(VK_F10
, 0, 0, 0);
9164 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9165 pump_msg_loop(hwnd
, 0);
9166 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", TRUE
);
9168 trace("testing SHIFT+F10 press/release\n");
9169 keybd_event(VK_SHIFT
, 0, 0, 0);
9170 keybd_event(VK_F10
, 0, 0, 0);
9171 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9172 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9173 keybd_event(VK_ESCAPE
, 0, 0, 0);
9174 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
9175 pump_msg_loop(hwnd
, 0);
9176 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
9178 trace("testing Shift+MouseButton press/release\n");
9179 /* first, move mouse pointer inside of the window client area */
9180 GetClientRect(hwnd
, &rc
);
9181 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
9182 rc
.left
+= (rc
.right
- rc
.left
)/2;
9183 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
9184 SetCursorPos(rc
.left
, rc
.top
);
9185 SetActiveWindow(hwnd
);
9190 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
9193 keybd_event(VK_SHIFT
, 0, 0, 0);
9194 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
9195 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
9196 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9197 pump_msg_loop(hwnd
, 0);
9198 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
9199 if (i
< sequence_cnt
)
9200 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
9202 skip( "Shift+MouseButton event didn't get to the window\n" );
9206 if (hAccel
) DestroyAcceleratorTable(hAccel
);
9207 DestroyWindow(hwnd
);
9210 /************* window procedures ********************/
9212 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
9213 WPARAM wParam
, LPARAM lParam
)
9215 static LONG defwndproc_counter
= 0;
9216 static LONG beginpaint_counter
= 0;
9218 struct recvd_message msg
;
9220 if (ignore_message( message
)) return 0;
9226 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9227 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
9228 "wrong WS_DISABLED state: %ld != %d\n", wParam
, !(style
& WS_DISABLED
));
9232 case WM_CAPTURECHANGED
:
9233 if (test_DestroyWindow_flag
)
9235 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9236 if (style
& WS_CHILD
)
9237 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
9238 else if (style
& WS_POPUP
)
9239 lParam
= WND_POPUP_ID
;
9241 lParam
= WND_PARENT_ID
;
9249 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
9250 capture
= GetCapture();
9253 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
9254 trace("current capture %p, releasing...\n", capture
);
9261 ok(pGetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
9262 if (test_DestroyWindow_flag
)
9264 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9265 if (style
& WS_CHILD
)
9266 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
9267 else if (style
& WS_POPUP
)
9268 lParam
= WND_POPUP_ID
;
9270 lParam
= WND_PARENT_ID
;
9274 /* test_accelerators() depends on this */
9280 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo
;
9281 HANDLE handle
, event
= (HANDLE
)lParam
;
9284 handle
= (void*)0xdeadbeef;
9285 ret
= pGetCurrentActCtx(&handle
);
9286 ok(ret
, "failed to get current context, %u\n", GetLastError());
9287 ok(handle
== 0, "got active context %p\n", handle
);
9289 memset(&basicinfo
, 0xff, sizeof(basicinfo
));
9290 ret
= pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
, handle
, 0, ActivationContextBasicInformation
,
9291 &basicinfo
, sizeof(basicinfo
), NULL
);
9292 ok(ret
, "got %d, error %d\n", ret
, GetLastError());
9293 ok(basicinfo
.hActCtx
== NULL
, "got %p\n", basicinfo
.hActCtx
);
9294 ok(basicinfo
.dwFlags
== 0, "got %x\n", basicinfo
.dwFlags
);
9296 if (event
) SetEvent(event
);
9302 case WM_MOUSEACTIVATE
:
9303 case WM_NCMOUSEMOVE
:
9310 msg
.message
= message
;
9311 msg
.flags
= sent
|wparam
|lparam
;
9312 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9313 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
9314 msg
.wParam
= wParam
;
9315 msg
.lParam
= lParam
;
9316 msg
.descr
= "MsgCheckProc";
9319 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
9321 HWND parent
= GetParent(hwnd
);
9323 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
9325 GetClientRect(parent
, &rc
);
9326 trace("parent %p client size = (%d x %d)\n", parent
, rc
.right
, rc
.bottom
);
9327 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
9328 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
9329 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
9330 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
9331 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
9332 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
9334 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %d != %d\n",
9335 minmax
->ptMaxSize
.x
, rc
.right
);
9336 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %d != %d\n",
9337 minmax
->ptMaxSize
.y
, rc
.bottom
);
9340 if (message
== WM_PAINT
)
9343 beginpaint_counter
++;
9344 BeginPaint( hwnd
, &ps
);
9345 beginpaint_counter
--;
9346 EndPaint( hwnd
, &ps
);
9350 if (message
== WM_CONTEXTMENU
)
9352 /* don't create context menu */
9356 defwndproc_counter
++;
9357 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
9358 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9359 defwndproc_counter
--;
9364 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9366 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
9369 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9371 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
9374 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9376 static LONG defwndproc_counter
= 0;
9378 struct recvd_message msg
;
9380 if (ignore_message( message
)) return 0;
9384 case WM_QUERYENDSESSION
:
9386 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
9391 msg
.message
= message
;
9392 msg
.flags
= sent
|wparam
|lparam
;
9393 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9394 msg
.wParam
= wParam
;
9395 msg
.lParam
= lParam
;
9396 msg
.descr
= "popup";
9399 if (message
== WM_CREATE
)
9401 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
9402 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
9405 defwndproc_counter
++;
9406 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9407 defwndproc_counter
--;
9412 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9414 static LONG defwndproc_counter
= 0;
9415 static LONG beginpaint_counter
= 0;
9417 struct recvd_message msg
;
9419 if (ignore_message( message
)) return 0;
9421 if (log_all_parent_messages
||
9422 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
9423 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
9424 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
9425 message
== WM_DRAWITEM
|| message
== WM_MEASUREITEM
|| message
== WM_COMPAREITEM
||
9426 message
== WM_COMMAND
|| message
== WM_IME_SETCONTEXT
)
9435 case WM_NCMOUSEMOVE
:
9441 INT ret
= GetClipBox((HDC
)wParam
, &rc
);
9443 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret
, wine_dbgstr_rect(&rc
));
9449 msg
.message
= message
;
9450 msg
.flags
= sent
|parent
|wparam
|lparam
;
9451 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9452 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
9453 msg
.wParam
= wParam
;
9454 msg
.lParam
= lParam
;
9455 msg
.descr
= "parent";
9459 if (message
== WM_PAINT
)
9462 beginpaint_counter
++;
9463 BeginPaint( hwnd
, &ps
);
9464 beginpaint_counter
--;
9465 EndPaint( hwnd
, &ps
);
9469 defwndproc_counter
++;
9470 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9471 defwndproc_counter
--;
9473 return message
== WM_COMPAREITEM
? -1 : ret
;
9476 static INT_PTR CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
9478 if (message
== WM_CREATE
)
9479 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
9480 else if (message
== WM_CLOSE
)
9482 /* Only the first WM_QUIT will survive the window destruction */
9483 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
9484 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
9485 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
9488 return DefWindowProcA(hwnd
, message
, wp
, lp
);
9491 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9493 static LONG defwndproc_counter
= 0;
9495 struct recvd_message msg
;
9497 if (ignore_message( message
)) return 0;
9501 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
9502 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
9503 if (after_end_dialog
)
9504 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
9506 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
9510 msg
.message
= message
;
9511 msg
.flags
= sent
|wparam
|lparam
;
9512 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9513 msg
.wParam
= wParam
;
9514 msg
.lParam
= lParam
;
9515 msg
.descr
= "dialog";
9518 defwndproc_counter
++;
9519 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
9520 defwndproc_counter
--;
9525 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9527 static LONG defwndproc_counter
= 0;
9529 struct recvd_message msg
;
9531 /* log only specific messages we are interested in */
9534 #if 0 /* probably log these as well */
9542 case WM_GETMINMAXINFO
:
9543 case WM_WINDOWPOSCHANGING
:
9544 case WM_WINDOWPOSCHANGED
:
9547 default: /* ignore */
9548 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
9549 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9553 msg
.message
= message
;
9554 msg
.flags
= sent
|wparam
|lparam
;
9555 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9556 msg
.wParam
= wParam
;
9557 msg
.lParam
= lParam
;
9561 defwndproc_counter
++;
9562 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9563 defwndproc_counter
--;
9568 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
9572 case WM_CREATE
: return 0;
9581 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
9583 TranslateMessage(&msg2
);
9584 DispatchMessageA(&msg2
);
9588 else ok(broken(1), "infinite loop\n");
9590 paint_loop_done
= TRUE
;
9591 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
9594 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
9597 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9599 static LONG defwndproc_counter
= 0;
9601 struct recvd_message msg
;
9604 if (ignore_message( message
)) return 0;
9606 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
9607 message
== WM_HOTKEY
|| message
>= WM_APP
)
9610 msg
.message
= message
;
9611 msg
.flags
= sent
|wparam
|lparam
;
9612 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9613 msg
.wParam
= wParam
;
9614 msg
.lParam
= lParam
;
9615 msg
.descr
= "HotkeyMsgCheckProcA";
9619 defwndproc_counter
++;
9620 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9621 defwndproc_counter
--;
9623 if (message
== WM_APP
)
9625 queue_status
= GetQueueStatus(QS_HOTKEY
);
9626 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
9627 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
9628 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
9629 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
9631 else if (message
== WM_APP
+1)
9633 queue_status
= GetQueueStatus(QS_HOTKEY
);
9634 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
9640 static BOOL
RegisterWindowClasses(void)
9646 cls
.lpfnWndProc
= MsgCheckProcA
;
9649 cls
.hInstance
= GetModuleHandleA(0);
9651 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
9652 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
9653 cls
.lpszMenuName
= NULL
;
9654 cls
.lpszClassName
= "TestWindowClass";
9655 if(!RegisterClassA(&cls
)) return FALSE
;
9657 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
9658 cls
.lpszClassName
= "HotkeyWindowClass";
9659 if(!RegisterClassA(&cls
)) return FALSE
;
9661 cls
.lpfnWndProc
= ShowWindowProcA
;
9662 cls
.lpszClassName
= "ShowWindowClass";
9663 if(!RegisterClassA(&cls
)) return FALSE
;
9665 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
9666 cls
.lpszClassName
= "TestPopupClass";
9667 if(!RegisterClassA(&cls
)) return FALSE
;
9669 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
9670 cls
.lpszClassName
= "TestParentClass";
9671 if(!RegisterClassA(&cls
)) return FALSE
;
9673 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
9674 cls
.lpszClassName
= "StopQuitClass";
9675 if(!RegisterClassA(&cls
)) return FALSE
;
9677 cls
.lpfnWndProc
= DefWindowProcA
;
9678 cls
.lpszClassName
= "SimpleWindowClass";
9679 if(!RegisterClassA(&cls
)) return FALSE
;
9681 cls
.lpfnWndProc
= PaintLoopProcA
;
9682 cls
.lpszClassName
= "PaintLoopWindowClass";
9683 if(!RegisterClassA(&cls
)) return FALSE
;
9685 cls
.style
= CS_NOCLOSE
;
9686 cls
.lpszClassName
= "NoCloseWindowClass";
9687 if(!RegisterClassA(&cls
)) return FALSE
;
9689 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
9691 cls
.hInstance
= GetModuleHandleA(0);
9692 cls
.hbrBackground
= 0;
9693 cls
.lpfnWndProc
= TestDlgProcA
;
9694 cls
.lpszClassName
= "TestDialogClass";
9695 if(!RegisterClassA(&cls
)) return FALSE
;
9698 clsW
.lpfnWndProc
= MsgCheckProcW
;
9699 clsW
.cbClsExtra
= 0;
9700 clsW
.cbWndExtra
= 0;
9701 clsW
.hInstance
= GetModuleHandleW(0);
9703 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
9704 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
9705 clsW
.lpszMenuName
= NULL
;
9706 clsW
.lpszClassName
= testWindowClassW
;
9707 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
9712 static BOOL
is_our_logged_class(HWND hwnd
)
9716 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
9718 if (!lstrcmpiA(buf
, "TestWindowClass") ||
9719 !lstrcmpiA(buf
, "ShowWindowClass") ||
9720 !lstrcmpiA(buf
, "TestParentClass") ||
9721 !lstrcmpiA(buf
, "TestPopupClass") ||
9722 !lstrcmpiA(buf
, "SimpleWindowClass") ||
9723 !lstrcmpiA(buf
, "TestDialogClass") ||
9724 !lstrcmpiA(buf
, "MDI_frame_class") ||
9725 !lstrcmpiA(buf
, "MDI_client_class") ||
9726 !lstrcmpiA(buf
, "MDI_child_class") ||
9727 !lstrcmpiA(buf
, "my_button_class") ||
9728 !lstrcmpiA(buf
, "my_edit_class") ||
9729 !lstrcmpiA(buf
, "static") ||
9730 !lstrcmpiA(buf
, "ListBox") ||
9731 !lstrcmpiA(buf
, "ComboBox") ||
9732 !lstrcmpiA(buf
, "MyDialogClass") ||
9733 !lstrcmpiA(buf
, "#32770") ||
9734 !lstrcmpiA(buf
, "#32768"))
9740 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
9744 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
9746 if (nCode
== HCBT_CLICKSKIPPED
)
9748 /* ignore this event, XP sends it a lot when switching focus between windows */
9749 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9752 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
9754 struct recvd_message msg
;
9757 msg
.message
= nCode
;
9758 msg
.flags
= hook
|wparam
|lparam
;
9759 msg
.wParam
= wParam
;
9760 msg
.lParam
= lParam
;
9764 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9767 if (nCode
== HCBT_DESTROYWND
)
9769 if (test_DestroyWindow_flag
)
9771 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
9772 if (style
& WS_CHILD
)
9773 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
9774 else if (style
& WS_POPUP
)
9775 lParam
= WND_POPUP_ID
;
9777 lParam
= WND_PARENT_ID
;
9781 /* Log also SetFocus(0) calls */
9782 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
9784 if (is_our_logged_class(hwnd
))
9786 struct recvd_message msg
;
9789 msg
.message
= nCode
;
9790 msg
.flags
= hook
|wparam
|lparam
;
9791 msg
.wParam
= wParam
;
9792 msg
.lParam
= lParam
;
9796 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9799 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
9807 ok(thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
9809 /* ignore mouse cursor events */
9810 if (object_id
== OBJID_CURSOR
) return;
9812 if (!hwnd
|| is_our_logged_class(hwnd
))
9814 struct recvd_message msg
;
9817 msg
.message
= event
;
9818 msg
.flags
= winevent_hook
|wparam
|lparam
;
9819 msg
.wParam
= object_id
;
9820 msg
.lParam
= child_id
;
9826 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
9827 static const WCHAR wszAnsi
[] = {'U',0};
9829 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
9833 case CB_FINDSTRINGEXACT
:
9834 trace("String: %p\n", (LPCWSTR
)lParam
);
9835 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
9837 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
9841 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
9844 static const struct message WmGetTextLengthAfromW
[] = {
9845 { WM_GETTEXTLENGTH
, sent
},
9846 { WM_GETTEXT
, sent
|optional
},
9850 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
9852 /* dummy window proc for WM_GETTEXTLENGTH test */
9853 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
9857 case WM_GETTEXTLENGTH
:
9858 return lstrlenW(dummy_window_text
) + 37; /* some random length */
9860 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
9861 return lstrlenW( (LPWSTR
)lp
);
9863 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
9867 static void test_message_conversion(void)
9869 static const WCHAR wszMsgConversionClass
[] =
9870 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
9874 WNDPROC wndproc
, newproc
;
9878 cls
.lpfnWndProc
= MsgConversionProcW
;
9881 cls
.hInstance
= GetModuleHandleW(NULL
);
9883 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
9884 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
9885 cls
.lpszMenuName
= NULL
;
9886 cls
.lpszClassName
= wszMsgConversionClass
;
9887 /* this call will fail on Win9x, but that doesn't matter as this test is
9888 * meaningless on those platforms */
9889 if(!RegisterClassW(&cls
)) return;
9891 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
9892 100, 100, 200, 200, 0, 0, 0, NULL
);
9893 ok(hwnd
!= NULL
, "Window creation failed\n");
9897 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
9898 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9899 ok(lRes
== 0, "String should have been converted\n");
9900 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9901 ok(lRes
== 1, "String shouldn't have been converted\n");
9905 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
9906 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9907 ok(lRes
== 1, "String shouldn't have been converted\n");
9908 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9909 ok(lRes
== 1, "String shouldn't have been converted\n");
9911 /* Synchronous messages */
9913 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9914 ok(lRes
== 0, "String should have been converted\n");
9915 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9916 ok(lRes
== 1, "String shouldn't have been converted\n");
9918 /* Asynchronous messages */
9921 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9922 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9923 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9925 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9926 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9927 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9929 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9930 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9931 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9933 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9934 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9935 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9937 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9938 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9939 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9941 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9942 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9943 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9945 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
9946 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9947 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9949 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
9950 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9951 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9953 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
9955 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
9956 WS_OVERLAPPEDWINDOW
,
9957 100, 100, 200, 200, 0, 0, 0, NULL
);
9960 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
9961 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
9962 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
9963 "got bad length %ld\n", lRes
);
9966 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
9967 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
9968 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
9969 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
9970 "got bad length %ld\n", lRes
);
9972 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
9973 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
9974 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
9975 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
9976 NULL
, 0, NULL
, NULL
) ||
9977 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
9978 "got bad length %ld\n", lRes
);
9980 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
9981 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
9982 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
9983 NULL
, 0, NULL
, NULL
) ||
9984 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
9985 "got bad length %ld\n", lRes
);
9987 ret
= DestroyWindow(hwnd
);
9988 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
9998 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
10002 #define TIMER_ID 0x19
10003 #define TIMER_COUNT_EXPECTED 100
10004 #define TIMER_COUNT_TOLERANCE 10
10006 static int count
= 0;
10007 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
10012 static DWORD exception
;
10013 static void CALLBACK
callback_exception(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
10016 RaiseException(exception
, 0, 0, NULL
);
10019 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
10021 struct timer_info
*info
= x
;
10024 r
= KillTimer(info
->hWnd
, 0x19);
10025 ok(r
,"KillTimer failed in thread\n");
10026 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
10027 ok(r
,"SetTimer failed in thread\n");
10028 ok(r
==TIMER_ID
,"SetTimer id different\n");
10029 r
= SetEvent(info
->handles
[0]);
10030 ok(r
,"SetEvent failed in thread\n");
10034 static void test_timers(void)
10036 struct timer_info info
;
10041 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
10042 WS_OVERLAPPEDWINDOW
,
10043 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
10046 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
10047 ok(info
.id
, "SetTimer failed\n");
10048 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
10049 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
10050 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
10052 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
10054 WaitForSingleObject(info
.handles
[1], INFINITE
);
10056 CloseHandle(info
.handles
[0]);
10057 CloseHandle(info
.handles
[1]);
10059 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
10061 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
10062 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
10063 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
10064 * ±9 counts (~4 ms) around the expected value.
10067 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
10068 ok(id
!= 0, "did not get id from SetTimer.\n");
10069 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
10070 start
= GetTickCount();
10071 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
10072 DispatchMessageA(&msg
);
10074 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
10075 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
10076 || broken(abs(count
-43) < TIMER_COUNT_TOLERANCE
) /* w2k3, win8 */,
10077 "did not get expected count for minimum timeout (%d != ~%d).\n",
10078 count
, TIMER_COUNT_EXPECTED
);
10079 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
10080 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
10081 if (pSetSystemTimer
)
10086 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
10087 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
10088 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
10089 start
= GetTickCount();
10090 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
10092 if (msg
.message
== WM_SYSTIMER
)
10094 DispatchMessageA(&msg
);
10096 ok(abs(syscount
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
10097 || broken(abs(syscount
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
10098 || broken(syscount
> 4000 && syscount
< 12000) /* win2k3sp0 */,
10099 "did not get expected count for minimum timeout (%d != ~%d).\n",
10100 syscount
, TIMER_COUNT_EXPECTED
);
10101 todo_wine
ok(count
== 0, "did not get expected count for callback timeout (%d != 0).\n",
10103 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
10106 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
10109 static void test_timers_no_wnd(void)
10111 static UINT_PTR ids
[0xffff];
10118 id
= SetTimer(NULL
, 0, 100, callback_count
);
10119 ok(id
!= 0, "did not get id from SetTimer.\n");
10120 id2
= SetTimer(NULL
, id
, 200, callback_count
);
10121 ok(id2
== id
, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2
, id
);
10123 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10124 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
10126 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10127 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
10128 KillTimer(NULL
, id
);
10130 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10131 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
10133 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
10134 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
10135 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
10136 * ±9 counts (~4 ms) around the expected value.
10139 id
= SetTimer(NULL
, 0, 0, callback_count
);
10140 ok(id
!= 0, "did not get id from SetTimer.\n");
10141 start
= GetTickCount();
10142 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, NULL
, 0, 0))
10143 DispatchMessageA(&msg
);
10145 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
10146 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */,
10147 "did not get expected count for minimum timeout (%d != ~%d).\n",
10148 count
, TIMER_COUNT_EXPECTED
);
10149 KillTimer(NULL
, id
);
10150 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
10152 if (pSetCoalescableTimer
)
10155 id
= pSetCoalescableTimer(NULL
, 0, 0, callback_count
, 0);
10156 ok(id
!= 0, "SetCoalescableTimer failed with %u.\n", GetLastError());
10157 start
= GetTickCount();
10158 while (GetTickCount()-start
< 100 && GetMessageA(&msg
, NULL
, 0, 0))
10159 DispatchMessageA(&msg
);
10160 ok(count
> 1, "expected count > 1, got %d.\n", count
);
10161 KillTimer(NULL
, id
);
10164 win_skip("SetCoalescableTimer not available.\n");
10166 /* Check what happens when we're running out of timers */
10167 for (i
=0; i
<sizeof(ids
)/sizeof(ids
[0]); i
++)
10169 SetLastError(0xdeadbeef);
10170 ids
[i
] = SetTimer(NULL
, 0, USER_TIMER_MAXIMUM
, tfunc
);
10171 if (!ids
[i
]) break;
10173 ok(i
!= sizeof(ids
)/sizeof(ids
[0]), "all timers were created successfully\n");
10174 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES
|| broken(GetLastError()==0xdeadbeef),
10175 "GetLastError() = %d\n", GetLastError());
10176 while (i
> 0) KillTimer(NULL
, ids
[--i
]);
10179 static void test_timers_exception(DWORD code
)
10185 id
= SetTimer(NULL
, 0, 1000, callback_exception
);
10186 ok(id
!= 0, "did not get id from SetTimer.\n");
10188 memset(&msg
, 0, sizeof(msg
));
10189 msg
.message
= WM_TIMER
;
10191 msg
.lParam
= (LPARAM
)callback_exception
;
10194 DispatchMessageA(&msg
);
10195 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
10197 KillTimer(NULL
, id
);
10200 static void test_timers_exceptions(void)
10202 test_timers_exception(EXCEPTION_ACCESS_VIOLATION
);
10203 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT
);
10204 test_timers_exception(EXCEPTION_BREAKPOINT
);
10205 test_timers_exception(EXCEPTION_SINGLE_STEP
);
10206 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED
);
10207 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND
);
10208 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO
);
10209 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT
);
10210 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION
);
10211 test_timers_exception(0xE000BEEF); /* customer exception */
10214 /* Various win events with arbitrary parameters */
10215 static const struct message WmWinEventsSeq
[] = {
10216 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
10217 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
10218 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
10219 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
10220 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
10221 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
10222 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
10223 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
10224 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
10225 /* our win event hook ignores OBJID_CURSOR events */
10226 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
10227 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
10228 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
10229 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
10230 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
10231 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
10232 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
10233 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
10234 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
10235 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
10236 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
10237 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
10238 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
10239 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
10242 static const struct message WmWinEventCaretSeq
[] = {
10243 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10244 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10245 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
10246 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10249 static const struct message WmWinEventCaretSeq_2
[] = {
10250 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10251 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10252 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10255 static const struct message WmWinEventAlertSeq
[] = {
10256 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
10259 static const struct message WmWinEventAlertSeq_2
[] = {
10260 /* create window in the thread proc */
10261 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
10262 /* our test event */
10263 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
10266 static const struct message WmGlobalHookSeq_1
[] = {
10267 /* create window in the thread proc */
10268 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
10269 /* our test events */
10270 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
10271 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
10274 static const struct message WmGlobalHookSeq_2
[] = {
10275 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
10276 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
10277 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
10278 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
10282 static const struct message WmMouseLLHookSeq
[] = {
10283 { WM_MOUSEMOVE
, hook
},
10284 { WM_LBUTTONUP
, hook
},
10285 { WM_MOUSEMOVE
, hook
},
10289 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
10299 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
10301 if (!lstrcmpiA(buf
, "TestWindowClass") ||
10302 !lstrcmpiA(buf
, "static"))
10304 struct recvd_message msg
;
10307 msg
.message
= event
;
10308 msg
.flags
= winevent_hook
|wparam
|lparam
;
10309 msg
.wParam
= object_id
;
10310 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
10311 msg
.descr
= "WEH_2";
10317 static HHOOK hCBT_global_hook
;
10318 static DWORD cbt_global_hook_thread_id
;
10320 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
10325 if (nCode
== HCBT_SYSCOMMAND
)
10327 struct recvd_message msg
;
10330 msg
.message
= nCode
;
10331 msg
.flags
= hook
|wparam
|lparam
;
10332 msg
.wParam
= wParam
;
10333 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
10334 msg
.descr
= "CBT_2";
10337 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
10339 /* WH_MOUSE_LL hook */
10340 if (nCode
== HC_ACTION
)
10342 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
10344 /* we can't test for real mouse events */
10345 if (mhll
->flags
& LLMHF_INJECTED
)
10347 struct recvd_message msg
;
10349 memset (&msg
, 0, sizeof (msg
));
10350 msg
.message
= wParam
;
10352 msg
.descr
= "CBT_2";
10355 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
10358 /* Log also SetFocus(0) calls */
10359 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
10361 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
10363 if (!lstrcmpiA(buf
, "TestWindowClass") ||
10364 !lstrcmpiA(buf
, "static"))
10366 struct recvd_message msg
;
10369 msg
.message
= nCode
;
10370 msg
.flags
= hook
|wparam
|lparam
;
10371 msg
.wParam
= wParam
;
10372 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
10373 msg
.descr
= "CBT_2";
10377 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
10380 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
10384 HANDLE hevent
= *(HANDLE
*)param
;
10386 assert(pNotifyWinEvent
);
10388 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
10390 trace("created thread window %p\n", hwnd
);
10392 *(HWND
*)param
= hwnd
;
10395 /* this event should be received only by our new hook proc,
10396 * an old one does not expect an event from another thread.
10398 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
10401 while (GetMessageA(&msg
, 0, 0, 0))
10403 TranslateMessage(&msg
);
10404 DispatchMessageA(&msg
);
10409 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
10413 HANDLE hevent
= *(HANDLE
*)param
;
10416 /* these events should be received only by our new hook proc,
10417 * an old one does not expect an event from another thread.
10420 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
10422 trace("created thread window %p\n", hwnd
);
10424 *(HWND
*)param
= hwnd
;
10426 /* Windows doesn't like when a thread plays games with the focus,
10427 that leads to all kinds of misbehaviours and failures to activate
10428 a window. So, better keep next lines commented out.
10432 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
10433 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
10437 while (GetMessageA(&msg
, 0, 0, 0))
10439 TranslateMessage(&msg
);
10440 DispatchMessageA(&msg
);
10445 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
10449 HANDLE hevent
= *(HANDLE
*)param
;
10451 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
10453 trace("created thread window %p\n", hwnd
);
10455 *(HWND
*)param
= hwnd
;
10459 /* Windows doesn't like when a thread plays games with the focus,
10460 * that leads to all kinds of misbehaviours and failures to activate
10461 * a window. So, better don't generate a mouse click message below.
10463 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10464 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
10465 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10468 while (GetMessageA(&msg
, 0, 0, 0))
10470 TranslateMessage(&msg
);
10471 DispatchMessageA(&msg
);
10476 static void test_winevents(void)
10482 HANDLE hthread
, hevent
;
10484 HWINEVENTHOOK hhook
;
10485 const struct message
*events
= WmWinEventsSeq
;
10487 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
10488 WS_OVERLAPPEDWINDOW
,
10489 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
10493 /****** start of global hook test *************/
10494 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
10495 if (!hCBT_global_hook
)
10497 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10498 skip( "cannot set global hook\n" );
10502 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10506 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
10507 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10509 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10511 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
10514 /* this one should be received only by old hook proc */
10515 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
10516 /* this one should be received only by old hook proc */
10517 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
10519 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
10521 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
10522 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
10524 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10525 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10526 CloseHandle(hthread
);
10527 CloseHandle(hevent
);
10528 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10529 /****** end of global hook test *************/
10531 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
10533 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10541 /* this test doesn't pass under Win9x */
10542 /* win2k ignores events with hwnd == 0 */
10543 SetLastError(0xdeadbeef);
10544 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
10545 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
10546 GetLastError() == 0xdeadbeef, /* Win9x */
10547 "unexpected error %d\n", GetLastError());
10548 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
10551 for (i
= 0; i
< sizeof(WmWinEventsSeq
)/sizeof(WmWinEventsSeq
[0]); i
++)
10552 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
10554 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
10556 /****** start of event filtering test *************/
10557 hhook
= pSetWinEventHook(
10558 EVENT_OBJECT_SHOW
, /* 0x8002 */
10559 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
10560 GetModuleHandleA(0), win_event_global_hook_proc
,
10561 GetCurrentProcessId(), 0,
10562 WINEVENT_INCONTEXT
);
10563 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10565 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10569 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
10570 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10572 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10574 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
10577 /* this one should be received only by old hook proc */
10578 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
10579 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
10580 /* this one should be received only by old hook proc */
10581 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
10583 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
10585 ret
= pUnhookWinEvent(hhook
);
10586 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10588 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10589 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10590 CloseHandle(hthread
);
10591 CloseHandle(hevent
);
10592 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10593 /****** end of event filtering test *************/
10595 /****** start of out of context event test *************/
10596 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
10597 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
10598 WINEVENT_OUTOFCONTEXT
);
10599 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10601 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10607 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
10608 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10610 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10612 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
10613 /* process pending winevent messages */
10614 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
10615 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
10618 /* this one should be received only by old hook proc */
10619 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
10620 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
10621 /* this one should be received only by old hook proc */
10622 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
10624 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
10625 /* process pending winevent messages */
10626 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
10627 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
10629 ret
= pUnhookWinEvent(hhook
);
10630 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10632 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10633 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10634 CloseHandle(hthread
);
10635 CloseHandle(hevent
);
10636 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10637 /****** end of out of context event test *************/
10639 /****** start of MOUSE_LL hook test *************/
10640 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
10641 /* WH_MOUSE_LL is not supported on Win9x platforms */
10642 if (!hCBT_global_hook
)
10644 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
10645 goto skip_mouse_ll_hook_test
;
10648 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10652 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
10653 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10655 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
10656 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
10658 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
10661 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10662 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
10663 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10665 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
10667 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
10668 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
10670 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10671 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10672 CloseHandle(hthread
);
10673 CloseHandle(hevent
);
10674 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10675 /****** end of MOUSE_LL hook test *************/
10676 skip_mouse_ll_hook_test
:
10678 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10681 static void test_set_hook(void)
10685 HWINEVENTHOOK hwinevent_hook
;
10687 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
10688 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
10689 UnhookWindowsHookEx(hhook
);
10693 /* this test doesn't pass under Win9x: BUG! */
10694 SetLastError(0xdeadbeef);
10695 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
10696 ok(!hhook
, "global hook requires hModule != 0\n");
10697 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %d\n", GetLastError());
10700 SetLastError(0xdeadbeef);
10701 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
10702 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
10703 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
|| /* Win2k */
10704 GetLastError() == 0xdeadbeef, /* Win9x */
10705 "unexpected error %d\n", GetLastError());
10707 SetLastError(0xdeadbeef);
10708 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
10709 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
|| /* Win2k */
10710 GetLastError() == 0xdeadbeef, /* Win9x */
10711 "unexpected error %d\n", GetLastError());
10713 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
10715 /* even process local incontext hooks require hmodule */
10716 SetLastError(0xdeadbeef);
10717 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10718 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
10719 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
10720 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
10721 GetLastError() == 0xdeadbeef, /* Win9x */
10722 "unexpected error %d\n", GetLastError());
10724 /* even thread local incontext hooks require hmodule */
10725 SetLastError(0xdeadbeef);
10726 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10727 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
10728 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
10729 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
10730 GetLastError() == 0xdeadbeef, /* Win9x */
10731 "unexpected error %d\n", GetLastError());
10735 /* these 3 tests don't pass under Win9x */
10736 SetLastError(0xdeadbeef);
10737 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
10738 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10739 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
10740 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
10742 SetLastError(0xdeadbeef);
10743 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
10744 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10745 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
10746 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
10748 SetLastError(0xdeadbeef);
10749 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10750 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
10751 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
10752 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %d\n", GetLastError());
10755 SetLastError(0xdeadbeef);
10756 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
10757 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10758 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10759 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10760 ret
= pUnhookWinEvent(hwinevent_hook
);
10761 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10764 /* This call succeeds under win2k SP4, but fails under Wine.
10765 Does win2k test/use passed process id? */
10766 SetLastError(0xdeadbeef);
10767 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10768 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
10769 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10770 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10771 ret
= pUnhookWinEvent(hwinevent_hook
);
10772 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10775 SetLastError(0xdeadbeef);
10776 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
10777 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
10778 GetLastError() == 0xdeadbeef, /* Win9x */
10779 "unexpected error %d\n", GetLastError());
10782 static HWND hook_hwnd
;
10783 static HHOOK recursive_hook
;
10784 static int hook_depth
, max_hook_depth
;
10786 static LRESULT WINAPI
rec_get_message_hook(int code
, WPARAM w
, LPARAM l
)
10793 if(hook_depth
> max_hook_depth
)
10794 max_hook_depth
= hook_depth
;
10796 b
= PeekMessageW(&msg
, hook_hwnd
, 0, 0, PM_NOREMOVE
);
10797 ok(b
, "PeekMessage failed\n");
10799 res
= CallNextHookEx(recursive_hook
, code
, w
, l
);
10805 static void test_recursive_hook(void)
10810 hook_hwnd
= CreateWindowA("Static", NULL
, WS_POPUP
, 0, 0, 200, 60, NULL
, NULL
, NULL
, NULL
);
10811 ok(hook_hwnd
!= NULL
, "CreateWindow failed\n");
10813 recursive_hook
= SetWindowsHookExW(WH_GETMESSAGE
, rec_get_message_hook
, NULL
, GetCurrentThreadId());
10814 ok(recursive_hook
!= NULL
, "SetWindowsHookEx failed\n");
10816 PostMessageW(hook_hwnd
, WM_USER
, 0, 0);
10817 PostMessageW(hook_hwnd
, WM_USER
+1, 0, 0);
10820 GetMessageW(&msg
, hook_hwnd
, 0, 0);
10821 ok(15 <= max_hook_depth
&& max_hook_depth
< 45, "max_hook_depth = %d\n", max_hook_depth
);
10822 trace("max_hook_depth = %d\n", max_hook_depth
);
10824 b
= UnhookWindowsHookEx(recursive_hook
);
10825 ok(b
, "UnhokWindowsHookEx failed\n");
10827 DestroyWindow(hook_hwnd
);
10830 static const struct message ScrollWindowPaint1
[] = {
10831 { WM_PAINT
, sent
},
10832 { WM_ERASEBKGND
, sent
|beginpaint
},
10833 { WM_GETTEXTLENGTH
, sent
|optional
},
10834 { WM_PAINT
, sent
|optional
},
10835 { WM_NCPAINT
, sent
|beginpaint
|optional
},
10836 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10837 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10838 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10839 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
10840 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
10844 static const struct message ScrollWindowPaint2
[] = {
10845 { WM_PAINT
, sent
},
10849 static void test_scrollwindowex(void)
10852 RECT rect
={0,0,130,130};
10854 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
10855 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
10856 100, 100, 200, 200, 0, 0, 0, NULL
);
10857 ok (hwnd
!= 0, "Failed to create overlapped window\n");
10858 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
10859 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
10860 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
10861 ok (hchild
!= 0, "Failed to create child\n");
10862 UpdateWindow(hwnd
);
10866 /* scroll without the child window */
10867 trace("start scroll\n");
10868 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
10869 SW_ERASE
|SW_INVALIDATE
);
10870 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
10871 trace("end scroll\n");
10874 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
10878 /* Now without the SW_ERASE flag */
10879 trace("start scroll\n");
10880 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
10881 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
10882 trace("end scroll\n");
10885 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
10889 /* now scroll the child window as well */
10890 trace("start scroll\n");
10891 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
10892 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
10893 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
10894 /* windows sometimes a WM_MOVE */
10895 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
10896 trace("end scroll\n");
10899 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
10903 /* now scroll with ScrollWindow() */
10904 trace("start scroll with ScrollWindow\n");
10905 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
10906 trace("end scroll\n");
10909 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
10911 ok(DestroyWindow(hchild
), "failed to destroy window\n");
10912 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10916 static const struct message destroy_window_with_children
[] = {
10917 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
10918 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10919 { 0x0090, sent
|optional
},
10920 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10921 { 0x0090, sent
|optional
},
10922 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
10923 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10924 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10925 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10926 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* parent */
10927 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10928 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
10929 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
10930 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
10931 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
10932 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
10933 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
10934 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10938 static void test_DestroyWindow(void)
10941 HWND parent
, child1
, child2
, child3
, child4
, test
;
10942 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
10944 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
10945 100, 100, 200, 200, 0, 0, 0, NULL
);
10946 assert(parent
!= 0);
10947 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10948 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
10949 assert(child1
!= 0);
10950 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10951 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
10952 assert(child2
!= 0);
10953 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10954 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
10955 assert(child3
!= 0);
10956 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
10957 0, 0, 50, 50, parent
, 0, 0, NULL
);
10958 assert(child4
!= 0);
10960 /* test owner/parent of child2 */
10961 test
= GetParent(child2
);
10962 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10963 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
10965 test
= pGetAncestor(child2
, GA_PARENT
);
10966 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10968 test
= GetWindow(child2
, GW_OWNER
);
10969 ok(!test
, "wrong owner %p\n", test
);
10971 test
= SetParent(child2
, parent
);
10972 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
10974 /* test owner/parent of the parent */
10975 test
= GetParent(parent
);
10976 ok(!test
, "wrong parent %p\n", test
);
10977 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
10979 test
= pGetAncestor(parent
, GA_PARENT
);
10980 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10982 test
= GetWindow(parent
, GW_OWNER
);
10983 ok(!test
, "wrong owner %p\n", test
);
10985 /* test owner/parent of child1 */
10986 test
= GetParent(child1
);
10987 ok(test
== parent
, "wrong parent %p\n", test
);
10988 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
10990 test
= pGetAncestor(child1
, GA_PARENT
);
10991 ok(test
== parent
, "wrong parent %p\n", test
);
10993 test
= GetWindow(child1
, GW_OWNER
);
10994 ok(!test
, "wrong owner %p\n", test
);
10996 /* test owner/parent of child2 */
10997 test
= GetParent(child2
);
10998 ok(test
== parent
, "wrong parent %p\n", test
);
10999 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
11001 test
= pGetAncestor(child2
, GA_PARENT
);
11002 ok(test
== parent
, "wrong parent %p\n", test
);
11004 test
= GetWindow(child2
, GW_OWNER
);
11005 ok(!test
, "wrong owner %p\n", test
);
11007 /* test owner/parent of child3 */
11008 test
= GetParent(child3
);
11009 ok(test
== child1
, "wrong parent %p\n", test
);
11010 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
11012 test
= pGetAncestor(child3
, GA_PARENT
);
11013 ok(test
== child1
, "wrong parent %p\n", test
);
11015 test
= GetWindow(child3
, GW_OWNER
);
11016 ok(!test
, "wrong owner %p\n", test
);
11018 /* test owner/parent of child4 */
11019 test
= GetParent(child4
);
11020 ok(test
== parent
, "wrong parent %p\n", test
);
11021 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
11023 test
= pGetAncestor(child4
, GA_PARENT
);
11024 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
11026 test
= GetWindow(child4
, GW_OWNER
);
11027 ok(test
== parent
, "wrong owner %p\n", test
);
11031 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
11032 parent
, child1
, child2
, child3
, child4
);
11034 SetCapture(child4
);
11035 test
= GetCapture();
11036 ok(test
== child4
, "wrong capture window %p\n", test
);
11038 test_DestroyWindow_flag
= TRUE
;
11039 ret
= DestroyWindow(parent
);
11040 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
11041 test_DestroyWindow_flag
= FALSE
;
11042 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
11044 ok(!IsWindow(parent
), "parent still exists\n");
11045 ok(!IsWindow(child1
), "child1 still exists\n");
11046 ok(!IsWindow(child2
), "child2 still exists\n");
11047 ok(!IsWindow(child3
), "child3 still exists\n");
11048 ok(!IsWindow(child4
), "child4 still exists\n");
11050 test
= GetCapture();
11051 ok(!test
, "wrong capture window %p\n", test
);
11055 static const struct message WmDispatchPaint
[] = {
11056 { WM_NCPAINT
, sent
},
11057 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11058 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11059 { WM_ERASEBKGND
, sent
},
11063 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11065 if (message
== WM_PAINT
) return 0;
11066 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
11069 static void test_DispatchMessage(void)
11074 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11075 100, 100, 200, 200, 0, 0, 0, NULL
);
11076 ShowWindow( hwnd
, SW_SHOW
);
11077 UpdateWindow( hwnd
);
11080 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
11082 SetRect( &rect
, -5, -5, 5, 5 );
11083 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11085 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11087 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11091 DispatchMessageA( &msg
);
11092 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
11093 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11094 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
11095 if (++count
> 10) break;
11098 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
11100 trace("now without DispatchMessage\n");
11102 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11104 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11106 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11109 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
11111 /* this will send WM_NCCPAINT just like DispatchMessage does */
11112 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
11113 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11114 DeleteObject( hrgn
);
11115 GetClientRect( hwnd
, &rect
);
11116 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
11117 ok( !count
, "Got multiple WM_PAINTs\n" );
11118 if (++count
> 10) break;
11123 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11125 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11127 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11133 hdc
= BeginPaint( hwnd
, NULL
);
11134 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
11135 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
11136 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11137 ok( !count
, "Got multiple WM_PAINTs\n" );
11138 if (++count
> 10) break;
11141 DestroyWindow(hwnd
);
11145 static const struct message WmUser
[] = {
11150 struct sendmsg_info
11157 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
11159 struct sendmsg_info
*info
= arg
;
11160 SetLastError( 0xdeadbeef );
11161 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
11162 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
11163 broken(GetLastError() == 0), /* win9x */
11164 "unexpected error %d\n", GetLastError());
11168 static void wait_for_thread( HANDLE thread
)
11170 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
11173 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11177 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11179 if (message
== WM_USER
) Sleep(200);
11180 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
11183 static void test_SendMessageTimeout(void)
11186 struct sendmsg_info info
;
11190 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11191 100, 100, 200, 200, 0, 0, 0, NULL
);
11195 info
.timeout
= 1000;
11196 info
.ret
= 0xdeadbeef;
11197 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11198 wait_for_thread( thread
);
11199 CloseHandle( thread
);
11200 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11201 ok_sequence( WmUser
, "WmUser", FALSE
);
11204 info
.ret
= 0xdeadbeef;
11205 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11206 Sleep(100); /* SendMessageTimeout should time out here */
11207 wait_for_thread( thread
);
11208 CloseHandle( thread
);
11209 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
11210 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11212 /* 0 means infinite timeout (but not on win9x) */
11214 info
.ret
= 0xdeadbeef;
11215 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11217 wait_for_thread( thread
);
11218 CloseHandle( thread
);
11219 is_win9x
= !info
.ret
;
11220 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11221 else ok_sequence( WmUser
, "WmUser", FALSE
);
11223 /* timeout is treated as signed despite the prototype (but not on win9x) */
11224 info
.timeout
= 0x7fffffff;
11225 info
.ret
= 0xdeadbeef;
11226 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11228 wait_for_thread( thread
);
11229 CloseHandle( thread
);
11230 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11231 ok_sequence( WmUser
, "WmUser", FALSE
);
11233 info
.timeout
= 0x80000000;
11234 info
.ret
= 0xdeadbeef;
11235 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11237 wait_for_thread( thread
);
11238 CloseHandle( thread
);
11241 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11242 ok_sequence( WmUser
, "WmUser", FALSE
);
11246 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
11247 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11250 /* now check for timeout during message processing */
11251 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
11252 info
.timeout
= 100;
11253 info
.ret
= 0xdeadbeef;
11254 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11255 wait_for_thread( thread
);
11256 CloseHandle( thread
);
11257 /* we should time out but still get the message */
11258 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
11259 ok_sequence( WmUser
, "WmUser", FALSE
);
11261 DestroyWindow( info
.hwnd
);
11265 /****************** edit message test *************************/
11266 #define ID_EDIT 0x1234
11267 static const struct message sl_edit_setfocus
[] =
11269 { HCBT_SETFOCUS
, hook
},
11270 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11271 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11272 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11273 { WM_SETFOCUS
, sent
|wparam
, 0 },
11274 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11275 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
11276 { WM_CTLCOLOREDIT
, sent
|parent
},
11277 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11278 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11279 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11280 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11283 static const struct message sl_edit_invisible
[] =
11285 { HCBT_SETFOCUS
, hook
},
11286 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11287 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11288 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11289 { WM_KILLFOCUS
, sent
|parent
},
11290 { WM_SETFOCUS
, sent
},
11291 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11294 static const struct message ml_edit_setfocus
[] =
11296 { HCBT_SETFOCUS
, hook
},
11297 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11298 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11299 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11300 { WM_SETFOCUS
, sent
|wparam
, 0 },
11301 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11302 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11303 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11304 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11305 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11308 static const struct message sl_edit_killfocus
[] =
11310 { HCBT_SETFOCUS
, hook
},
11311 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11312 { WM_KILLFOCUS
, sent
|wparam
, 0 },
11313 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11314 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11315 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
11316 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
11317 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11320 static const struct message sl_edit_lbutton_dblclk
[] =
11322 { WM_LBUTTONDBLCLK
, sent
},
11323 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
11326 static const struct message sl_edit_lbutton_down
[] =
11328 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
11329 { HCBT_SETFOCUS
, hook
},
11330 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11331 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11332 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11333 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
11334 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11335 { WM_CTLCOLOREDIT
, sent
|parent
},
11336 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11337 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11338 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11339 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11340 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11341 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
11342 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11343 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
11344 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11345 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11346 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11349 static const struct message ml_edit_lbutton_down
[] =
11351 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
11352 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
11353 { HCBT_SETFOCUS
, hook
},
11354 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11355 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11356 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11357 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
11358 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11359 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11360 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11361 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11362 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11365 static const struct message sl_edit_lbutton_up
[] =
11367 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
11368 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11369 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
11370 { WM_CAPTURECHANGED
, sent
|defwinproc
},
11371 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11374 static const struct message ml_edit_lbutton_up
[] =
11376 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
11377 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
11378 { WM_CAPTURECHANGED
, sent
|defwinproc
},
11382 static WNDPROC old_edit_proc
;
11384 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11386 static LONG defwndproc_counter
= 0;
11388 struct recvd_message msg
;
11390 if (ignore_message( message
)) return 0;
11393 msg
.message
= message
;
11394 msg
.flags
= sent
|wparam
|lparam
;
11395 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11396 msg
.wParam
= wParam
;
11397 msg
.lParam
= lParam
;
11398 msg
.descr
= "edit";
11401 defwndproc_counter
++;
11402 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
11403 defwndproc_counter
--;
11408 static void subclass_edit(void)
11412 if (!GetClassInfoA(0, "edit", &cls
)) assert(0);
11414 old_edit_proc
= cls
.lpfnWndProc
;
11416 cls
.hInstance
= GetModuleHandleA(NULL
);
11417 cls
.lpfnWndProc
= edit_hook_proc
;
11418 cls
.lpszClassName
= "my_edit_class";
11419 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
11420 if (!RegisterClassA(&cls
)) assert(0);
11423 static void test_edit_messages(void)
11429 log_all_parent_messages
++;
11431 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11432 100, 100, 200, 200, 0, 0, 0, NULL
);
11433 ok (parent
!= 0, "Failed to create parent window\n");
11435 /* test single line edit */
11436 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
11437 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
11438 ok(hwnd
!= 0, "Failed to create edit window\n");
11440 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
11441 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08x\n", dlg_code
);
11445 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
11447 ShowWindow(hwnd
, SW_SHOW
);
11448 UpdateWindow(hwnd
);
11453 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
11456 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
11462 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
11463 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
11469 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
11470 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
11472 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
11473 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
11475 DestroyWindow(hwnd
);
11477 /* test multiline edit */
11478 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
11479 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
11480 ok(hwnd
!= 0, "Failed to create edit window\n");
11482 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
11483 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
11484 "wrong dlg_code %08x\n", dlg_code
);
11486 ShowWindow(hwnd
, SW_SHOW
);
11487 UpdateWindow(hwnd
);
11492 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
11495 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
11501 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
11502 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
11508 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
11509 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
11511 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
11512 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
11514 DestroyWindow(hwnd
);
11515 DestroyWindow(parent
);
11517 log_all_parent_messages
--;
11520 /**************************** End of Edit test ******************************/
11522 static const struct message WmKeyDownSkippedSeq
[] =
11524 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
11527 static const struct message WmKeyDownWasDownSkippedSeq
[] =
11529 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
11532 static const struct message WmKeyUpSkippedSeq
[] =
11534 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
11537 static const struct message WmUserKeyUpSkippedSeq
[] =
11540 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
11545 #define EV_SENDMSG 1
11548 struct peekmsg_info
11551 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
11554 static DWORD CALLBACK
send_msg_thread_2(void *param
)
11557 struct peekmsg_info
*info
= param
;
11559 trace("thread: looping\n");
11560 SetEvent(info
->hevent
[EV_ACK
]);
11564 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
11568 case WAIT_OBJECT_0
+ EV_STOP
:
11569 trace("thread: exiting\n");
11572 case WAIT_OBJECT_0
+ EV_SENDMSG
:
11573 trace("thread: sending message\n");
11574 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
11575 ok(ret
, "SendNotifyMessageA failed error %u\n", GetLastError());
11576 SetEvent(info
->hevent
[EV_ACK
]);
11580 trace("unexpected return: %04x\n", ret
);
11588 static void test_PeekMessage(void)
11592 DWORD tid
, qstatus
;
11593 UINT qs_all_input
= QS_ALLINPUT
;
11594 UINT qs_input
= QS_INPUT
;
11596 struct peekmsg_info info
;
11598 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11599 100, 100, 200, 200, 0, 0, 0, NULL
);
11601 ShowWindow(info
.hwnd
, SW_SHOW
);
11602 UpdateWindow(info
.hwnd
);
11603 SetFocus(info
.hwnd
);
11605 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
11606 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
11607 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
11609 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
11610 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
11615 SetLastError(0xdeadbeef);
11616 qstatus
= GetQueueStatus(qs_all_input
);
11617 if (GetLastError() == ERROR_INVALID_FLAGS
)
11619 trace("QS_RAWINPUT not supported on this platform\n");
11620 qs_all_input
&= ~QS_RAWINPUT
;
11621 qs_input
&= ~QS_RAWINPUT
;
11623 if (qstatus
& QS_POSTMESSAGE
)
11625 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
11626 qstatus
= GetQueueStatus(qs_all_input
);
11628 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11630 trace("signalling to send message\n");
11631 SetEvent(info
.hevent
[EV_SENDMSG
]);
11632 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11634 /* pass invalid QS_xxxx flags */
11635 SetLastError(0xdeadbeef);
11636 qstatus
= GetQueueStatus(0xffffffff);
11637 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus
);
11640 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %d\n", GetLastError());
11641 qstatus
= GetQueueStatus(qs_all_input
);
11643 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
11644 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
),
11645 "wrong qstatus %08x\n", qstatus
);
11648 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11650 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11652 ok_sequence(WmUser
, "WmUser", FALSE
);
11654 qstatus
= GetQueueStatus(qs_all_input
);
11655 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11657 keybd_event('N', 0, 0, 0);
11658 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
11659 qstatus
= GetQueueStatus(qs_all_input
);
11660 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
11662 skip( "queuing key events not supported\n" );
11665 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
11666 /* keybd_event seems to trigger a sent message on NT4 */
11667 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
11668 "wrong qstatus %08x\n", qstatus
);
11670 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11671 qstatus
= GetQueueStatus(qs_all_input
);
11672 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
11673 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
11674 "wrong qstatus %08x\n", qstatus
);
11676 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
11677 qstatus
= GetQueueStatus(qs_all_input
);
11678 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
11679 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
11680 "wrong qstatus %08x\n", qstatus
);
11682 trace("signalling to send message\n");
11683 SetEvent(info
.hevent
[EV_SENDMSG
]);
11684 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11686 qstatus
= GetQueueStatus(qs_all_input
);
11687 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11688 "wrong qstatus %08x\n", qstatus
);
11691 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
11692 if (ret
&& msg
.message
== WM_CHAR
)
11694 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11698 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11700 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
11702 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11705 ok_sequence(WmUser
, "WmUser", FALSE
);
11707 qstatus
= GetQueueStatus(qs_all_input
);
11708 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11709 "wrong qstatus %08x\n", qstatus
);
11711 trace("signalling to send message\n");
11712 SetEvent(info
.hevent
[EV_SENDMSG
]);
11713 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11715 qstatus
= GetQueueStatus(qs_all_input
);
11716 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11717 "wrong qstatus %08x\n", qstatus
);
11720 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11722 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11724 ok_sequence(WmUser
, "WmUser", FALSE
);
11726 qstatus
= GetQueueStatus(qs_all_input
);
11727 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11728 "wrong qstatus %08x\n", qstatus
);
11731 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11732 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11733 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11734 ret
, msg
.message
, msg
.wParam
);
11735 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11737 qstatus
= GetQueueStatus(qs_all_input
);
11738 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
11739 "wrong qstatus %08x\n", qstatus
);
11742 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11744 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11746 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11748 qstatus
= GetQueueStatus(qs_all_input
);
11749 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
11750 "wrong qstatus %08x\n", qstatus
);
11753 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
11754 ok(ret
&& msg
.message
== WM_PAINT
,
11755 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
11756 DispatchMessageA(&msg
);
11757 ok_sequence(WmPaint
, "WmPaint", FALSE
);
11759 qstatus
= GetQueueStatus(qs_all_input
);
11760 ok(qstatus
== MAKELONG(0, QS_KEY
),
11761 "wrong qstatus %08x\n", qstatus
);
11764 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
11766 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11768 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11770 qstatus
= GetQueueStatus(qs_all_input
);
11771 ok(qstatus
== MAKELONG(0, QS_KEY
),
11772 "wrong qstatus %08x\n", qstatus
);
11774 trace("signalling to send message\n");
11775 SetEvent(info
.hevent
[EV_SENDMSG
]);
11776 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11778 qstatus
= GetQueueStatus(qs_all_input
);
11779 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
11780 "wrong qstatus %08x\n", qstatus
);
11782 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11784 qstatus
= GetQueueStatus(qs_all_input
);
11785 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11786 "wrong qstatus %08x\n", qstatus
);
11789 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
11790 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11791 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11792 ret
, msg
.message
, msg
.wParam
);
11793 ok_sequence(WmUser
, "WmUser", FALSE
);
11795 qstatus
= GetQueueStatus(qs_all_input
);
11796 ok(qstatus
== MAKELONG(0, QS_KEY
),
11797 "wrong qstatus %08x\n", qstatus
);
11800 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
11802 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11804 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11806 qstatus
= GetQueueStatus(qs_all_input
);
11807 ok(qstatus
== MAKELONG(0, QS_KEY
),
11808 "wrong qstatus %08x\n", qstatus
);
11810 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11812 qstatus
= GetQueueStatus(qs_all_input
);
11813 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
11814 "wrong qstatus %08x\n", qstatus
);
11816 trace("signalling to send message\n");
11817 SetEvent(info
.hevent
[EV_SENDMSG
]);
11818 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11820 qstatus
= GetQueueStatus(qs_all_input
);
11821 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11822 "wrong qstatus %08x\n", qstatus
);
11825 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
11827 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11829 ok_sequence(WmUser
, "WmUser", FALSE
);
11831 qstatus
= GetQueueStatus(qs_all_input
);
11832 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
11833 "wrong qstatus %08x\n", qstatus
);
11836 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
11837 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
11838 else /* workaround for a missing QS_RAWINPUT support */
11839 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
11840 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11841 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11842 ret
, msg
.message
, msg
.wParam
);
11843 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
11845 qstatus
= GetQueueStatus(qs_all_input
);
11846 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
11847 "wrong qstatus %08x\n", qstatus
);
11850 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
11851 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
11852 else /* workaround for a missing QS_RAWINPUT support */
11853 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
11854 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
11855 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n",
11856 ret
, msg
.message
, msg
.wParam
);
11857 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
11859 qstatus
= GetQueueStatus(qs_all_input
);
11860 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11861 "wrong qstatus %08x\n", qstatus
);
11864 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
11866 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11868 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11870 qstatus
= GetQueueStatus(qs_all_input
);
11871 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11872 "wrong qstatus %08x\n", qstatus
);
11875 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11876 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11877 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11878 ret
, msg
.message
, msg
.wParam
);
11879 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11881 qstatus
= GetQueueStatus(qs_all_input
);
11883 "wrong qstatus %08x\n", qstatus
);
11886 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11888 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11890 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11892 qstatus
= GetQueueStatus(qs_all_input
);
11894 "wrong qstatus %08x\n", qstatus
);
11896 /* test whether presence of the quit flag in the queue affects
11899 PostQuitMessage(0x1234abcd);
11901 qstatus
= GetQueueStatus(qs_all_input
);
11902 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
11903 "wrong qstatus %08x\n", qstatus
);
11905 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
11907 qstatus
= GetQueueStatus(qs_all_input
);
11908 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
11909 "wrong qstatus %08x\n", qstatus
);
11912 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11913 ok(ret
&& msg
.message
== WM_USER
,
11914 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
11915 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11917 qstatus
= GetQueueStatus(qs_all_input
);
11918 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11919 "wrong qstatus %08x\n", qstatus
);
11922 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11923 ok(ret
&& msg
.message
== WM_QUIT
,
11924 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
11925 ok(msg
.wParam
== 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg
.wParam
);
11926 ok(msg
.lParam
== 0, "got lParam %08lx instead of 0\n", msg
.lParam
);
11927 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11929 qstatus
= GetQueueStatus(qs_all_input
);
11931 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11932 "wrong qstatus %08x\n", qstatus
);
11936 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11938 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11940 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11942 qstatus
= GetQueueStatus(qs_all_input
);
11944 "wrong qstatus %08x\n", qstatus
);
11946 /* some GetMessage tests */
11948 keybd_event('N', 0, 0, 0);
11949 qstatus
= GetQueueStatus(qs_all_input
);
11950 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11952 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11953 qstatus
= GetQueueStatus(qs_all_input
);
11954 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11958 ret
= GetMessageA( &msg
, 0, 0, 0 );
11959 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11960 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11961 ret
, msg
.message
, msg
.wParam
);
11962 qstatus
= GetQueueStatus(qs_all_input
);
11963 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11968 ret
= GetMessageA( &msg
, 0, 0, 0 );
11969 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11970 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11971 ret
, msg
.message
, msg
.wParam
);
11972 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
11973 qstatus
= GetQueueStatus(qs_all_input
);
11974 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11977 keybd_event('N', 0, 0, 0);
11978 qstatus
= GetQueueStatus(qs_all_input
);
11979 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11981 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11982 qstatus
= GetQueueStatus(qs_all_input
);
11983 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11985 if (qstatus
& (QS_KEY
<< 16))
11987 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
11988 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11989 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11990 ret
, msg
.message
, msg
.wParam
);
11991 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
11992 qstatus
= GetQueueStatus(qs_all_input
);
11993 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
11998 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
11999 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12000 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
12001 ret
, msg
.message
, msg
.wParam
);
12002 qstatus
= GetQueueStatus(qs_all_input
);
12003 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
12006 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
12007 qstatus
= GetQueueStatus(qs_all_input
);
12008 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
12010 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
12011 qstatus
= GetQueueStatus(qs_all_input
);
12012 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
12014 trace("signalling to send message\n");
12015 SetEvent(info
.hevent
[EV_SENDMSG
]);
12016 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
12017 qstatus
= GetQueueStatus(qs_all_input
);
12018 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
12019 "wrong qstatus %08x\n", qstatus
);
12021 if (qstatus
& (QS_KEY
<< 16))
12023 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
12024 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
12025 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12026 ret
, msg
.message
, msg
.wParam
);
12027 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
12028 qstatus
= GetQueueStatus(qs_all_input
);
12029 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
12034 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
12035 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
12036 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
12037 ret
, msg
.message
, msg
.wParam
);
12038 qstatus
= GetQueueStatus(qs_all_input
);
12039 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
12042 trace("signalling to exit\n");
12043 SetEvent(info
.hevent
[EV_STOP
]);
12045 WaitForSingleObject(hthread
, INFINITE
);
12047 CloseHandle(hthread
);
12048 CloseHandle(info
.hevent
[0]);
12049 CloseHandle(info
.hevent
[1]);
12050 CloseHandle(info
.hevent
[2]);
12052 DestroyWindow(info
.hwnd
);
12055 static void wait_move_event(HWND hwnd
, int x
, int y
)
12061 time
= GetTickCount();
12062 while (GetTickCount() - time
< 200) {
12063 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12064 if (ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
) break;
12065 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, GetTickCount() - time
, QS_ALLINPUT
);
12066 else Sleep( GetTickCount() - time
);
12071 static void test_PeekMessage2(void)
12077 DWORD time1
, time2
, time3
;
12078 int x1
, y1
, x2
, y2
, x3
, y3
;
12081 time1
= time2
= time3
= 0;
12082 x1
= y1
= x2
= y2
= x3
= y3
= 0;
12084 /* Initialise window and make sure it is ready for events */
12085 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
12086 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
12088 trace("Window for test_PeekMessage2 %p\n", hwnd
);
12089 ShowWindow(hwnd
, SW_SHOW
);
12090 UpdateWindow(hwnd
);
12092 GetCursorPos(&pos
);
12093 SetCursorPos(100, 100);
12094 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
12097 /* Do initial mousemove, wait until we can see it
12098 and then do our test peek with PM_NOREMOVE. */
12099 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
12100 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
12102 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12105 skip( "queuing mouse events not supported\n" );
12110 trace("1st move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
12111 message
= msg
.message
;
12115 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
12118 /* Allow time to advance a bit, and then simulate the user moving their
12119 * mouse around. After that we peek again with PM_NOREMOVE.
12120 * Although the previous mousemove message was never removed, the
12121 * mousemove we now peek should reflect the recent mouse movements
12122 * because the input queue will merge the move events. */
12124 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
12125 wait_move_event(hwnd
, x1
, y1
);
12127 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12128 ok(ret
, "no message available\n");
12130 trace("2nd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
12131 message
= msg
.message
;
12135 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
12136 ok(time2
> time1
, "message time not advanced: %x %x\n", time1
, time2
);
12137 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
12140 /* Have another go, to drive the point home */
12142 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
12143 wait_move_event(hwnd
, x2
, y2
);
12145 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12146 ok(ret
, "no message available\n");
12148 trace("3rd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
12149 message
= msg
.message
;
12153 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
12154 ok(time3
> time2
, "message time not advanced: %x %x\n", time2
, time3
);
12155 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
12159 DestroyWindow(hwnd
);
12160 SetCursorPos(pos
.x
, pos
.y
);
12164 static void test_PeekMessage3(void)
12170 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW
,
12171 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
12172 ok(hwnd
!= NULL
, "expected hwnd != NULL\n");
12175 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
12176 * were already seen. */
12178 SetTimer(hwnd
, 1, 0, NULL
);
12179 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
12180 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12181 PostMessageA(hwnd
, WM_USER
, 0, 0);
12182 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
12183 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12184 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12185 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12186 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12187 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12188 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12189 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12191 SetTimer(hwnd
, 1, 0, NULL
);
12192 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
12193 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12194 PostMessageA(hwnd
, WM_USER
, 0, 0);
12195 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12196 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12197 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12198 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12199 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12200 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12202 /* It doesn't matter if a message range is specified or not. */
12204 SetTimer(hwnd
, 1, 0, NULL
);
12205 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12206 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12207 PostMessageA(hwnd
, WM_USER
, 0, 0);
12208 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12209 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12210 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12211 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12212 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12213 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12215 /* But not if the post messages were added before the PeekMessage() call. */
12217 PostMessageA(hwnd
, WM_USER
, 0, 0);
12218 SetTimer(hwnd
, 1, 0, NULL
);
12219 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12220 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12221 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12222 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12223 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12224 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12225 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12226 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12228 /* More complicated test with multiple messages. */
12230 PostMessageA(hwnd
, WM_USER
, 0, 0);
12231 SetTimer(hwnd
, 1, 0, NULL
);
12232 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12233 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12234 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
12235 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12236 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12237 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12238 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12239 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12240 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
12241 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12242 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12244 /* Newer messages are still returned when specifying a message range. */
12246 SetTimer(hwnd
, 1, 0, NULL
);
12247 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12248 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12249 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
12250 PostMessageA(hwnd
, WM_USER
, 0, 0);
12251 ret
= PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
12252 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12253 ret
= PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
+ 1, PM_NOREMOVE
);
12254 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
12255 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12256 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12257 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12258 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
12259 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12260 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12261 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12262 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12264 /* Also works for posted messages, but the situation is a bit different,
12265 * because both messages are in the same queue. */
12267 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
12268 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12269 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12270 PostMessageA(hwnd
, WM_USER
, 0, 0);
12271 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12272 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12273 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12274 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12275 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12276 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12278 PostMessageA(hwnd
, WM_USER
, 0, 0);
12279 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
12280 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12281 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12282 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12283 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12284 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12285 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12286 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12287 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12289 DestroyWindow(hwnd
);
12293 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12295 struct recvd_message msg
;
12297 if (ignore_message( message
)) return 0;
12300 msg
.message
= message
;
12301 msg
.flags
= sent
|wparam
|lparam
;
12304 msg
.descr
= "dialog";
12309 case WM_INITDIALOG
:
12310 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
12311 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
12314 case WM_GETDLGCODE
:
12318 EndDialog(hwnd
, 0);
12325 static const struct message WmQuitDialogSeq
[] = {
12326 { HCBT_CREATEWND
, hook
},
12327 { WM_SETFONT
, sent
},
12328 { WM_INITDIALOG
, sent
},
12329 { WM_CHANGEUISTATE
, sent
|optional
},
12330 { HCBT_DESTROYWND
, hook
},
12331 { 0x0090, sent
|optional
}, /* Vista */
12332 { WM_DESTROY
, sent
},
12333 { WM_NCDESTROY
, sent
},
12337 static const struct message WmStopQuitSeq
[] = {
12338 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
12339 { WM_CLOSE
, posted
},
12340 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
12344 static void test_quit_message(void)
12349 /* test using PostQuitMessage */
12351 PostQuitMessage(0xbeef);
12354 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_QS_SENDMESSAGE
);
12355 ok(!ret
, "got %x message\n", msg
.message
);
12357 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
12358 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
12359 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12360 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
12362 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
12363 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
12365 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12366 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
12367 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
12369 /* note: WM_QUIT message received after WM_USER message */
12370 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12371 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
12372 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12373 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
12375 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12376 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
12378 /* now test with PostThreadMessage - different behaviour! */
12379 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
12381 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
12382 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
12383 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12384 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
12386 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
12387 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
12389 /* note: we receive the WM_QUIT message first this time */
12390 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12391 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
12392 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12393 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
12395 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12396 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
12397 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
12401 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
12402 ok(ret
== 1, "expected 1, got %d\n", ret
);
12403 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
12404 memset(&msg
, 0xab, sizeof(msg
));
12405 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12406 ok(ret
, "PeekMessage failed\n");
12407 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12408 ok(msg
.wParam
== 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg
.wParam
);
12409 ok(msg
.lParam
== 0, "lParam was 0x%lx instead of 0\n", msg
.lParam
);
12411 /* Check what happens to a WM_QUIT message posted to a window that gets
12414 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
12415 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
12417 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12419 struct recvd_message rmsg
;
12420 rmsg
.hwnd
= msg
.hwnd
;
12421 rmsg
.message
= msg
.message
;
12422 rmsg
.flags
= posted
|wparam
|lparam
;
12423 rmsg
.wParam
= msg
.wParam
;
12424 rmsg
.lParam
= msg
.lParam
;
12425 rmsg
.descr
= "stop/quit";
12426 if (msg
.message
== WM_QUIT
)
12427 /* The hwnd can only be checked here */
12428 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
12429 add_message(&rmsg
);
12430 DispatchMessageA(&msg
);
12432 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
12435 static const struct message WmNotifySeq
[] = {
12436 { WM_NOTIFY
, sent
|wparam
|lparam
, 0x1234, 0xdeadbeef },
12440 static void test_notify_message(void)
12446 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12447 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0, NULL
, NULL
, 0);
12448 ok(hwnd
!= 0, "Failed to create window\n");
12452 ret
= SendNotifyMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12453 ok(ret
== TRUE
, "SendNotifyMessageA failed with error %u\n", GetLastError());
12454 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12456 ret
= SendNotifyMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12457 ok(ret
== TRUE
, "SendNotifyMessageW failed with error %u\n", GetLastError());
12458 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12460 ret
= SendMessageCallbackA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
12461 ok(ret
== TRUE
, "SendMessageCallbackA failed with error %u\n", GetLastError());
12462 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12464 ret
= SendMessageCallbackW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
12465 ok(ret
== TRUE
, "SendMessageCallbackW failed with error %u\n", GetLastError());
12466 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12468 ret
= PostMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12469 ok(ret
== TRUE
, "PostMessageA failed with error %u\n", GetLastError());
12471 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12473 ret
= PostMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12474 ok(ret
== TRUE
, "PostMessageW failed with error %u\n", GetLastError());
12476 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12478 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
12479 ok(ret
== TRUE
, "PostThreadMessageA failed with error %u\n", GetLastError());
12480 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12483 DispatchMessageA(&msg
);
12485 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12487 ret
= PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
12488 ok(ret
== TRUE
, "PostThreadMessageW failed with error %u\n", GetLastError());
12489 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12492 DispatchMessageA(&msg
);
12494 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12496 DestroyWindow(hwnd
);
12499 static const struct message WmMouseHoverSeq
[] = {
12500 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
12501 { WM_MOUSEACTIVATE
, sent
|optional
},
12502 { WM_TIMER
, sent
|optional
}, /* XP sends it */
12503 { WM_SYSTIMER
, sent
},
12504 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
12508 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
12511 DWORD start_ticks
, end_ticks
;
12513 start_ticks
= GetTickCount();
12514 /* add some deviation (50%) to cover not expected delays */
12515 start_ticks
+= timeout
/ 2;
12519 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12521 /* Timer proc messages are not dispatched to the window proc,
12522 * and therefore not logged.
12524 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
12526 struct recvd_message s_msg
;
12528 s_msg
.hwnd
= msg
.hwnd
;
12529 s_msg
.message
= msg
.message
;
12530 s_msg
.flags
= sent
|wparam
|lparam
;
12531 s_msg
.wParam
= msg
.wParam
;
12532 s_msg
.lParam
= msg
.lParam
;
12533 s_msg
.descr
= "msg_loop";
12534 add_message(&s_msg
);
12536 DispatchMessageA(&msg
);
12539 end_ticks
= GetTickCount();
12541 /* inject WM_MOUSEMOVE to see how it changes tracking */
12542 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
12544 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12545 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12547 inject_mouse_move
= FALSE
;
12549 } while (start_ticks
+ timeout
>= end_ticks
);
12552 static void test_TrackMouseEvent(void)
12554 TRACKMOUSEEVENT tme
;
12557 RECT rc_parent
, rc_child
;
12558 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
12560 #define track_hover(track_hwnd, track_hover_time) \
12561 tme.cbSize = sizeof(tme); \
12562 tme.dwFlags = TME_HOVER; \
12563 tme.hwndTrack = track_hwnd; \
12564 tme.dwHoverTime = track_hover_time; \
12565 SetLastError(0xdeadbeef); \
12566 ret = pTrackMouseEvent(&tme); \
12567 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError())
12569 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
12570 tme.cbSize = sizeof(tme); \
12571 tme.dwFlags = TME_QUERY; \
12572 tme.hwndTrack = (HWND)0xdeadbeef; \
12573 tme.dwHoverTime = 0xdeadbeef; \
12574 SetLastError(0xdeadbeef); \
12575 ret = pTrackMouseEvent(&tme); \
12576 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\
12577 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \
12578 ok(tme.dwFlags == (expected_track_flags), \
12579 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
12580 ok(tme.hwndTrack == (expected_track_hwnd), \
12581 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
12582 ok(tme.dwHoverTime == (expected_hover_time), \
12583 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time))
12585 #define track_hover_cancel(track_hwnd) \
12586 tme.cbSize = sizeof(tme); \
12587 tme.dwFlags = TME_HOVER | TME_CANCEL; \
12588 tme.hwndTrack = track_hwnd; \
12589 tme.dwHoverTime = 0xdeadbeef; \
12590 SetLastError(0xdeadbeef); \
12591 ret = pTrackMouseEvent(&tme); \
12592 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError())
12594 default_hover_time
= 0xdeadbeef;
12595 SetLastError(0xdeadbeef);
12596 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
12597 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
12598 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError());
12599 if (!ret
) default_hover_time
= 400;
12600 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
12602 SetLastError(0xdeadbeef);
12603 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
12604 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
12605 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError());
12606 if (!ret
) hover_width
= 4;
12607 SetLastError(0xdeadbeef);
12608 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
12609 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
12610 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError());
12611 if (!ret
) hover_height
= 4;
12612 trace("hover rect is %u x %d\n", hover_width
, hover_height
);
12614 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
12615 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12616 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
12620 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
12621 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
12622 50, 50, 200, 200, hwnd
,
12626 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
12631 tme
.dwFlags
= TME_QUERY
;
12632 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12633 tme
.dwHoverTime
= 0xdeadbeef;
12634 SetLastError(0xdeadbeef);
12635 ret
= pTrackMouseEvent(&tme
);
12636 ok(!ret
, "TrackMouseEvent should fail\n");
12637 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
12638 "not expected error %u\n", GetLastError());
12640 tme
.cbSize
= sizeof(tme
);
12641 tme
.dwFlags
= TME_HOVER
;
12642 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12643 tme
.dwHoverTime
= 0xdeadbeef;
12644 SetLastError(0xdeadbeef);
12645 ret
= pTrackMouseEvent(&tme
);
12646 ok(!ret
, "TrackMouseEvent should fail\n");
12647 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
12648 "not expected error %u\n", GetLastError());
12650 tme
.cbSize
= sizeof(tme
);
12651 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
12652 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12653 tme
.dwHoverTime
= 0xdeadbeef;
12654 SetLastError(0xdeadbeef);
12655 ret
= pTrackMouseEvent(&tme
);
12656 ok(!ret
, "TrackMouseEvent should fail\n");
12657 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
12658 "not expected error %u\n", GetLastError());
12660 GetWindowRect(hwnd
, &rc_parent
);
12661 GetWindowRect(hchild
, &rc_child
);
12662 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
12664 /* Process messages so that the system updates its internal current
12665 * window and hittest, otherwise TrackMouseEvent calls don't have any
12671 track_query(0, NULL
, 0);
12672 track_hover(hchild
, 0);
12673 track_query(0, NULL
, 0);
12678 track_hover(hwnd
, 0);
12679 tme
.cbSize
= sizeof(tme
);
12680 tme
.dwFlags
= TME_QUERY
;
12681 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12682 tme
.dwHoverTime
= 0xdeadbeef;
12683 SetLastError(0xdeadbeef);
12684 ret
= pTrackMouseEvent(&tme
);
12685 ok(ret
, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());
12686 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %u\n", tme
.cbSize
);
12689 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
12690 DestroyWindow( hwnd
);
12693 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme
.dwFlags
);
12694 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
12695 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %u, expected %u\n",
12696 tme
.dwHoverTime
, default_hover_time
);
12698 pump_msg_loop_timeout(default_hover_time
, FALSE
);
12699 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12701 track_query(0, NULL
, 0);
12703 track_hover(hwnd
, HOVER_DEFAULT
);
12704 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12706 Sleep(default_hover_time
/ 2);
12707 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12708 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12710 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12712 pump_msg_loop_timeout(default_hover_time
, FALSE
);
12713 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12715 track_query(0, NULL
, 0);
12717 track_hover(hwnd
, HOVER_DEFAULT
);
12718 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12720 pump_msg_loop_timeout(default_hover_time
, TRUE
);
12721 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12723 track_query(0, NULL
, 0);
12725 track_hover(hwnd
, HOVER_DEFAULT
);
12726 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12727 track_hover_cancel(hwnd
);
12729 DestroyWindow(hwnd
);
12733 #undef track_hover_cancel
12737 static const struct message WmSetWindowRgn
[] = {
12738 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12739 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12740 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
12741 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12742 { WM_ERASEBKGND
, sent
|optional
},
12743 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12744 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12748 static const struct message WmSetWindowRgn_no_redraw
[] = {
12749 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
12750 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12751 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
12752 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12756 static const struct message WmSetWindowRgn_clear
[] = {
12757 { WM_WINDOWPOSCHANGING
, sent
/*|wparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ },
12758 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12759 { WM_NCPAINT
, sent
|optional
},
12760 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12761 { WM_ERASEBKGND
, sent
|optional
}, /* FIXME: remove optional once Wine is fixed */
12762 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12763 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
12764 { WM_NCPAINT
, sent
|optional
},
12765 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12766 { WM_ERASEBKGND
, sent
|optional
},
12767 { WM_WINDOWPOSCHANGING
, sent
|optional
},
12768 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
12769 { WM_NCPAINT
, sent
|optional
},
12770 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12771 { WM_ERASEBKGND
, sent
|optional
},
12772 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12773 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
12774 { WM_NCPAINT
, sent
|optional
},
12775 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12776 { WM_ERASEBKGND
, sent
|optional
},
12777 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12778 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12782 static void test_SetWindowRgn(void)
12785 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
12786 100, 100, 200, 200, 0, 0, 0, NULL
);
12787 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
12789 ShowWindow( hwnd
, SW_SHOW
);
12790 UpdateWindow( hwnd
);
12794 trace("testing SetWindowRgn\n");
12795 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
12796 SetWindowRgn( hwnd
, hrgn
, TRUE
);
12797 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
12799 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
12800 SetWindowRgn( hwnd
, hrgn
, FALSE
);
12801 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
12803 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
12804 SetWindowRgn( hwnd
, hrgn
, TRUE
);
12805 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
12807 SetWindowRgn( hwnd
, 0, TRUE
);
12808 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
12810 DestroyWindow( hwnd
);
12813 /*************************** ShowWindow() test ******************************/
12814 static const struct message WmShowNormal
[] = {
12815 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12816 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12817 { HCBT_ACTIVATE
, hook
},
12818 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12819 { HCBT_SETFOCUS
, hook
},
12820 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12823 static const struct message WmShow
[] = {
12824 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12825 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12826 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12827 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12828 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12829 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12832 static const struct message WmShowNoActivate_1
[] = {
12833 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
12834 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12835 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12836 { WM_MOVE
, sent
|defwinproc
|optional
},
12837 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12840 static const struct message WmShowNoActivate_2
[] = {
12841 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
12842 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12843 { HCBT_ACTIVATE
, hook
|optional
},
12844 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12845 { HCBT_SETFOCUS
, hook
|optional
},
12846 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12847 { WM_MOVE
, sent
|defwinproc
},
12848 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12849 { HCBT_SETFOCUS
, hook
|optional
},
12850 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
12851 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12852 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12853 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
12856 static const struct message WmShowNA_1
[] = {
12857 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12858 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
12859 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12862 static const struct message WmShowNA_2
[] = {
12863 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12864 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
12865 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12868 static const struct message WmRestore_1
[] = {
12869 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
12870 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12871 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12872 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12873 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12874 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12875 { WM_MOVE
, sent
|defwinproc
},
12876 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12877 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
12880 static const struct message WmRestore_2
[] = {
12881 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12882 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12883 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12884 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12885 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12886 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12889 static const struct message WmRestore_3
[] = {
12890 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
12891 { WM_GETMINMAXINFO
, sent
},
12892 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12893 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
12894 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12895 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
12896 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12897 { WM_MOVE
, sent
|defwinproc
},
12898 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12899 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
12902 static const struct message WmRestore_4
[] = {
12903 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
12904 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12905 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12906 { WM_MOVE
, sent
|defwinproc
|optional
},
12907 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
12910 static const struct message WmRestore_5
[] = {
12911 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
12912 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12913 { HCBT_ACTIVATE
, hook
|optional
},
12914 { HCBT_SETFOCUS
, hook
|optional
},
12915 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12916 { WM_MOVE
, sent
|defwinproc
|optional
},
12917 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
12920 static const struct message WmHide_1
[] = {
12921 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12922 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
12923 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
12924 { HCBT_ACTIVATE
, hook
|optional
},
12925 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
12928 static const struct message WmHide_2
[] = {
12929 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12930 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
12931 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
12932 { HCBT_ACTIVATE
, hook
|optional
},
12935 static const struct message WmHide_3
[] = {
12936 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12937 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12938 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12939 { HCBT_SETFOCUS
, hook
|optional
},
12940 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12943 static const struct message WmShowMinimized_1
[] = {
12944 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
12945 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12946 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12947 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12948 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12949 { WM_MOVE
, sent
|defwinproc
},
12950 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12953 static const struct message WmMinimize_1
[] = {
12954 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12955 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12956 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12957 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12958 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12959 { WM_MOVE
, sent
|defwinproc
},
12960 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12963 static const struct message WmMinimize_2
[] = {
12964 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12965 { HCBT_SETFOCUS
, hook
|optional
},
12966 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12967 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12968 { WM_MOVE
, sent
|defwinproc
},
12969 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12972 static const struct message WmMinimize_3
[] = {
12973 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12974 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12975 { HCBT_ACTIVATE
, hook
|optional
},
12976 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12977 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12978 { WM_MOVE
, sent
|defwinproc
},
12979 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12982 static const struct message WmShowMinNoActivate
[] = {
12983 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
12984 { WM_WINDOWPOSCHANGING
, sent
},
12985 { WM_WINDOWPOSCHANGED
, sent
},
12986 { WM_MOVE
, sent
|defwinproc
|optional
},
12987 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
12990 static const struct message WmMinMax_1
[] = {
12991 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
12994 static const struct message WmMinMax_2
[] = {
12995 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12996 { WM_GETMINMAXINFO
, sent
|optional
},
12997 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
12998 { HCBT_ACTIVATE
, hook
|optional
},
12999 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13000 { HCBT_SETFOCUS
, hook
|optional
},
13001 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13002 { WM_MOVE
, sent
|defwinproc
|optional
},
13003 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
13004 { HCBT_SETFOCUS
, hook
|optional
},
13007 static const struct message WmMinMax_3
[] = {
13008 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
13009 { HCBT_SETFOCUS
, hook
|optional
},
13010 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13011 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13012 { WM_MOVE
, sent
|defwinproc
|optional
},
13013 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
13016 static const struct message WmMinMax_4
[] = {
13017 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
13020 static const struct message WmShowMaximized_1
[] = {
13021 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
13022 { WM_GETMINMAXINFO
, sent
},
13023 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13024 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
13025 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
13026 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
13027 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13028 { WM_MOVE
, sent
|defwinproc
},
13029 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
13030 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
13033 static const struct message WmShowMaximized_2
[] = {
13034 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
13035 { WM_GETMINMAXINFO
, sent
},
13036 { WM_WINDOWPOSCHANGING
, sent
|optional
},
13037 { HCBT_ACTIVATE
, hook
|optional
},
13038 { WM_WINDOWPOSCHANGED
, sent
|optional
},
13039 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
13040 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
13041 { WM_WINDOWPOSCHANGING
, sent
|optional
},
13042 { HCBT_SETFOCUS
, hook
|optional
},
13043 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
13044 { WM_MOVE
, sent
|defwinproc
},
13045 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
13046 { HCBT_SETFOCUS
, hook
|optional
},
13049 static const struct message WmShowMaximized_3
[] = {
13050 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
13051 { WM_GETMINMAXINFO
, sent
|optional
},
13052 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13053 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
13054 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
13055 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
13056 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
13057 { WM_MOVE
, sent
|defwinproc
|optional
},
13058 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
13062 static void test_ShowWindow(void)
13064 /* ShowWindow commands in random order */
13065 static const struct
13067 INT cmd
; /* ShowWindow command */
13068 LPARAM ret
; /* ShowWindow return value */
13069 DWORD style
; /* window style after the command */
13070 const struct message
*msg
; /* message sequence the command produces */
13071 INT wp_cmd
, wp_flags
; /* window placement after the command */
13072 POINT wp_min
, wp_max
; /* window placement after the command */
13073 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
13076 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
13077 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
13078 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13079 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
13080 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
13081 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
13082 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13083 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
13084 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
13085 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13086 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
13087 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13088 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
13089 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13090 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
13091 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13092 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
13093 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13094 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
13095 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13096 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
13097 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13098 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
13099 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13100 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
13101 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13102 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13103 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13104 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
13105 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13106 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13107 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13108 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
13109 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13110 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13111 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13112 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
13113 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13114 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
13115 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13116 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13117 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13118 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
13119 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
13120 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
13121 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13122 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13123 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13124 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
13125 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13126 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
13127 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13128 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
13129 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13130 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13131 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13132 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
13133 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13134 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
13135 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13136 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13137 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13138 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
13139 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13140 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13141 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13142 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
13143 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13144 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
13145 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13146 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13147 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13148 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
13149 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13150 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13151 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13152 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13153 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13154 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
13155 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13156 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
13157 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13158 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
13159 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13160 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
13161 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13162 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
13163 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13164 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
13165 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13166 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
13167 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13168 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
13169 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13170 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
13171 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13172 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
13173 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13174 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
13175 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13176 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
13177 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13178 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
13179 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13180 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13181 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13182 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
13183 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13184 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13185 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13186 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
13187 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13188 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13189 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
13195 WINDOWPLACEMENT wp
;
13196 RECT win_rc
, work_rc
= {0, 0, 0, 0};
13198 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
13199 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
13204 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
13205 ok(style
== 0, "expected style 0, got %08x\n", style
);
13210 if (pGetMonitorInfoA
&& pMonitorFromPoint
)
13216 SetLastError(0xdeadbeef);
13217 hmon
= pMonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
13218 ok(hmon
!= 0, "MonitorFromPoint error %u\n", GetLastError());
13220 mi
.cbSize
= sizeof(mi
);
13221 SetLastError(0xdeadbeef);
13222 ret
= pGetMonitorInfoA(hmon
, &mi
);
13223 ok(ret
, "GetMonitorInfo error %u\n", GetLastError());
13224 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi
.rcMonitor
),
13225 wine_dbgstr_rect(&mi
.rcWork
));
13226 work_rc
= mi
.rcWork
;
13229 GetWindowRect(hwnd
, &win_rc
);
13230 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
13232 wp
.length
= sizeof(wp
);
13233 SetLastError(0xdeadbeaf);
13234 ret
= GetWindowPlacement(hwnd
, &wp
);
13235 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
13236 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
13237 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
13238 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
13239 "expected -1,-1 got %d,%d\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
13240 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
13241 "expected -1,-1 got %d,%d\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
13242 todo_wine_if (work_rc
.left
|| work_rc
.top
) /* FIXME: remove once Wine is fixed */
13243 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n", wine_dbgstr_rect(&win_rc
),
13244 wine_dbgstr_rect(&wp
.rcNormalPosition
));
13246 for (i
= 0; i
< sizeof(sw
)/sizeof(sw
[0]); i
++)
13248 static const char * const sw_cmd_name
[13] =
13250 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
13251 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
13252 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
13253 "SW_NORMALNA" /* 0xCC */
13256 INT idx
; /* index into the above array of names */
13258 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
13260 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
13261 trace("%d: sending %s, current window style %08x\n", i
+1, sw_cmd_name
[idx
], style
);
13262 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
13263 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %lu, got %lu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
13264 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
13265 ok(style
== sw
[i
].style
, "%d: expected style %08x, got %08x\n", i
+1, sw
[i
].style
, style
);
13267 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
13268 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
13270 wp
.length
= sizeof(wp
);
13271 SetLastError(0xdeadbeaf);
13272 ret
= GetWindowPlacement(hwnd
, &wp
);
13273 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
13274 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
13275 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
13277 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
13278 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
13279 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
13281 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
13282 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
13283 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
13287 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
13288 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
13291 todo_wine_if(wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
13292 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
13293 "expected %d,%d got %d,%d\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
13295 if (0) /* FIXME: Wine behaves completely different here */
13296 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n",
13297 wine_dbgstr_rect(&win_rc
), wine_dbgstr_rect(&wp
.rcNormalPosition
));
13299 DestroyWindow(hwnd
);
13303 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13305 struct recvd_message msg
;
13307 if (ignore_message( message
)) return 0;
13310 msg
.message
= message
;
13311 msg
.flags
= sent
|wparam
|lparam
;
13312 msg
.wParam
= wParam
;
13313 msg
.lParam
= lParam
;
13314 msg
.descr
= "dialog";
13317 /* calling DefDlgProc leads to a recursion under XP */
13321 case WM_INITDIALOG
:
13324 case WM_GETDLGCODE
:
13330 static WNDPROC orig_edit_proc
;
13331 static LRESULT WINAPI
dlg_creation_edit_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
13333 struct recvd_message msg
;
13335 if (ignore_message( message
)) return 0;
13338 msg
.message
= message
;
13339 msg
.flags
= sent
|wparam
|lparam
;
13342 msg
.descr
= "edit";
13345 return CallWindowProcW(orig_edit_proc
, hwnd
, message
, wp
, lp
);
13348 static INT_PTR WINAPI
test_dlg_proc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13350 struct recvd_message msg
;
13352 if (ignore_message( message
)) return 0;
13355 msg
.message
= message
;
13356 msg
.flags
= sent
|wparam
|lparam
|parent
;
13357 msg
.wParam
= wParam
;
13358 msg
.lParam
= lParam
;
13359 msg
.descr
= "dialog";
13362 if (message
== WM_INITDIALOG
)
13364 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
13365 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
13371 static INT_PTR WINAPI
test_dlg_proc3(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13373 ok( 0, "should not be called since DefDlgProc is not used\n" );
13377 static LRESULT WINAPI
test_dlg_proc4(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13379 struct recvd_message msg
;
13381 if (!ignore_message( message
))
13384 msg
.message
= message
;
13385 msg
.flags
= sent
|wparam
|lparam
|parent
;
13386 msg
.wParam
= wParam
;
13387 msg
.lParam
= lParam
;
13388 msg
.descr
= "dialog";
13391 if (message
== WM_INITDIALOG
)
13393 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
13394 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
13397 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
13400 static const struct message WmDefDlgSetFocus_1
[] = {
13401 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13402 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
13403 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
13404 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
13405 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
13406 { HCBT_SETFOCUS
, hook
},
13407 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
13408 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13409 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13410 { WM_SETFOCUS
, sent
|wparam
, 0 },
13411 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
13412 { WM_CTLCOLOREDIT
, sent
},
13413 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13414 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13415 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13416 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13417 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
13420 static const struct message WmDefDlgSetFocus_2
[] = {
13421 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13422 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
13423 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
13424 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
13425 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
13426 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13427 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
13428 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13431 /* Creation of a dialog */
13432 static const struct message WmCreateDialogParamSeq_0
[] = {
13433 { HCBT_CREATEWND
, hook
},
13434 { WM_NCCREATE
, sent
},
13435 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
13436 { WM_CREATE
, sent
},
13437 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13438 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
13440 { WM_SETFONT
, sent
},
13441 { WM_INITDIALOG
, sent
},
13442 { WM_CHANGEUISTATE
, sent
|optional
},
13445 /* Creation of a dialog */
13446 static const struct message WmCreateDialogParamSeq_1
[] = {
13447 { HCBT_CREATEWND
, hook
},
13448 { WM_NCCREATE
, sent
},
13449 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
13450 { WM_CREATE
, sent
},
13451 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13452 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
13454 { WM_SETFONT
, sent
},
13455 { WM_INITDIALOG
, sent
},
13456 { WM_GETDLGCODE
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
13457 { HCBT_SETFOCUS
, hook
},
13458 { HCBT_ACTIVATE
, hook
},
13459 { WM_QUERYNEWPALETTE
, sent
|optional
},
13460 { WM_PALETTEISCHANGING
, sent
|optional
},
13461 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13462 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13463 { WM_NCACTIVATE
, sent
},
13464 { WM_ACTIVATE
, sent
|wparam
, 1 },
13465 { WM_SETFOCUS
, sent
},
13466 { WM_CHANGEUISTATE
, sent
|optional
},
13469 /* Creation of a dialog */
13470 static const struct message WmCreateDialogParamSeq_2
[] = {
13471 { HCBT_CREATEWND
, hook
},
13472 { WM_NCCREATE
, sent
},
13473 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
13474 { WM_CREATE
, sent
},
13475 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13476 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
13478 { WM_CHANGEUISTATE
, sent
|optional
},
13482 static const struct message WmCreateDialogParamSeq_3
[] = {
13483 { HCBT_CREATEWND
, hook
},
13484 { WM_SETFONT
, sent
|parent
},
13485 { WM_INITDIALOG
, sent
|parent
},
13486 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13487 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
13488 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13489 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13490 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13491 { HCBT_ACTIVATE
, hook
},
13492 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
13493 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13494 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13495 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
13496 { WM_NCACTIVATE
, sent
|parent
},
13497 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
13498 { WM_SETFOCUS
, sent
},
13499 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
13500 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13501 { WM_USER
, sent
|parent
},
13502 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
13506 static const struct message WmCreateDialogParamSeq_4
[] = {
13507 { HCBT_CREATEWND
, hook
},
13508 { WM_NCCREATE
, sent
|parent
},
13509 { WM_NCCALCSIZE
, sent
|parent
|wparam
, 0 },
13510 { WM_CREATE
, sent
|parent
},
13511 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13512 { WM_SIZE
, sent
|parent
|wparam
, SIZE_RESTORED
},
13513 { WM_MOVE
, sent
|parent
},
13514 { WM_SETFONT
, sent
|parent
},
13515 { WM_INITDIALOG
, sent
|parent
},
13516 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13517 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
13518 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13519 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13520 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13521 { HCBT_ACTIVATE
, hook
},
13522 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
13523 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13524 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13525 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
13526 { WM_NCACTIVATE
, sent
|parent
},
13527 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
13528 { HCBT_SETFOCUS
, hook
},
13529 { WM_SETFOCUS
, sent
|parent
},
13530 { WM_KILLFOCUS
, sent
|parent
},
13531 { WM_SETFOCUS
, sent
},
13532 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
13533 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13534 { WM_USER
, sent
|parent
},
13535 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
13536 { WM_UPDATEUISTATE
, sent
|parent
|optional
},
13537 { WM_UPDATEUISTATE
, sent
|optional
},
13541 static void test_dialog_messages(void)
13544 HWND hdlg
, hedit1
, hedit2
, hfocus
, parent
, child
, child2
;
13547 #define set_selection(hctl, start, end) \
13548 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
13549 ok(ret == 1, "EM_SETSEL returned %ld\n", ret);
13551 #define check_selection(hctl, start, end) \
13552 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
13553 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
13557 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
13558 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
13559 0, 0, 100, 100, 0, 0, 0, NULL
);
13560 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
13562 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
13563 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
13564 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
13565 ok(hedit1
!= 0, "Failed to create edit control\n");
13566 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
13567 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
13568 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
13569 ok(hedit2
!= 0, "Failed to create edit control\n");
13571 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
13572 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
13574 hfocus
= GetFocus();
13575 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
13578 hfocus
= GetFocus();
13579 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
13581 check_selection(hedit1
, 0, 0);
13582 check_selection(hedit2
, 0, 0);
13584 set_selection(hedit2
, 0, -1);
13585 check_selection(hedit2
, 0, 3);
13588 hfocus
= GetFocus();
13589 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
13592 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
13593 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
13594 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
13596 hfocus
= GetFocus();
13597 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
13599 check_selection(hedit1
, 0, 5);
13600 check_selection(hedit2
, 0, 3);
13603 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
13604 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
13605 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
13607 hfocus
= GetFocus();
13608 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
13610 check_selection(hedit1
, 0, 5);
13611 check_selection(hedit2
, 0, 3);
13613 EndDialog(hdlg
, 0);
13614 DestroyWindow(hedit1
);
13615 DestroyWindow(hedit2
);
13616 DestroyWindow(hdlg
);
13619 #undef set_selection
13620 #undef check_selection
13622 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
13623 cls
.lpszClassName
= "MyDialogClass";
13624 cls
.hInstance
= GetModuleHandleA(NULL
);
13625 /* need a cast since a dlgproc is used as a wndproc */
13626 cls
.lpfnWndProc
= test_dlg_proc
;
13627 if (!RegisterClassA(&cls
)) assert(0);
13631 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
13632 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13633 ok_sequence(WmCreateDialogParamSeq_0
, "CreateDialogParam_0", FALSE
);
13634 hfocus
= GetFocus();
13635 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
13636 EndDialog(hdlg
, 0);
13637 DestroyWindow(hdlg
);
13642 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 1);
13643 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13644 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
13645 hfocus
= GetFocus();
13646 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
13647 EndDialog(hdlg
, 0);
13648 DestroyWindow(hdlg
);
13651 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
13652 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13653 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
13654 EndDialog(hdlg
, 0);
13655 DestroyWindow(hdlg
);
13658 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2
, 0);
13659 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13660 ok_sequence(WmCreateDialogParamSeq_3
, "CreateDialogParam_3", TRUE
);
13661 EndDialog(hdlg
, 0);
13662 DestroyWindow(hdlg
);
13665 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
13666 cls
.lpfnWndProc
= test_dlg_proc4
;
13667 ok( RegisterClassA(&cls
), "failed to register class again\n" );
13668 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3
, 0);
13669 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13670 ok_sequence(WmCreateDialogParamSeq_4
, "CreateDialogParam_4", TRUE
);
13671 EndDialog(hdlg
, 0);
13672 DestroyWindow(hdlg
);
13675 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
13677 parent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13678 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13679 100, 100, 200, 200, 0, 0, 0, NULL
);
13680 ok (parent
!= 0, "Failed to create parent window\n");
13682 /* This child has no parent set. We will later call SetParent on it,
13683 * so that it will have a parent set, but no WS_CHILD style. */
13684 child
= CreateWindowExA(0, "TestWindowClass", "Test child",
13685 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13686 100, 100, 200, 200, 0, 0, 0, NULL
);
13687 ok (child
!= 0, "Failed to create child window\n");
13689 /* This is a regular child window. When used as an owner, the other
13690 * child window will be used. */
13691 child2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2",
13692 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CHILD
,
13693 100, 100, 200, 200, child
, 0, 0, NULL
);
13694 ok (child2
!= 0, "Failed to create child window\n");
13696 SetParent(child
, parent
);
13700 DialogBoxA( 0, "TEST_DIALOG", child2
, TestModalDlgProc2
);
13701 ok_sequence(WmModalDialogSeq_2
, "ModalDialog2", TRUE
);
13703 DestroyWindow(child2
);
13704 DestroyWindow(child
);
13705 DestroyWindow(parent
);
13709 static void test_enddialog_seq(HWND dialog
, HWND owner
)
13711 const struct message seq
[] = {
13712 { WM_ENABLE
, sent
},
13713 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13714 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
13715 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13716 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13717 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */
13718 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13719 { WM_QUERYNEWPALETTE
, sent
|optional
},
13720 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
13721 { WM_GETTEXT
, sent
|optional
|defwinproc
},
13722 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
13723 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
13724 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
13725 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, (WPARAM
)dialog
},
13730 EndDialog(dialog
, 0);
13731 ok_sequence(seq
, "EndDialog", FALSE
);
13734 static void test_enddialog_seq2(HWND dialog
, HWND owner
)
13736 const struct message seq
[] = {
13737 { WM_ENABLE
, parent
|sent
},
13738 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13739 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
13740 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13741 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13742 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13743 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13744 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
13745 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
13746 { WM_SETFOCUS
, sent
|parent
|defwinproc
|wparam
, (WPARAM
)dialog
},
13751 EndDialog(dialog
, 0);
13752 ok_sequence(seq
, "EndDialog2", FALSE
);
13755 static void test_EndDialog(void)
13757 HWND hparent
, hother
, hactive
, hdlg
, hchild
;
13760 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13761 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
13762 100, 100, 200, 200, 0, 0, 0, NULL
);
13763 ok (hparent
!= 0, "Failed to create parent window\n");
13765 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
13766 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13767 200, 100, 200, 200, 0, 0, 0, NULL
);
13768 ok (hother
!= 0, "Failed to create parent window\n");
13770 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
13771 cls
.lpszClassName
= "MyDialogClass";
13772 cls
.hInstance
= GetModuleHandleA(NULL
);
13773 cls
.lpfnWndProc
= test_dlg_proc
;
13774 if (!RegisterClassA(&cls
)) assert(0);
13777 SetForegroundWindow(hother
);
13778 hactive
= GetForegroundWindow();
13779 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
13781 /* create a dialog where the parent is disabled, this parent should be
13782 * enabled and receive focus when dialog exits */
13783 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
13784 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13785 SetForegroundWindow(hdlg
);
13786 hactive
= GetForegroundWindow();
13787 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
13788 EndDialog(hdlg
, 0);
13789 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
13790 hactive
= GetForegroundWindow();
13791 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
13792 DestroyWindow(hdlg
);
13795 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */
13796 EnableWindow(hparent
, FALSE
);
13797 hdlg
= CreateWindowExA(0, "TestDialogClass", NULL
,
13798 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
13799 0, 0, 100, 100, hparent
, 0, 0, NULL
);
13800 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13802 SetForegroundWindow(hother
);
13804 hactive
= GetForegroundWindow();
13805 ok(hactive
== hother
, "Wrong foreground (%p != %p)\n", hactive
, hother
);
13806 hactive
= GetActiveWindow();
13807 ok(hactive
== hother
, "Wrong active window (%p != %p)\n", hactive
, hother
);
13808 EndDialog(hdlg
, 0);
13809 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
13810 hactive
= GetForegroundWindow();
13811 ok(hother
== hactive
, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
13812 DestroyWindow(hdlg
);
13815 DestroyWindow( hparent
);
13817 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13818 WS_POPUP
| WS_VISIBLE
| WS_DISABLED
,
13819 100, 100, 200, 200, 0, 0, 0, NULL
);
13820 ok (hparent
!= 0, "Failed to create parent window\n");
13822 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
13823 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
13824 0, 0, 0, 0, 0, 0, 0, NULL
);
13825 ok (hchild
!= 0, "Failed to create child window\n");
13827 SetParent(hchild
, hparent
);
13830 SetForegroundWindow(hother
);
13831 hactive
= GetForegroundWindow();
13832 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
13834 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
13835 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13837 SetForegroundWindow(hdlg
);
13838 test_enddialog_seq(hdlg
, hchild
);
13840 hactive
= GetForegroundWindow();
13841 ok(hactive
== hchild
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
13843 DestroyWindow(hdlg
);
13845 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */
13846 SetWindowLongW(hchild
, GWL_STYLE
, GetWindowLongW(hchild
, GWL_STYLE
) | WS_CHILD
);
13848 SetForegroundWindow(hother
);
13849 hactive
= GetForegroundWindow();
13850 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
13852 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
13853 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13855 SetForegroundWindow(hdlg
);
13856 test_enddialog_seq2(hdlg
, hparent
);
13858 hactive
= GetForegroundWindow();
13859 ok(hactive
== hparent
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
13860 DestroyWindow(hdlg
);
13861 DestroyWindow(hchild
);
13862 DestroyWindow(hparent
);
13863 DestroyWindow(hother
);
13866 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
13869 static void test_nullCallback(void)
13873 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
13874 100, 100, 200, 200, 0, 0, 0, NULL
);
13875 ok (hwnd
!= 0, "Failed to create overlapped window\n");
13877 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
13879 DestroyWindow(hwnd
);
13882 /* SetActiveWindow( 0 ) hwnd visible */
13883 static const struct message SetActiveWindowSeq0
[] =
13885 { HCBT_ACTIVATE
, hook
|optional
},
13886 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13887 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13888 { WM_ACTIVATE
, sent
|wparam
, 0 },
13889 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13890 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13891 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13892 { WM_KILLFOCUS
, sent
|optional
},
13893 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13894 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13895 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
13896 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13897 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
13898 { HCBT_SETFOCUS
, hook
|optional
},
13899 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
13900 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
13901 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
13902 { WM_IME_SETCONTEXT
, sent
|optional
},
13903 { WM_IME_SETCONTEXT
, sent
|optional
},
13904 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13905 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13906 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
13907 { WM_GETTEXT
, sent
|optional
},
13910 /* SetActiveWindow( hwnd ) hwnd visible */
13911 static const struct message SetActiveWindowSeq1
[] =
13913 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13916 /* SetActiveWindow( popup ) hwnd visible, popup visible */
13917 static const struct message SetActiveWindowSeq2
[] =
13919 { HCBT_ACTIVATE
, hook
},
13920 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13921 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13922 { WM_ACTIVATE
, sent
|wparam
, 0 },
13923 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13924 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13925 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13926 { WM_NCPAINT
, sent
|optional
},
13927 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13928 { WM_ERASEBKGND
, sent
|optional
},
13929 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13930 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13931 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13932 { WM_ACTIVATE
, sent
|wparam
, 1 },
13933 { HCBT_SETFOCUS
, hook
},
13934 { WM_KILLFOCUS
, sent
|defwinproc
},
13935 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
13936 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13937 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13938 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13939 { WM_SETFOCUS
, sent
|defwinproc
},
13940 { WM_GETTEXT
, sent
|optional
},
13944 /* SetActiveWindow( hwnd ) hwnd not visible */
13945 static const struct message SetActiveWindowSeq3
[] =
13947 { HCBT_ACTIVATE
, hook
},
13948 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13949 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13950 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
13951 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13952 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13953 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13954 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13955 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13956 { WM_ACTIVATE
, sent
|wparam
, 1 },
13957 { HCBT_SETFOCUS
, hook
},
13958 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13959 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13960 { WM_SETFOCUS
, sent
|defwinproc
},
13963 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
13964 static const struct message SetActiveWindowSeq4
[] =
13966 { HCBT_ACTIVATE
, hook
},
13967 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13968 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13969 { WM_ACTIVATE
, sent
|wparam
, 0 },
13970 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13971 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
13972 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13973 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13974 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13975 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13976 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13977 { WM_ACTIVATE
, sent
|wparam
, 1 },
13978 { HCBT_SETFOCUS
, hook
},
13979 { WM_KILLFOCUS
, sent
|defwinproc
},
13980 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
13981 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13982 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13983 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13984 { WM_SETFOCUS
, sent
|defwinproc
},
13989 static void test_SetActiveWindow(void)
13991 HWND hwnd
, popup
, ret
;
13993 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
13994 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13995 100, 100, 200, 200, 0, 0, 0, NULL
);
13997 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
13998 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
13999 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
14001 ok(hwnd
!= 0, "Failed to create overlapped window\n");
14002 ok(popup
!= 0, "Failed to create popup window\n");
14003 SetForegroundWindow( popup
);
14006 trace("SetActiveWindow(0)\n");
14007 ret
= SetActiveWindow(0);
14008 ok( ret
== popup
, "Failed to SetActiveWindow(0)\n");
14009 ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
14012 trace("SetActiveWindow(hwnd), hwnd visible\n");
14013 ret
= SetActiveWindow(hwnd
);
14014 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
14017 trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
14018 ret
= SetActiveWindow(popup
);
14019 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
14020 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
14023 ShowWindow(hwnd
, SW_HIDE
);
14024 ShowWindow(popup
, SW_HIDE
);
14027 trace("SetActiveWindow(hwnd), hwnd not visible\n");
14028 ret
= SetActiveWindow(hwnd
);
14029 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
14030 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
14033 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
14034 ret
= SetActiveWindow(popup
);
14035 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
14036 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
14041 DestroyWindow(hwnd
);
14044 static const struct message SetForegroundWindowSeq
[] =
14046 { WM_NCACTIVATE
, sent
|wparam
, 0 },
14047 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14048 { WM_ACTIVATE
, sent
|wparam
, 0 },
14049 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
14050 { WM_KILLFOCUS
, sent
},
14051 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
14052 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
14056 static void test_SetForegroundWindow(void)
14060 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
14061 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14062 100, 100, 200, 200, 0, 0, 0, NULL
);
14063 ok (hwnd
!= 0, "Failed to create overlapped window\n");
14064 SetForegroundWindow( hwnd
);
14067 trace("SetForegroundWindow( 0 )\n");
14068 SetForegroundWindow( 0 );
14069 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
14070 trace("SetForegroundWindow( GetDesktopWindow() )\n");
14071 SetForegroundWindow( GetDesktopWindow() );
14072 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
14073 "foreground top level window", FALSE
);
14076 DestroyWindow(hwnd
);
14079 static DWORD
get_input_codepage( void )
14083 HKL hkl
= GetKeyboardLayout( 0 );
14085 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
,
14086 (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
14087 if (!ret
) cp
= CP_ACP
;
14091 static void test_dbcs_wm_char(void)
14094 WCHAR wch
, bad_wch
;
14102 struct message wmCharSeq
[2];
14104 DWORD cp
= get_input_codepage();
14106 if (!pGetCPInfoExA
)
14108 win_skip("GetCPInfoExA is not available\n");
14112 pGetCPInfoExA( cp
, 0, &cpinfo
);
14113 if (cpinfo
.MaxCharSize
!= 2)
14115 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
14119 dbch
[0] = dbch
[1] = 0;
14121 bad_wch
= cpinfo
.UnicodeDefaultChar
;
14122 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
14123 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
14124 for (k
= 128; k
<= 255; k
++)
14130 if (MultiByteToWideChar( cp
, 0, str
, 2, wstr
, 2 ) == 1 &&
14131 WideCharToMultiByte( cp
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
14132 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
14133 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
14144 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
14147 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
14148 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
14150 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
14151 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
14152 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
14153 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
14154 ok (hwnd
!= 0, "Failed to create overlapped window\n");
14155 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
14158 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
14159 wmCharSeq
[0].message
= WM_CHAR
;
14160 wmCharSeq
[0].flags
= sent
|wparam
;
14161 wmCharSeq
[0].wParam
= wch
;
14163 /* posted message */
14164 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14165 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14166 ok( !ret
, "got message %x\n", msg
.message
);
14167 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14168 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14169 ok( ret
, "no message\n" );
14170 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14171 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
14172 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14173 ok( !ret
, "got message %x\n", msg
.message
);
14175 /* posted thread message */
14176 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
14177 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14178 ok( !ret
, "got message %x\n", msg
.message
);
14179 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14180 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14181 ok( ret
, "no message\n" );
14182 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14183 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
14184 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14185 ok( !ret
, "got message %x\n", msg
.message
);
14189 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14190 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14191 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14192 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14193 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14194 ok( !ret
, "got message %x\n", msg
.message
);
14196 /* sent message with timeout */
14198 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
14199 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14200 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
14201 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14202 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14203 ok( !ret
, "got message %x\n", msg
.message
);
14205 /* sent message with timeout and callback */
14207 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
14208 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14209 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
14210 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14211 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14212 ok( !ret
, "got message %x\n", msg
.message
);
14214 /* sent message with callback */
14216 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14217 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14218 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
14219 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14220 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14221 ok( !ret
, "got message %x\n", msg
.message
);
14223 /* direct window proc call */
14225 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
14226 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14227 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
14228 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14230 /* dispatch message */
14232 msg
.message
= WM_CHAR
;
14233 msg
.wParam
= dbch
[0];
14235 DispatchMessageA( &msg
);
14236 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14237 msg
.wParam
= dbch
[1];
14238 DispatchMessageA( &msg
);
14239 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14241 /* window handle is irrelevant */
14243 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
14244 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14245 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14246 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14247 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14248 ok( !ret
, "got message %x\n", msg
.message
);
14250 /* interleaved post and send */
14252 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
14253 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
14254 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14255 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14256 ok( !ret
, "got message %x\n", msg
.message
);
14257 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14258 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14259 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14260 ok( ret
, "no message\n" );
14261 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14262 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
14263 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14264 ok( !ret
, "got message %x\n", msg
.message
);
14265 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14266 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14267 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14268 ok( !ret
, "got message %x\n", msg
.message
);
14270 /* interleaved sent message and winproc */
14272 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14273 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
14274 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14275 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14276 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14277 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
14278 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14280 /* interleaved winproc and dispatch */
14282 msg
.message
= WM_CHAR
;
14283 msg
.wParam
= dbch
[0];
14285 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
14286 DispatchMessageA( &msg
);
14287 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14288 msg
.wParam
= dbch
[1];
14289 DispatchMessageA( &msg
);
14290 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14291 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
14292 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14294 /* interleaved sends */
14296 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14297 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
14298 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14299 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
14300 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14301 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14302 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14306 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
14307 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14308 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14309 ok( !ret
, "got message %x\n", msg
.message
);
14311 /* other char messages are not magic */
14312 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
14313 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14314 ok( ret
, "no message\n" );
14315 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
14316 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
14317 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14318 ok( !ret
, "got message %x\n", msg
.message
);
14319 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
14320 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14321 ok( ret
, "no message\n" );
14322 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
14323 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
14324 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14325 ok( !ret
, "got message %x\n", msg
.message
);
14327 /* test retrieving messages */
14329 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
14330 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14331 ok( ret
, "no message\n" );
14332 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14333 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14334 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14335 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14336 ok( ret
, "no message\n" );
14337 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14338 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14339 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14340 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14341 ok( !ret
, "got message %x\n", msg
.message
);
14343 /* message filters */
14344 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
14345 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14346 ok( ret
, "no message\n" );
14347 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14348 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14349 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14350 /* message id is filtered, hwnd is not */
14351 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
14352 ok( !ret
, "no message\n" );
14353 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
14354 ok( ret
, "no message\n" );
14355 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14356 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14357 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14358 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14359 ok( !ret
, "got message %x\n", msg
.message
);
14361 /* mixing GetMessage and PostMessage */
14362 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
14363 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
14364 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14365 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14366 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14367 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
14370 ok( time
- GetTickCount() <= 100, "bad time %x\n", msg
.time
);
14371 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14372 ok( ret
, "no message\n" );
14373 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14374 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14375 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14376 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
14377 ok( msg
.time
== time
, "bad time %x/%x\n", msg
.time
, time
);
14378 ok( msg
.pt
.x
== pt
.x
&& msg
.pt
.y
== pt
.y
, "bad point %u,%u/%u,%u\n", msg
.pt
.x
, msg
.pt
.y
, pt
.x
, pt
.y
);
14379 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14380 ok( !ret
, "got message %x\n", msg
.message
);
14382 /* without PM_REMOVE */
14383 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
14384 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14385 ok( ret
, "no message\n" );
14386 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14387 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14388 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14389 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14390 ok( ret
, "no message\n" );
14391 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14392 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14393 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14394 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14395 ok( ret
, "no message\n" );
14396 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14397 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14398 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14399 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14400 ok( ret
, "no message\n" );
14401 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14402 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14403 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14404 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14405 ok( !ret
, "got message %x\n", msg
.message
);
14407 DestroyWindow(hwnd
);
14408 DestroyWindow(hwnd2
);
14411 static void test_unicode_wm_char(void)
14415 struct message seq
[2];
14416 HKL hkl_orig
, hkl_greek
;
14418 LCID thread_locale
;
14420 hkl_orig
= GetKeyboardLayout( 0 );
14421 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
14424 skip( "Default codepage %d\n", cp
);
14428 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
14429 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
14431 skip( "Unable to load Greek keyboard layout\n" );
14435 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
14436 100, 100, 200, 200, 0, 0, 0, NULL
);
14439 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
14441 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
14443 if (!ignore_message( msg
.message
)) break;
14446 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14447 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14448 ok( msg
.wParam
== 0x3b1, "bad wparam %lx\n", msg
.wParam
);
14449 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
14451 DispatchMessageW( &msg
);
14453 memset( seq
, 0, sizeof(seq
) );
14454 seq
[0].message
= WM_CHAR
;
14455 seq
[0].flags
= sent
|wparam
;
14456 seq
[0].wParam
= 0x3b1;
14458 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
14462 /* greek alpha -> 'a' in cp1252 */
14463 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
14465 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
14466 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14467 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14468 ok( msg
.wParam
== 0x61, "bad wparam %lx\n", msg
.wParam
);
14469 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
14471 DispatchMessageA( &msg
);
14473 seq
[0].wParam
= 0x61;
14474 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
14476 thread_locale
= GetThreadLocale();
14477 ActivateKeyboardLayout( hkl_greek
, 0 );
14478 ok( GetThreadLocale() == thread_locale
, "locale changed from %08x to %08x\n",
14479 thread_locale
, GetThreadLocale() );
14483 /* greek alpha -> 0xe1 in cp1253 */
14484 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
14486 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
14487 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14488 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14489 ok( msg
.wParam
== 0xe1, "bad wparam %lx\n", msg
.wParam
);
14490 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
14492 DispatchMessageA( &msg
);
14494 seq
[0].wParam
= 0x3b1;
14495 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
14497 DestroyWindow( hwnd
);
14498 ActivateKeyboardLayout( hkl_orig
, 0 );
14499 UnloadKeyboardLayout( hkl_greek
);
14502 #define ID_LISTBOX 0x000f
14504 static const struct message wm_lb_setcursel_0
[] =
14506 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
14507 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14508 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
14509 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14510 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14513 static const struct message wm_lb_setcursel_1
[] =
14515 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
14516 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14517 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
14518 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14519 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
14520 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
14521 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
14524 static const struct message wm_lb_setcursel_2
[] =
14526 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
14527 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14528 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
14529 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14530 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
14531 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
14532 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
14535 static const struct message wm_lb_click_0
[] =
14537 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
14538 { HCBT_SETFOCUS
, hook
},
14539 { WM_KILLFOCUS
, sent
|parent
},
14540 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
14541 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
14542 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14543 { WM_SETFOCUS
, sent
|defwinproc
},
14545 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
14546 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
14547 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
14548 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
14549 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
14551 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
14552 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14553 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
14554 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14555 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
14556 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
14558 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14559 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14561 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
14562 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
14563 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
14564 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
14567 static const struct message wm_lb_deletestring
[] =
14569 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
14570 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
14571 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14572 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14575 static const struct message wm_lb_deletestring_reset
[] =
14577 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
14578 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
14579 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
14580 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14581 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14584 static const struct message wm_lb_addstring
[] =
14586 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
14587 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
14588 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
14591 static const struct message wm_lb_addstring_ownerdraw
[] =
14593 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
14594 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
14595 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
14596 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
14597 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
14598 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
14601 static const struct message wm_lb_addstring_sort_ownerdraw
[] =
14603 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
14604 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
14605 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
14606 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ee },
14607 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
14608 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
14609 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ef },
14610 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ee, 0xf30604ef },
14611 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
14615 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
14617 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
14619 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14621 static LONG defwndproc_counter
= 0;
14623 struct recvd_message msg
;
14625 /* do not log painting messages */
14626 if (message
!= WM_PAINT
&&
14627 message
!= WM_NCPAINT
&&
14628 message
!= WM_SYNCPAINT
&&
14629 message
!= WM_ERASEBKGND
&&
14630 message
!= WM_NCHITTEST
&&
14631 message
!= WM_GETTEXT
&&
14632 !ignore_message( message
))
14635 msg
.message
= message
;
14636 msg
.flags
= sent
|wparam
|lparam
;
14637 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
14639 if (message
== LB_ADDSTRING
)
14640 msg
.lParam
= lp
? hash_Ly((const char *)lp
) : 0;
14643 msg
.descr
= "listbox";
14647 defwndproc_counter
++;
14648 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
14649 defwndproc_counter
--;
14654 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
14655 int caret_index
, int top_index
, int line
)
14659 /* calling an orig proc helps to avoid unnecessary message logging */
14660 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
14661 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %ld\n", count
, ret
);
14662 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
14663 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %ld\n", cur_sel
, ret
);
14664 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
14665 ok_(__FILE__
, line
)(ret
== caret_index
||
14666 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
14667 "expected caret index %d, got %ld\n", caret_index
, ret
);
14668 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
14669 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %ld\n", top_index
, ret
);
14672 static void test_listbox_messages(void)
14674 HWND parent
, listbox
;
14677 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14678 100, 100, 200, 200, 0, 0, 0, NULL
);
14679 /* with LBS_HASSTRINGS */
14680 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
14681 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
14682 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
14683 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
14685 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
14689 log_all_parent_messages
++;
14691 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
14692 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14693 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
14694 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14695 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
14696 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14698 ok_sequence(wm_lb_addstring_ownerdraw
, "LB_ADDSTRING", FALSE
);
14699 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
14703 trace("selecting item 0\n");
14704 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
14705 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14706 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
14707 check_lb_state(listbox
, 3, 0, 0, 0);
14710 trace("selecting item 1\n");
14711 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
14712 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14713 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
14714 check_lb_state(listbox
, 3, 1, 1, 0);
14716 trace("selecting item 2\n");
14717 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
14718 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14719 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
14720 check_lb_state(listbox
, 3, 2, 2, 0);
14722 trace("clicking on item 0\n");
14723 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
14724 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
14725 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
14726 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
14727 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
14728 check_lb_state(listbox
, 3, 0, 0, 0);
14731 trace("deleting item 0\n");
14732 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14733 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14734 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
14735 check_lb_state(listbox
, 2, -1, 0, 0);
14738 trace("deleting item 0\n");
14739 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14740 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14741 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
14742 check_lb_state(listbox
, 1, -1, 0, 0);
14745 trace("deleting item 0\n");
14746 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14747 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14748 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
14749 check_lb_state(listbox
, 0, -1, 0, 0);
14752 trace("deleting item 0\n");
14753 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14754 ok(ret
== LB_ERR
, "expected LB_ERR, got %ld\n", ret
);
14755 check_lb_state(listbox
, 0, -1, 0, 0);
14758 log_all_parent_messages
--;
14760 DestroyWindow(listbox
);
14762 /* with LBS_SORT and without LBS_HASSTRINGS */
14763 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
14764 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_SORT
| WS_VISIBLE
,
14765 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
14766 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
14768 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
14772 log_all_parent_messages
++;
14774 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
14775 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14776 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
14777 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14778 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
14779 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14781 ok_sequence(wm_lb_addstring_sort_ownerdraw
, "LB_ADDSTRING", FALSE
);
14782 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
14784 log_all_parent_messages
--;
14786 DestroyWindow(listbox
);
14788 /* with LBS_HASSTRINGS */
14789 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
14790 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| WS_VISIBLE
,
14791 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
14792 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
14794 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
14798 log_all_parent_messages
++;
14800 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
14801 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14802 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
14803 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14804 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
14805 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14807 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
14808 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
14810 log_all_parent_messages
--;
14812 DestroyWindow(listbox
);
14814 /* with LBS_HASSTRINGS and LBS_SORT */
14815 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
14816 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| LBS_SORT
| WS_VISIBLE
,
14817 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
14818 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
14820 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
14824 log_all_parent_messages
++;
14826 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
14827 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14828 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
14829 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14830 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
14831 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14833 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
14834 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
14836 log_all_parent_messages
--;
14838 DestroyWindow(listbox
);
14839 DestroyWindow(parent
);
14842 /*************************** Menu test ******************************/
14843 static const struct message wm_popup_menu_1
[] =
14845 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14846 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14847 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
14848 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
14849 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
14850 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
14851 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14852 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14853 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
14854 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
14855 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
14856 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
14857 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
14858 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14859 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
14860 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
14861 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14862 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14863 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14864 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
14865 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14866 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14869 static const struct message wm_popup_menu_2
[] =
14871 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14872 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14873 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
14874 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
14875 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
14876 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
14877 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14878 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14879 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
14880 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
14881 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
14882 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
14883 { HCBT_CREATEWND
, hook
},
14884 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
14885 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
14886 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
14887 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14888 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
14889 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
14890 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
14891 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
14892 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
14893 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
14894 { HCBT_DESTROYWND
, hook
},
14895 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14896 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
14897 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14898 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14899 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14900 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
14901 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14902 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14905 static const struct message wm_popup_menu_3
[] =
14907 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14908 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14909 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
14910 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
14911 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
14912 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
14913 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14914 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14915 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
14916 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
14917 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
14918 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
14919 { HCBT_CREATEWND
, hook
},
14920 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
14921 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
14922 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
14923 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14924 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
14925 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
14926 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
14927 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
14928 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
14929 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
14930 { HCBT_DESTROYWND
, hook
},
14931 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14932 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
14933 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14934 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14935 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14936 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
14937 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14938 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14942 static const struct message wm_single_menu_item
[] =
14944 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14945 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14946 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
14947 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
14948 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
14949 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
14950 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14951 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14952 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
14953 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14954 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14955 { WM_MENUCOMMAND
, sent
},
14956 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
14957 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
14958 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
14959 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
14961 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
14962 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
14963 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
14964 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
14965 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
14969 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14971 if (message
== WM_ENTERIDLE
||
14972 message
== WM_INITMENU
||
14973 message
== WM_INITMENUPOPUP
||
14974 message
== WM_MENUSELECT
||
14975 message
== WM_PARENTNOTIFY
||
14976 message
== WM_ENTERMENULOOP
||
14977 message
== WM_EXITMENULOOP
||
14978 message
== WM_UNINITMENUPOPUP
||
14979 message
== WM_KEYDOWN
||
14980 message
== WM_KEYUP
||
14981 message
== WM_CHAR
||
14982 message
== WM_SYSKEYDOWN
||
14983 message
== WM_SYSKEYUP
||
14984 message
== WM_SYSCHAR
||
14985 message
== WM_COMMAND
||
14986 message
== WM_MENUCOMMAND
)
14988 struct recvd_message msg
;
14991 msg
.message
= message
;
14992 msg
.flags
= sent
|wparam
|lparam
;
14995 msg
.descr
= "parent_menu_proc";
14999 return DefWindowProcA(hwnd
, message
, wp
, lp
);
15002 static void set_menu_style(HMENU hmenu
, DWORD style
)
15007 mi
.cbSize
= sizeof(mi
);
15008 mi
.fMask
= MIM_STYLE
;
15009 mi
.dwStyle
= style
;
15010 SetLastError(0xdeadbeef);
15011 ret
= pSetMenuInfo(hmenu
, &mi
);
15012 ok(ret
, "SetMenuInfo error %u\n", GetLastError());
15015 static DWORD
get_menu_style(HMENU hmenu
)
15020 mi
.cbSize
= sizeof(mi
);
15021 mi
.fMask
= MIM_STYLE
;
15023 SetLastError(0xdeadbeef);
15024 ret
= pGetMenuInfo(hmenu
, &mi
);
15025 ok(ret
, "GetMenuInfo error %u\n", GetLastError());
15030 static void test_menu_messages(void)
15034 HMENU hmenu
, hmenu_popup
;
15038 if (!pGetMenuInfo
|| !pSetMenuInfo
)
15040 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n");
15044 cls
.lpfnWndProc
= parent_menu_proc
;
15045 cls
.cbClsExtra
= 0;
15046 cls
.cbWndExtra
= 0;
15047 cls
.hInstance
= GetModuleHandleA(0);
15049 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
15050 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
15051 cls
.lpszMenuName
= NULL
;
15052 cls
.lpszClassName
= "TestMenuClass";
15053 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
15054 if (!RegisterClassA(&cls
)) assert(0);
15056 SetLastError(0xdeadbeef);
15057 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15058 100, 100, 200, 200, 0, 0, 0, NULL
);
15059 ok(hwnd
!= 0, "LoadMenuA error %u\n", GetLastError());
15061 SetLastError(0xdeadbeef);
15062 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
15063 ok(hmenu
!= 0, "LoadMenuA error %u\n", GetLastError());
15065 SetMenu(hwnd
, hmenu
);
15066 SetForegroundWindow( hwnd
);
15069 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
15070 style
= get_menu_style(hmenu
);
15071 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
15073 hmenu_popup
= GetSubMenu(hmenu
, 0);
15074 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
15075 style
= get_menu_style(hmenu_popup
);
15076 ok(style
== 0, "expected 0, got %u\n", style
);
15078 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
15079 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
15080 style
= get_menu_style(hmenu_popup
);
15081 ok(style
== 0, "expected 0, got %u\n", style
);
15084 trace("testing a popup menu command\n");
15086 keybd_event(VK_MENU
, 0, 0, 0);
15087 keybd_event('E', 0, 0, 0);
15088 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
15089 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
15090 keybd_event(VK_RETURN
, 0, 0, 0);
15091 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
15092 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
15094 TranslateMessage(&msg
);
15095 DispatchMessageA(&msg
);
15097 if (!sequence_cnt
) /* we didn't get any message */
15099 skip( "queuing key events not supported\n" );
15102 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
15103 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
15105 win_skip( "menu tracking through VK_MENU not supported\n" );
15108 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
15110 /* Alt+F, Right, Enter */
15111 trace("testing submenu of a popup menu command\n");
15113 keybd_event(VK_MENU
, 0, 0, 0);
15114 keybd_event('F', 0, 0, 0);
15115 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
15116 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
15117 keybd_event(VK_RIGHT
, 0, 0, 0);
15118 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
15119 keybd_event(VK_RETURN
, 0, 0, 0);
15120 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
15121 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
15123 TranslateMessage(&msg
);
15124 DispatchMessageA(&msg
);
15126 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
15128 trace("testing single menu item command\n");
15130 keybd_event(VK_MENU
, 0, 0, 0);
15131 keybd_event('Q', 0, 0, 0);
15132 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
15133 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
15134 keybd_event(VK_ESCAPE
, 0, 0, 0);
15135 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
15136 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
15138 TranslateMessage(&msg
);
15139 DispatchMessageA(&msg
);
15141 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
15143 set_menu_style(hmenu
, 0);
15144 style
= get_menu_style(hmenu
);
15145 ok(style
== 0, "expected 0, got %u\n", style
);
15147 hmenu_popup
= GetSubMenu(hmenu
, 0);
15148 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
15149 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
15150 style
= get_menu_style(hmenu_popup
);
15151 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
15153 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
15154 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
15155 style
= get_menu_style(hmenu_popup
);
15156 ok(style
== 0, "expected 0, got %u\n", style
);
15158 /* Alt+F, Right, Enter */
15159 trace("testing submenu of a popup menu command\n");
15161 keybd_event(VK_MENU
, 0, 0, 0);
15162 keybd_event('F', 0, 0, 0);
15163 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
15164 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
15165 keybd_event(VK_RIGHT
, 0, 0, 0);
15166 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
15167 keybd_event(VK_RETURN
, 0, 0, 0);
15168 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
15169 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
15171 TranslateMessage(&msg
);
15172 DispatchMessageA(&msg
);
15174 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
15177 DestroyWindow(hwnd
);
15178 DestroyMenu(hmenu
);
15182 static void test_paintingloop(void)
15186 paint_loop_done
= FALSE
;
15187 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
15188 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
15189 100, 100, 100, 100, 0, 0, 0, NULL
);
15190 ok(hwnd
!= 0, "PaintLoop window error %u\n", GetLastError());
15191 ShowWindow(hwnd
,SW_NORMAL
);
15194 while (!paint_loop_done
)
15197 if (PeekMessageA(&msg
, 0, 0, 0, 1))
15199 TranslateMessage(&msg
);
15200 DispatchMessageA(&msg
);
15203 DestroyWindow(hwnd
);
15206 static const struct message NCRBUTTONDOWNSeq
[] =
15208 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
15209 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15210 { WM_CAPTURECHANGED
, sent
},
15211 { WM_CONTEXTMENU
, sent
, /*hwnd*/0, -1 },
15215 static const struct message NCXBUTTONUPSeq1
[] =
15217 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_BACKWARD
) },
15221 static const struct message NCXBUTTONUPSeq2
[] =
15223 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_FORWARD
) },
15227 struct rbuttonup_thread_data
15230 HANDLE wndproc_finished
;
15233 static DWORD CALLBACK
post_rbuttonup_msg( void *arg
)
15235 struct rbuttonup_thread_data
*data
= arg
;
15238 ret
= WaitForSingleObject( data
->wndproc_finished
, 500 );
15239 todo_wine
ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %x\n", ret
);
15240 if( ret
== WAIT_OBJECT_0
) return 0;
15242 PostMessageA( data
->hwnd
, WM_RBUTTONUP
, 0, 0 );
15246 static void test_defwinproc(void)
15250 BOOL gotwmquit
= FALSE
;
15255 struct rbuttonup_thread_data data
;
15259 hwnd
= CreateWindowExA(0, "TestWindowClass", "test_defwndproc",
15260 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0,0,500,100,0,0,0, NULL
);
15265 GetWindowTextA(hwnd
, buffA
, sizeof(buffA
)/sizeof(*buffA
));
15266 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
15268 /* Zero high word of the lParam */
15269 res
= DefWindowProcA(hwnd
, WM_SETTEXT
, 0, 0x1234);
15270 ok(res
== 0, "WM_SETTEXT was expected to fail, %ld\n", res
);
15272 GetWindowTextA(hwnd
, buffA
, sizeof(buffA
)/sizeof(*buffA
));
15273 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
15275 res
= DefWindowProcW(hwnd
, WM_SETTEXT
, 0, 0x1234);
15276 ok(res
== 0, "WM_SETTEXT was expected to fail, %ld\n", res
);
15278 GetWindowTextA(hwnd
, buffA
, sizeof(buffA
)/sizeof(*buffA
));
15279 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
15281 GetCursorPos(&pos
);
15282 GetWindowRect(hwnd
, &rect
);
15283 x
= (rect
.left
+rect
.right
) / 2;
15284 y
= rect
.top
+ GetSystemMetrics(SM_CYFRAME
) + 1;
15285 SetCursorPos(x
, y
);
15287 res
= DefWindowProcA( hwnd
, WM_NCHITTEST
, 0, MAKELPARAM(x
, y
));
15288 ok(res
== HTCAPTION
, "WM_NCHITTEST returned %ld\n", res
);
15290 mouse_event( MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0 );
15291 mouse_event( MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0 );
15295 mouse_event( MOUSEEVENTF_RIGHTUP
, 0, 0, 0, 0 );
15296 /* workaround for missing support for clicking on window frame */
15298 data
.wndproc_finished
= CreateEventA( NULL
, FALSE
, FALSE
, NULL
);
15299 thread
= CreateThread( NULL
, 0, post_rbuttonup_msg
, (void*)&data
, 0, NULL
);
15301 DefWindowProcA( hwnd
, WM_NCRBUTTONDOWN
, HTCAPTION
, MAKELPARAM(x
, y
));
15302 ok_sequence(NCRBUTTONDOWNSeq
, "WM_NCRBUTTONDOWN on caption", FALSE
);
15304 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, 0, MAKELPARAM(x
, y
));
15305 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15306 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP without button", FALSE
);
15308 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON1
), MAKELPARAM(x
, y
));
15309 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15310 ok_sequence(NCXBUTTONUPSeq1
, "WM_NCXBUTTONUP with XBUTTON1", FALSE
);
15312 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON2
), MAKELPARAM(x
, y
));
15313 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15314 ok_sequence(NCXBUTTONUPSeq2
, "WM_NCXBUTTONUP with XBUTTON2", FALSE
);
15316 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, 3), MAKELPARAM(x
, y
));
15317 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15318 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP with invalid button", FALSE
);
15320 SetEvent( data
.wndproc_finished
);
15321 WaitForSingleObject( thread
, 1000 );
15322 CloseHandle( data
.wndproc_finished
);
15323 CloseHandle( thread
);
15325 SetCursorPos(pos
.x
, pos
.y
);
15327 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
15328 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
15329 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
15330 DispatchMessageA( &msg
);
15332 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
15333 DestroyWindow( hwnd
);
15336 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
15337 static void clear_clipboard_(int line
, HWND hWnd
)
15340 succ
= OpenClipboard(hWnd
);
15341 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%u\n", GetLastError());
15342 succ
= EmptyClipboard();
15343 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%u\n", GetLastError());
15344 succ
= CloseClipboard();
15345 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%u\n", GetLastError());
15348 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
15349 static void expect_HWND_(int line
, HWND expected
, HWND got
)
15351 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
15354 static WNDPROC pOldViewerProc
;
15356 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15358 static BOOL recursion_guard
;
15360 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
15362 recursion_guard
= TRUE
;
15363 clear_clipboard(hWnd
);
15364 recursion_guard
= FALSE
;
15366 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
15369 static void test_clipboard_viewers(void)
15371 static struct message wm_change_cb_chain
[] =
15373 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
15376 static const struct message wm_clipboard_destroyed
[] =
15378 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15381 static struct message wm_clipboard_changed
[] =
15383 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15386 static struct message wm_clipboard_changed_and_owned
[] =
15388 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15389 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15393 HINSTANCE hInst
= GetModuleHandleA(NULL
);
15394 HWND hWnd1
, hWnd2
, hWnd3
;
15398 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
15399 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
15400 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
15401 GetDesktopWindow(), NULL
, hInst
, NULL
);
15402 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
15403 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
15404 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
15405 GetDesktopWindow(), NULL
, hInst
, NULL
);
15406 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
15407 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
15408 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
15409 GetDesktopWindow(), NULL
, hInst
, NULL
);
15410 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
15411 assert(hWnd1
&& hWnd2
&& hWnd3
);
15413 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */
15416 /* Test getting the clipboard viewer and setting the viewer to NULL. */
15417 hOrigViewer
= GetClipboardViewer();
15418 hRet
= SetClipboardViewer(NULL
);
15419 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
15420 expect_HWND(hOrigViewer
, hRet
);
15421 expect_HWND(NULL
, GetClipboardViewer());
15423 /* Test registering hWnd1 as a viewer. */
15424 hRet
= SetClipboardViewer(hWnd1
);
15425 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
15426 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
15427 expect_HWND(NULL
, hRet
);
15428 expect_HWND(hWnd1
, GetClipboardViewer());
15430 /* Test that changing the clipboard actually refreshes the registered viewer. */
15431 clear_clipboard(hWnd1
);
15432 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
15433 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
15435 /* Again, but with different owner. */
15436 clear_clipboard(hWnd2
);
15437 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
15438 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
15440 /* Test re-registering same window. */
15441 hRet
= SetClipboardViewer(hWnd1
);
15442 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
15443 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
15444 expect_HWND(hWnd1
, hRet
);
15445 expect_HWND(hWnd1
, GetClipboardViewer());
15447 /* Test ChangeClipboardChain. */
15448 ChangeClipboardChain(hWnd2
, hWnd3
);
15449 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
15450 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
15451 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
15452 expect_HWND(hWnd1
, GetClipboardViewer());
15454 ChangeClipboardChain(hWnd2
, NULL
);
15455 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
15456 wm_change_cb_chain
[0].lParam
= 0;
15457 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
15458 expect_HWND(hWnd1
, GetClipboardViewer());
15460 ChangeClipboardChain(NULL
, hWnd2
);
15461 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", FALSE
);
15462 expect_HWND(hWnd1
, GetClipboardViewer());
15464 /* Actually change clipboard viewer with ChangeClipboardChain. */
15465 ChangeClipboardChain(hWnd1
, hWnd2
);
15466 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
15467 expect_HWND(hWnd2
, GetClipboardViewer());
15469 /* Test that no refresh messages are sent when viewer has unregistered. */
15470 clear_clipboard(hWnd2
);
15471 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
15473 /* Register hWnd1 again. */
15474 ChangeClipboardChain(hWnd2
, hWnd1
);
15475 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
15476 expect_HWND(hWnd1
, GetClipboardViewer());
15478 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
15479 * changes the clipboard. When this happens, the system shouldn't send
15480 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
15482 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
15483 clear_clipboard(hWnd2
);
15484 /* The clipboard owner is changed in recursive_viewer_proc: */
15485 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
15486 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
15488 /* Test unregistering. */
15489 ChangeClipboardChain(hWnd1
, NULL
);
15490 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
15491 expect_HWND(NULL
, GetClipboardViewer());
15493 clear_clipboard(hWnd1
);
15494 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
15496 DestroyWindow(hWnd1
);
15497 DestroyWindow(hWnd2
);
15498 DestroyWindow(hWnd3
);
15499 SetClipboardViewer(hOrigViewer
);
15502 static void test_PostMessage(void)
15504 static const struct
15510 { HWND_TOP
/* 0 */, TRUE
},
15511 { HWND_BROADCAST
, TRUE
},
15512 { HWND_BOTTOM
, TRUE
},
15513 { HWND_TOPMOST
, TRUE
},
15514 { HWND_NOTOPMOST
, FALSE
},
15515 { HWND_MESSAGE
, FALSE
},
15516 { (HWND
)0xdeadbeef, FALSE
}
15522 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
15524 SetLastError(0xdeadbeef);
15525 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
15526 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
15528 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
15535 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
15536 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
15538 for (i
= 0; i
< sizeof(data
)/sizeof(data
[0]); i
++)
15540 memset(&msg
, 0xab, sizeof(msg
));
15541 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
15542 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
15546 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
15547 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
15548 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
15549 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
15551 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
15552 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
15553 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
15554 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
15558 DestroyWindow(hwnd
);
15562 static LPARAM g_broadcast_lparam
;
15563 static LRESULT WINAPI
broadcast_test_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15565 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
15567 if (wParam
== 0xbaadbeef)
15568 g_broadcast_lparam
= wParam
;
15570 g_broadcast_lparam
= 0;
15572 return CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
15575 static void test_broadcast(void)
15577 static const UINT messages
[] =
15583 0xc000, /* lowest possible atom returned by RegisterWindowMessage */
15590 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0, 0, 0, 0, 0, 0, 0, NULL
);
15591 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
15593 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_proc
);
15594 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
15596 for (i
= 0; i
< sizeof(messages
)/sizeof(messages
[0]); i
++)
15602 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
15605 /* post, broadcast */
15606 ret
= PostMessageA(HWND_BROADCAST
, messages
[i
], 0, 0);
15607 ok(ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
15609 memset(&msg
, 0xab, sizeof(msg
));
15610 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
15611 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15613 ok(ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
15614 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
15618 ok(!ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
15621 /* post, topmost */
15622 ret
= PostMessageA(HWND_TOPMOST
, messages
[i
], 0, 0);
15623 ok(ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
15625 memset(&msg
, 0xab, sizeof(msg
));
15626 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
15627 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15629 ok(ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
15630 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
15634 ok(!ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
15637 /* send, broadcast */
15638 g_broadcast_lparam
= 0xdead;
15639 ret
= SendMessageTimeoutA(HWND_BROADCAST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
15640 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
15641 win_skip("broadcasting test %d, timeout\n", i
);
15644 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15646 ok(g_broadcast_lparam
== 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15647 g_broadcast_lparam
, GetLastError());
15651 ok(g_broadcast_lparam
== 0xdead, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15652 g_broadcast_lparam
, GetLastError());
15656 /* send, topmost */
15657 g_broadcast_lparam
= 0xdead;
15658 ret
= SendMessageTimeoutA(HWND_TOPMOST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
15659 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
15660 win_skip("broadcasting test %d, timeout\n", i
);
15663 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15665 ok(g_broadcast_lparam
== 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15666 g_broadcast_lparam
, GetLastError());
15670 ok(g_broadcast_lparam
== 0xdead, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15671 g_broadcast_lparam
, GetLastError());
15676 DestroyWindow(hwnd
);
15679 static const struct
15683 } wait_idle_expect
[] =
15685 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15686 { WAIT_TIMEOUT
, 0, FALSE
},
15687 { WAIT_TIMEOUT
, 0, FALSE
},
15688 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15689 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15690 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
15691 { WAIT_TIMEOUT
, 0, FALSE
},
15692 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15695 /* 10 */ { 0, 0, FALSE
},
15697 { 0, WAIT_TIMEOUT
, FALSE
},
15700 /* 15 */ { 0, 0, FALSE
},
15701 { WAIT_TIMEOUT
, 0, FALSE
},
15702 { WAIT_TIMEOUT
, 0, FALSE
},
15703 { WAIT_TIMEOUT
, 0, FALSE
},
15704 { WAIT_TIMEOUT
, 0, FALSE
},
15705 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
15708 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
15712 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15714 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
15718 static void do_wait_idle_child( int arg
)
15725 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
15726 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
15728 memset( &cls
, 0, sizeof(cls
) );
15729 cls
.lpfnWndProc
= DefWindowProcA
;
15730 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
15731 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
15732 cls
.lpszClassName
= "TestClass";
15733 RegisterClassA( &cls
);
15735 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
15737 ok( start_event
!= 0, "failed to create start event, error %u\n", GetLastError() );
15738 ok( end_event
!= 0, "failed to create end event, error %u\n", GetLastError() );
15743 SetEvent( start_event
);
15746 SetEvent( start_event
);
15748 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
15751 SetEvent( start_event
);
15753 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15754 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
15755 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
15758 SetEvent( start_event
);
15760 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
15763 SetEvent( start_event
);
15765 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15766 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
15769 SetEvent( start_event
);
15771 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15772 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
15775 SetEvent( start_event
);
15777 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15778 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
15780 GetMessageA( &msg
, 0, 0, 0 );
15781 DispatchMessageA( &msg
);
15785 SetEvent( start_event
);
15787 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15788 SetTimer( hwnd
, 3, 1, NULL
);
15790 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
15793 SetEvent( start_event
);
15795 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15796 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
15799 SetEvent( start_event
);
15801 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15802 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
15803 for (;;) GetMessageA( &msg
, 0, 0, 0 );
15806 SetEvent( start_event
);
15808 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15809 SetTimer( hwnd
, 3, 1, NULL
);
15811 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
15814 SetEvent( start_event
);
15816 return; /* exiting the process makes WaitForInputIdle return success too */
15818 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15820 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
15821 SetEvent( start_event
);
15824 SetEvent( start_event
);
15825 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15827 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
15828 WaitForSingleObject( thread
, 10000 );
15829 CloseHandle( thread
);
15832 SetEvent( start_event
);
15834 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
15837 SetEvent( start_event
);
15839 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
15842 SetEvent( start_event
);
15844 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
15847 SetEvent( start_event
);
15849 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
15852 SetEvent( start_event
);
15854 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
15857 SetEvent( start_event
);
15859 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
15862 SetEvent( start_event
);
15864 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
15867 WaitForSingleObject( end_event
, 2000 );
15868 CloseHandle( start_event
);
15869 CloseHandle( end_event
);
15870 if (hwnd
) DestroyWindow( hwnd
);
15873 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
15875 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
15876 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
15879 static DWORD CALLBACK
wait_idle_thread( void *arg
)
15885 memset( &cls
, 0, sizeof(cls
) );
15886 cls
.lpfnWndProc
= wait_idle_proc
;
15887 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
15888 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
15889 cls
.lpszClassName
= "TestClass";
15890 RegisterClassA( &cls
);
15892 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15893 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
15894 DestroyWindow(hwnd
);
15898 static void test_WaitForInputIdle( char *argv0
)
15900 char path
[MAX_PATH
];
15901 PROCESS_INFORMATION pi
;
15902 STARTUPINFOA startup
;
15904 HANDLE start_event
, end_event
, thread
;
15907 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
15908 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
15909 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
15911 if (console_app
) /* build the test with -mwindows for better coverage */
15912 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
15914 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
15915 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
15916 ok(start_event
!= 0, "failed to create start event, error %u\n", GetLastError());
15917 ok(end_event
!= 0, "failed to create end event, error %u\n", GetLastError());
15919 memset( &startup
, 0, sizeof(startup
) );
15920 startup
.cb
= sizeof(startup
);
15921 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
15922 startup
.wShowWindow
= SW_SHOWNORMAL
;
15924 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
15926 for (i
= 0; i
< sizeof(wait_idle_expect
)/sizeof(wait_idle_expect
[0]); i
++)
15928 ResetEvent( start_event
);
15929 ResetEvent( end_event
);
15930 #ifndef __REACTOS__
15931 sprintf( path
, "%s msg %u", argv0
, i
);
15933 sprintf( path
, "%s msg_queue %u", argv0
, i
);
15935 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
15936 ok( ret
, "CreateProcess '%s' failed err %u.\n", path
, GetLastError() );
15939 ret
= WaitForSingleObject( start_event
, 5000 );
15940 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
15941 if (ret
== WAIT_OBJECT_0
)
15943 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
15944 if (ret
== WAIT_FAILED
)
15946 ret
== wait_idle_expect
[i
].exp
||
15947 broken(ret
== wait_idle_expect
[i
].broken
),
15948 "%u: WaitForInputIdle error %08x expected %08x\n",
15949 i
, ret
, wait_idle_expect
[i
].exp
);
15950 else todo_wine_if (wait_idle_expect
[i
].todo
)
15951 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
15952 "%u: WaitForInputIdle error %08x expected %08x\n",
15953 i
, ret
, wait_idle_expect
[i
].exp
);
15954 SetEvent( end_event
);
15955 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
15957 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
15958 winetest_wait_child_process( pi
.hProcess
);
15959 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
15960 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
15961 CloseHandle( pi
.hProcess
);
15962 CloseHandle( pi
.hThread
);
15965 CloseHandle( start_event
);
15966 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
15967 WaitForSingleObject( thread
, 10000 );
15968 CloseHandle( thread
);
15971 static const struct message WmSetParentSeq_1
[] = {
15972 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15973 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15974 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
15975 { WM_CHILDACTIVATE
, sent
},
15976 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
15977 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
15978 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15979 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15983 static const struct message WmSetParentSeq_2
[] = {
15984 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15985 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15986 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15987 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15988 { HCBT_SETFOCUS
, hook
|optional
},
15989 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
15990 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
15991 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
15992 { WM_KILLFOCUS
, sent
|wparam
, 0 },
15993 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15994 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
15995 { HCBT_ACTIVATE
, hook
|optional
},
15996 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15997 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15998 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
15999 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
16000 { HCBT_SETFOCUS
, hook
|optional
},
16001 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16002 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
16003 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
16004 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
16005 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
16006 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
16007 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
16008 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
16009 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16014 static void test_SetParent(void)
16016 HWND parent1
, parent2
, child
, popup
;
16019 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
16020 100, 100, 200, 200, 0, 0, 0, NULL
);
16021 ok(parent1
!= 0, "Failed to create parent1 window\n");
16023 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
16024 400, 100, 200, 200, 0, 0, 0, NULL
);
16025 ok(parent2
!= 0, "Failed to create parent2 window\n");
16027 /* WS_CHILD window */
16028 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
16029 10, 10, 150, 150, parent1
, 0, 0, NULL
);
16030 ok(child
!= 0, "Failed to create child window\n");
16032 GetWindowRect(parent1
, &rc
);
16033 trace("parent1 %s\n", wine_dbgstr_rect(&rc
));
16034 GetWindowRect(child
, &rc_old
);
16035 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
16036 trace("child %s\n", wine_dbgstr_rect(&rc_old
));
16040 SetParent(child
, parent2
);
16042 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", TRUE
);
16044 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
16045 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
16047 GetWindowRect(parent2
, &rc
);
16048 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
16049 GetWindowRect(child
, &rc
);
16050 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
16051 trace("child %s\n", wine_dbgstr_rect(&rc
));
16053 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
16054 wine_dbgstr_rect(&rc
));
16056 /* WS_POPUP window */
16057 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
16058 20, 20, 100, 100, 0, 0, 0, NULL
);
16059 ok(popup
!= 0, "Failed to create popup window\n");
16061 GetWindowRect(popup
, &rc_old
);
16062 trace("popup %s\n", wine_dbgstr_rect(&rc_old
));
16066 SetParent(popup
, child
);
16068 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
16070 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
16071 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
16073 GetWindowRect(child
, &rc
);
16074 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
16075 GetWindowRect(popup
, &rc
);
16076 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
16077 trace("popup %s\n", wine_dbgstr_rect(&rc
));
16079 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
16080 wine_dbgstr_rect(&rc
));
16082 DestroyWindow(popup
);
16083 DestroyWindow(child
);
16084 DestroyWindow(parent1
);
16085 DestroyWindow(parent2
);
16090 static const struct message WmKeyReleaseOnly
[] = {
16091 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
16092 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
16095 static const struct message WmKeyPressNormal
[] = {
16096 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
16097 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
16100 static const struct message WmKeyPressRepeat
[] = {
16101 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
16102 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
16105 static const struct message WmKeyReleaseNormal
[] = {
16106 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
16107 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
16111 static void test_keyflags(void)
16115 BYTE keyboard_state
[256];
16118 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16119 100, 100, 200, 200, 0, 0, 0, NULL
);
16124 /* keyup without a keydown */
16125 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
16126 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16127 DispatchMessageA(&msg
);
16128 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
16130 key_state
= GetAsyncKeyState(0x41);
16131 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16133 key_state
= GetKeyState(0x41);
16134 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16137 keybd_event(0x41, 0, 0, 0);
16138 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16139 DispatchMessageA(&msg
);
16140 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
16142 key_state
= GetAsyncKeyState(0x41);
16143 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16145 key_state
= GetKeyState(0x41);
16146 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16148 /* keydown repeat */
16149 keybd_event(0x41, 0, 0, 0);
16150 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16151 DispatchMessageA(&msg
);
16152 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
16154 key_state
= GetAsyncKeyState(0x41);
16155 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16157 key_state
= GetKeyState(0x41);
16158 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16161 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
16162 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16163 DispatchMessageA(&msg
);
16164 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
16166 key_state
= GetAsyncKeyState(0x41);
16167 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16169 key_state
= GetKeyState(0x41);
16170 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16172 /* set the key state in this thread */
16173 GetKeyboardState(keyboard_state
);
16174 keyboard_state
[0x41] = 0x80;
16175 SetKeyboardState(keyboard_state
);
16177 key_state
= GetAsyncKeyState(0x41);
16178 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16181 keybd_event(0x41, 0, 0, 0);
16182 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16183 DispatchMessageA(&msg
);
16184 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
16186 key_state
= GetAsyncKeyState(0x41);
16187 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16189 key_state
= GetKeyState(0x41);
16190 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16192 /* clear the key state in this thread */
16193 GetKeyboardState(keyboard_state
);
16194 keyboard_state
[0x41] = 0;
16195 SetKeyboardState(keyboard_state
);
16197 key_state
= GetAsyncKeyState(0x41);
16198 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16201 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
16202 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16203 DispatchMessageA(&msg
);
16204 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
16206 key_state
= GetAsyncKeyState(0x41);
16207 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16209 key_state
= GetKeyState(0x41);
16210 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16212 DestroyWindow(test_window
);
16216 static const struct message WmHotkeyPressLWIN
[] = {
16217 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
16218 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
16219 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
16222 static const struct message WmHotkeyPress
[] = {
16223 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16224 { WM_HOTKEY
, sent
|wparam
, 5 },
16227 static const struct message WmHotkeyRelease
[] = {
16228 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16229 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
16230 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
16233 static const struct message WmHotkeyReleaseLWIN
[] = {
16234 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
16235 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
16236 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
16239 static const struct message WmHotkeyCombined
[] = {
16240 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
16241 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16242 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16243 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
16244 { WM_APP
, sent
, 0, 0 },
16245 { WM_HOTKEY
, sent
|wparam
, 5 },
16246 { WM_APP
+1, sent
, 0, 0 },
16247 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
16248 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
16249 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
16250 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
16251 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
16252 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
16255 static const struct message WmHotkeyPrevious
[] = {
16256 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
16257 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16258 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16259 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
16260 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
16261 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
16262 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
16263 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
16264 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
16265 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
16266 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
16267 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
16270 static const struct message WmHotkeyNew
[] = {
16271 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16272 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16273 { WM_HOTKEY
, sent
|wparam
, 5 },
16274 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
16275 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
16279 static int hotkey_letter
;
16281 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
16283 struct recvd_message msg
;
16285 if (nCode
== HC_ACTION
)
16287 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
16290 msg
.message
= wParam
;
16291 msg
.flags
= kbd_hook
|wparam
|lparam
;
16292 msg
.wParam
= kdbhookstruct
->vkCode
;
16293 msg
.lParam
= kdbhookstruct
->flags
;
16294 msg
.descr
= "KeyboardHookProc";
16297 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
)
16299 ok(kdbhookstruct
->vkCode
== VK_LWIN
|| kdbhookstruct
->vkCode
== hotkey_letter
,
16300 "unexpected keycode %x\n", kdbhookstruct
->vkCode
);
16304 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
16307 static void test_hotkey(void)
16309 HWND test_window
, taskbar_window
;
16312 DWORD queue_status
;
16315 SetLastError(0xdeadbeef);
16316 ret
= UnregisterHotKey(NULL
, 0);
16317 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16318 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16319 "unexpected error %d\n", GetLastError());
16323 skip("hotkeys not supported\n");
16327 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16328 100, 100, 200, 200, 0, 0, 0, NULL
);
16332 SetLastError(0xdeadbeef);
16333 ret
= UnregisterHotKey(test_window
, 0);
16334 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16335 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16336 "unexpected error %d\n", GetLastError());
16338 /* Search for a Windows Key + letter combination that hasn't been registered */
16339 for (hotkey_letter
= 0x41; hotkey_letter
<= 0x51; hotkey_letter
++)
16341 SetLastError(0xdeadbeef);
16342 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
16350 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16351 "unexpected error %d\n", GetLastError());
16355 if (hotkey_letter
== 0x52)
16357 ok(0, "Couldn't find any free Windows Key + letter combination\n");
16361 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
16362 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
16364 /* Same key combination, different id */
16365 SetLastError(0xdeadbeef);
16366 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
16367 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16368 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16369 "unexpected error %d\n", GetLastError());
16371 /* Same key combination, different window */
16372 SetLastError(0xdeadbeef);
16373 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
16374 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16375 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16376 "unexpected error %d\n", GetLastError());
16378 /* Register the same hotkey twice */
16379 SetLastError(0xdeadbeef);
16380 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
16381 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16382 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16383 "unexpected error %d\n", GetLastError());
16385 /* Window on another thread */
16386 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
16387 if (!taskbar_window
)
16389 skip("no taskbar?\n");
16393 SetLastError(0xdeadbeef);
16394 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
16395 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16396 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
16397 "unexpected error %d\n", GetLastError());
16400 /* Inject the appropriate key sequence */
16401 keybd_event(VK_LWIN
, 0, 0, 0);
16402 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16403 DispatchMessageA(&msg
);
16404 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
16406 keybd_event(hotkey_letter
, 0, 0, 0);
16407 queue_status
= GetQueueStatus(QS_HOTKEY
);
16408 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
16409 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16411 if (msg
.message
== WM_HOTKEY
)
16413 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
16414 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16416 DispatchMessageA(&msg
);
16418 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
16420 queue_status
= GetQueueStatus(QS_HOTKEY
);
16421 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
16423 key_state
= GetAsyncKeyState(hotkey_letter
);
16424 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16426 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16427 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16428 DispatchMessageA(&msg
);
16429 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
16431 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16432 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16433 DispatchMessageA(&msg
);
16434 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
16436 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
16437 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
16438 queue_status
= GetQueueStatus(QS_HOTKEY
);
16439 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
16440 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
16441 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
16442 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16443 DispatchMessageA(&msg
);
16446 /* Send and process all messages at once */
16447 PostMessageA(test_window
, WM_APP
, 0, 0);
16448 keybd_event(VK_LWIN
, 0, 0, 0);
16449 keybd_event(hotkey_letter
, 0, 0, 0);
16450 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16451 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16453 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16455 if (msg
.message
== WM_HOTKEY
)
16457 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
16458 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16460 DispatchMessageA(&msg
);
16462 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
16464 /* Register same hwnd/id with different key combination */
16465 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
16466 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16468 /* Previous key combination does not work */
16469 keybd_event(VK_LWIN
, 0, 0, 0);
16470 keybd_event(hotkey_letter
, 0, 0, 0);
16471 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16472 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16474 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16475 DispatchMessageA(&msg
);
16476 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
16478 /* New key combination works */
16479 keybd_event(hotkey_letter
, 0, 0, 0);
16480 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16482 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16484 if (msg
.message
== WM_HOTKEY
)
16486 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
16487 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16489 DispatchMessageA(&msg
);
16491 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
16493 /* Unregister hotkey properly */
16494 ret
= UnregisterHotKey(test_window
, 5);
16495 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16497 /* Unregister hotkey again */
16498 SetLastError(0xdeadbeef);
16499 ret
= UnregisterHotKey(test_window
, 5);
16500 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16501 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16502 "unexpected error %d\n", GetLastError());
16504 /* Register thread hotkey */
16505 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
16506 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16508 /* Inject the appropriate key sequence */
16509 keybd_event(VK_LWIN
, 0, 0, 0);
16510 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16512 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16513 DispatchMessageA(&msg
);
16515 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
16517 keybd_event(hotkey_letter
, 0, 0, 0);
16518 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16520 if (msg
.message
== WM_HOTKEY
)
16522 struct recvd_message message
;
16523 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
16524 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16525 message
.message
= msg
.message
;
16526 message
.flags
= sent
|wparam
|lparam
;
16527 message
.wParam
= msg
.wParam
;
16528 message
.lParam
= msg
.lParam
;
16529 message
.descr
= "test_hotkey thread message";
16530 add_message(&message
);
16533 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16534 DispatchMessageA(&msg
);
16536 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
16538 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16539 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16541 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16542 DispatchMessageA(&msg
);
16544 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
16546 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16547 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16549 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16550 DispatchMessageA(&msg
);
16552 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
16554 /* Unregister thread hotkey */
16555 ret
= UnregisterHotKey(NULL
, 5);
16556 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16558 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
16562 UnregisterHotKey(NULL
, 5);
16563 UnregisterHotKey(test_window
, 5);
16564 DestroyWindow(test_window
);
16569 static const struct message WmSetFocus_1
[] = {
16570 { HCBT_SETFOCUS
, hook
}, /* child */
16571 { HCBT_ACTIVATE
, hook
}, /* parent */
16572 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
16573 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
16574 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
16575 { WM_NCACTIVATE
, sent
|parent
},
16576 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
16577 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
16578 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
16579 { HCBT_SETFOCUS
, hook
}, /* parent */
16580 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
16581 { WM_KILLFOCUS
, sent
|parent
},
16582 { WM_SETFOCUS
, sent
},
16585 static const struct message WmSetFocus_2
[] = {
16586 { HCBT_SETFOCUS
, hook
}, /* parent */
16587 { WM_KILLFOCUS
, sent
},
16588 { WM_SETFOCUS
, sent
|parent
},
16591 static const struct message WmSetFocus_3
[] = {
16592 { HCBT_SETFOCUS
, hook
}, /* child */
16596 static void test_SetFocus(void)
16598 HWND parent
, old_parent
, child
, old_focus
, old_active
;
16600 struct wnd_event wnd_event
;
16604 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
16605 ok(wnd_event
.start_event
!= 0, "CreateEvent error %d\n", GetLastError());
16606 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
16607 ok(hthread
!= 0, "CreateThread error %d\n", GetLastError());
16608 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
16609 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
16610 CloseHandle(wnd_event
.start_event
);
16612 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
16613 0, 0, 0, 0, 0, 0, 0, NULL
);
16614 ok(parent
!= 0, "failed to create parent window\n");
16615 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
16616 0, 0, 0, 0, parent
, 0, 0, NULL
);
16617 ok(child
!= 0, "failed to create child window\n");
16619 trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
16622 SetActiveWindow(0);
16627 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
16628 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
16630 log_all_parent_messages
++;
16632 old_focus
= SetFocus(child
);
16633 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16634 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
16635 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
16636 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16637 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
16639 old_focus
= SetFocus(parent
);
16640 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16641 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
16642 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
16643 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16644 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16646 SetLastError(0xdeadbeef);
16647 old_focus
= SetFocus((HWND
)0xdeadbeef);
16648 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
16649 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
16650 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16651 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
16652 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16653 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16654 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16656 SetLastError(0xdeadbeef);
16657 old_focus
= SetFocus(GetDesktopWindow());
16658 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
16659 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
16660 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16661 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
16662 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16663 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16664 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16666 SetLastError(0xdeadbeef);
16667 old_focus
= SetFocus(wnd_event
.hwnd
);
16668 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
16669 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
16670 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16671 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
16672 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16673 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16674 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16676 SetLastError(0xdeadbeef);
16677 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
16678 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
16679 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
16680 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16681 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
16682 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
16683 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16684 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16686 SetLastError(0xdeadbeef);
16687 old_active
= SetActiveWindow(GetDesktopWindow());
16689 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
16690 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16691 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
16692 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
16693 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16694 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16696 SetLastError(0xdeadbeef);
16697 old_active
= SetActiveWindow(wnd_event
.hwnd
);
16699 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
16700 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16701 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
16702 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
16703 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16704 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16706 SetLastError(0xdeadbeef);
16707 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
16708 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
16710 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16711 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16716 old_focus
= SetFocus(wnd_event
.hwnd
);
16717 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16718 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
16719 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
16720 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
16722 old_focus
= SetFocus(parent
);
16723 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16724 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
16725 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16726 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16731 old_active
= SetActiveWindow(wnd_event
.hwnd
);
16732 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16733 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
16734 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
16735 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
16737 SetLastError(0xdeadbeef);
16738 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
16739 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
16741 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
16742 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
16744 old_parent
= SetParent(child
, GetDesktopWindow());
16745 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
16747 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
16748 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
16750 old_focus
= SetFocus(parent
);
16751 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16752 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
16753 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16754 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16759 SetLastError(0xdeadbeef);
16760 old_focus
= SetFocus(child
);
16762 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
16763 broken(GetLastError() == 0) /* XP */ ||
16764 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
16765 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16766 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
16767 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16768 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16769 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16771 SetLastError(0xdeadbeef);
16772 old_active
= SetActiveWindow(child
);
16773 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
16774 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16775 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
16776 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
16777 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16778 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16780 log_all_parent_messages
--;
16782 DestroyWindow(child
);
16783 DestroyWindow(parent
);
16785 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
16786 ok(ret
, "PostMessage(WM_QUIT) error %d\n", GetLastError());
16787 ret
= WaitForSingleObject(hthread
, INFINITE
);
16788 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
16789 CloseHandle(hthread
);
16792 static const struct message WmSetLayeredStyle
[] = {
16793 { WM_STYLECHANGING
, sent
},
16794 { WM_STYLECHANGED
, sent
},
16795 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16799 static const struct message WmSetLayeredStyle2
[] = {
16800 { WM_STYLECHANGING
, sent
},
16801 { WM_STYLECHANGED
, sent
},
16802 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16803 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
16804 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
16805 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
16806 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
16810 struct layered_window_info
16819 static DWORD CALLBACK
update_layered_proc( void *param
)
16821 struct layered_window_info
*info
= param
;
16822 POINT src
= { 0, 0 };
16824 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
16825 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16826 ok( info
->ret
, "failed\n");
16827 SetEvent( info
->event
);
16831 static void test_layered_window(void)
16842 struct layered_window_info info
;
16844 if (!pUpdateLayeredWindow
)
16846 win_skip( "UpdateLayeredWindow not supported\n" );
16850 hdc
= CreateCompatibleDC( 0 );
16851 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
16852 SelectObject( hdc
, bmp
);
16854 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
16855 100, 100, 300, 300, 0, 0, 0, NULL
);
16856 ok( hwnd
!= 0, "failed to create window\n" );
16857 ShowWindow( hwnd
, SW_SHOWNORMAL
);
16858 UpdateWindow( hwnd
);
16862 GetWindowRect( hwnd
, &rect
);
16863 GetClientRect( hwnd
, &client
);
16864 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
16865 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
16868 pos
.x
= pos
.y
= 300;
16869 size
.cx
= size
.cy
= 250;
16870 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16871 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16872 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
16873 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
16874 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
16876 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16877 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16878 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16879 GetWindowRect( hwnd
, &rect
);
16880 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
16881 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16882 GetClientRect( hwnd
, &rect
);
16883 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
16884 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16888 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16889 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16890 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16891 GetWindowRect( hwnd
, &rect
);
16892 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
16893 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16894 GetClientRect( hwnd
, &rect
);
16895 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
16896 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16898 SetWindowLongA( hwnd
, GWL_STYLE
,
16899 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
16900 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
16904 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16905 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16906 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16907 GetWindowRect( hwnd
, &rect
);
16908 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
16909 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16910 GetClientRect( hwnd
, &rect
);
16911 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
16912 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
16913 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16916 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16917 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16918 ok( GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == ERROR_MR_MID_NOT_FOUND
) ||
16919 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win7 */, "wrong error %u\n", GetLastError() );
16922 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16923 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16924 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
16926 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
16927 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
16928 GetWindowRect( hwnd
, &rect
);
16929 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
16930 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16931 GetClientRect( hwnd
, &rect
);
16932 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
16933 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
16934 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16936 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
16939 info
.size
.cx
= 250;
16940 info
.size
.cy
= 300;
16941 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
16943 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
16944 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
16945 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
16946 WaitForSingleObject( thread
, 1000 );
16947 CloseHandle( thread
);
16948 GetWindowRect( hwnd
, &rect
);
16949 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
16950 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16951 GetClientRect( hwnd
, &rect
);
16952 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
16953 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
16954 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16956 DestroyWindow( hwnd
);
16958 DeleteObject( bmp
);
16961 static HMENU hpopupmenu
;
16963 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16965 if (ignore_message( message
)) return 0;
16969 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
16973 case WM_INITMENUPOPUP
:
16974 case WM_UNINITMENUPOPUP
:
16975 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %lx\n", hpopupmenu
, wParam
);
16977 case WM_CAPTURECHANGED
:
16978 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %lx\n", lParam
);
16982 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
16985 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16987 if (ignore_message( message
)) return 0;
16990 case WM_ENTERMENULOOP
:
16991 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
16995 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
16998 static void test_TrackPopupMenu(void)
17004 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
17007 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
17009 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
17011 hpopupmenu
= CreatePopupMenu();
17012 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
17014 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
17015 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
17019 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
17020 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
17021 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
17023 /* Test popup closing with an ESC-press */
17025 PostMessageW(hwnd
, WM_KEYDOWN
, VK_ESCAPE
, 0);
17026 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
17027 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
17028 PostQuitMessage(0);
17030 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
17032 TranslateMessage(&msg
);
17033 DispatchMessageA(&msg
);
17035 ok_sequence(WmTrackPopupMenuEsc
, "TrackPopupMenuEsc", FALSE
); /* Shouldn't get any message */
17037 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
17041 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
17042 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
17043 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
17045 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
17051 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
17052 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
17053 ok(ret
== 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError());
17055 DestroyMenu(hpopupmenu
);
17056 DestroyWindow(hwnd
);
17059 static void test_TrackPopupMenuEmpty(void)
17064 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
17067 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
17069 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
17071 hpopupmenu
= CreatePopupMenu();
17072 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
17076 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
17077 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
17078 ok(ret
== 0, "TrackPopupMenu succeeded\n");
17080 DestroyMenu(hpopupmenu
);
17081 DestroyWindow(hwnd
);
17084 static const struct message send_message_1
[] = {
17085 { WM_USER
+2, sent
|wparam
|lparam
, 0, 0 },
17086 { WM_USER
, sent
|wparam
|lparam
, 0, 0 },
17089 static const struct message send_message_2
[] = {
17090 { WM_USER
+4, sent
|wparam
|lparam
, 0, 0 },
17093 static const struct message send_message_3
[] = {
17094 { WM_USER
+3, sent
|wparam
|lparam
, 0, 0 },
17095 { WM_USER
+1, sent
|wparam
|lparam
, 0, 0 },
17099 static DWORD WINAPI
SendMessage_thread_1(void *param
)
17101 struct wnd_event
*wnd_event
= param
;
17103 trace("thread: starting\n");
17104 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
17106 trace("thread: call PostMessage\n");
17107 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
17109 trace("thread: call PostMessage\n");
17110 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
17112 trace("thread: call SendMessage\n");
17113 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
17115 trace("thread: call SendMessage\n");
17116 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
17121 static DWORD WINAPI
SendMessage_thread_2(void *param
)
17123 struct wnd_event
*wnd_event
= param
;
17125 trace("thread: starting\n");
17126 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
17128 trace("thread: call PostMessage\n");
17129 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
17131 trace("thread: call PostMessage\n");
17132 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
17134 /* this leads to sending an internal message under Wine */
17135 trace("thread: call SetParent\n");
17136 SetParent(wnd_event
->hwnd
, wnd_event
->hwnd
);
17138 trace("thread: call SendMessage\n");
17139 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
17141 trace("thread: call SendMessage\n");
17142 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
17147 static void test_SendMessage_other_thread(int thread_n
)
17149 DWORD qs_all_input
= QS_ALLINPUT
& ~QS_RAWINPUT
;
17151 struct wnd_event wnd_event
;
17155 wnd_event
.start_event
= CreateEventA(NULL
, 0, 0, NULL
);
17157 wnd_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
17158 100, 100, 200, 200, 0, 0, 0, NULL
);
17159 ok(wnd_event
.hwnd
!= 0, "CreateWindowEx failed\n");
17161 hthread
= CreateThread(NULL
, 0, thread_n
== 1 ? SendMessage_thread_1
: SendMessage_thread_2
, &wnd_event
, 0, &tid
);
17162 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
17163 CloseHandle(hthread
);
17168 ret
= GetQueueStatus(QS_SENDMESSAGE
);
17169 ok(ret
== 0, "wrong status %08x\n", ret
);
17171 SetEvent(wnd_event
.start_event
);
17173 /* wait for other thread's SendMessage */
17176 ret
= GetQueueStatus(QS_SENDMESSAGE
);
17177 if (ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
)) break;
17181 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17182 ok(ret
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08x\n", ret
);
17184 trace("main: call GetMessage\n");
17185 GetMessageA(&msg
, 0, 0, 0);
17186 ok(msg
.message
== WM_USER
, "expected WM_USER, got %04x\n", msg
.message
);
17187 DispatchMessageA(&msg
);
17188 ok_sequence(send_message_1
, "SendMessage from other thread 1", thread_n
== 2);
17190 /* intentionally yield */
17191 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
17193 trace("main: call SendMessage\n");
17194 SendMessageA(wnd_event
.hwnd
, WM_USER
+4, 0, 0);
17195 ok_sequence(send_message_2
, "SendMessage from other thread 2", FALSE
);
17197 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17198 ok(ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08x\n", ret
);
17200 trace("main: call PeekMessage\n");
17201 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should not fail\n");
17202 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
17203 DispatchMessageA(&msg
);
17204 ok_sequence(send_message_3
, "SendMessage from other thread 3", thread_n
== 2);
17206 /* intentionally yield */
17207 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
17209 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17210 /* FIXME: remove once Wine is fixed */
17211 todo_wine_if (thread_n
== 2)
17212 ok(ret
== 0, "wrong status %08x\n", ret
);
17214 trace("main: call PeekMessage\n");
17215 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should fail\n");
17216 ok_sequence(WmEmptySeq
, "SendMessage from other thread 5", thread_n
== 2);
17218 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17219 ok(ret
== 0, "wrong status %08x\n", ret
);
17221 trace("main: call DestroyWindow\n");
17222 DestroyWindow(msg
.hwnd
);
17228 static LRESULT CALLBACK
insendmessage_wnd_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
17230 DWORD flags
= InSendMessageEx( NULL
);
17236 ok( flags
== ISMEX_SEND
, "wrong flags %x\n", flags
);
17237 ok( InSendMessage(), "InSendMessage returned false\n" );
17238 ret
= ReplyMessage( msg
);
17239 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
17240 flags
= InSendMessageEx( NULL
);
17241 ok( flags
== (ISMEX_SEND
| ISMEX_REPLIED
), "wrong flags %x\n", flags
);
17242 ok( InSendMessage(), "InSendMessage returned false\n" );
17245 ok( flags
== ISMEX_NOTIFY
, "wrong flags %x\n", flags
);
17246 ok( InSendMessage(), "InSendMessage returned false\n" );
17247 ret
= ReplyMessage( msg
);
17248 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
17249 flags
= InSendMessageEx( NULL
);
17250 ok( flags
== ISMEX_NOTIFY
, "wrong flags %x\n", flags
);
17251 ok( InSendMessage(), "InSendMessage returned false\n" );
17254 ok( flags
== ISMEX_CALLBACK
, "wrong flags %x\n", flags
);
17255 ok( InSendMessage(), "InSendMessage returned false\n" );
17256 ret
= ReplyMessage( msg
);
17257 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
17258 flags
= InSendMessageEx( NULL
);
17259 ok( flags
== (ISMEX_CALLBACK
| ISMEX_REPLIED
) || flags
== ISMEX_SEND
, "wrong flags %x\n", flags
);
17260 ok( InSendMessage(), "InSendMessage returned false\n" );
17263 ok( flags
== ISMEX_NOSEND
, "wrong flags %x\n", flags
);
17264 ok( !InSendMessage(), "InSendMessage returned true\n" );
17265 ret
= ReplyMessage( msg
);
17266 ok( !ret
, "ReplyMessage succeeded\n" );
17270 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
17273 static void CALLBACK
msg_callback( HWND hwnd
, UINT msg
, ULONG_PTR arg
, LRESULT result
)
17275 ok( msg
== WM_USER
+ 2, "wrong msg %x\n", msg
);
17276 ok( result
== WM_USER
+ 2, "wrong result %lx\n", result
);
17279 static DWORD WINAPI
send_message_thread( void *arg
)
17283 SendMessageA( win
, WM_USER
, 0, 0 );
17284 SendNotifyMessageA( win
, WM_USER
+ 1, 0, 0 );
17285 SendMessageCallbackA( win
, WM_USER
+ 2, 0, 0, msg_callback
, 0 );
17286 PostMessageA( win
, WM_USER
+ 3, 0, 0 );
17287 PostMessageA( win
, WM_QUIT
, 0, 0 );
17291 static void test_InSendMessage(void)
17299 memset(&cls
, 0, sizeof(cls
));
17300 cls
.lpfnWndProc
= insendmessage_wnd_proc
;
17301 cls
.hInstance
= GetModuleHandleA(NULL
);
17302 cls
.lpszClassName
= "InSendMessage_test";
17303 RegisterClassA(&cls
);
17305 win
= CreateWindowA( "InSendMessage_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
17306 ok( win
!= NULL
, "CreateWindow failed: %d\n", GetLastError() );
17308 thread
= CreateThread( NULL
, 0, send_message_thread
, win
, 0, &tid
);
17309 ok( thread
!= NULL
, "CreateThread failed: %d\n", GetLastError() );
17311 while (GetMessageA(&msg
, NULL
, 0, 0)) DispatchMessageA( &msg
);
17313 ok( WaitForSingleObject( thread
, 30000 ) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
17314 CloseHandle( thread
);
17316 DestroyWindow( win
);
17317 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL
) );
17320 static const struct message DoubleSetCaptureSeq
[] =
17322 { WM_CAPTURECHANGED
, sent
},
17326 static void test_DoubleSetCapture(void)
17330 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture",
17331 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
17332 100, 100, 200, 200, 0, 0, 0, NULL
);
17333 ok (hwnd
!= 0, "Failed to create overlapped window\n");
17335 ShowWindow( hwnd
, SW_SHOW
);
17336 UpdateWindow( hwnd
);
17340 SetCapture( hwnd
);
17341 SetCapture( hwnd
);
17342 ok_sequence(DoubleSetCaptureSeq
, "SetCapture( hwnd ) twice", FALSE
);
17344 DestroyWindow(hwnd
);
17347 static void init_funcs(void)
17349 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
17351 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
17354 X(DeactivateActCtx
);
17355 X(GetCurrentActCtx
);
17361 #ifndef __REACTOS__
17366 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
17367 HMODULE hModuleImm32
;
17368 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
17373 argc
= winetest_get_mainargs( &test_argv
);
17377 /* Child process. */
17378 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
17379 do_wait_idle_child( arg
);
17383 InitializeCriticalSection( &sequence_cs
);
17386 hModuleImm32
= LoadLibraryA("imm32.dll");
17387 if (hModuleImm32
) {
17388 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
17389 if (pImmDisableIME
)
17392 pImmDisableIME
= NULL
;
17393 FreeLibrary(hModuleImm32
);
17395 if (!RegisterWindowClasses()) assert(0);
17397 if (pSetWinEventHook
)
17399 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
17400 GetModuleHandleA(0), win_event_proc
,
17401 0, GetCurrentThreadId(),
17402 WINEVENT_INCONTEXT
);
17403 if (pIsWinEventHookInstalled
&& hEvent_hook
)
17406 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
17407 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
17410 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
17412 cbt_hook_thread_id
= GetCurrentThreadId();
17413 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
17414 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
17418 /* Fix message sequences before removing 4 lines below */
17419 if (pUnhookWinEvent
&& hEvent_hook
)
17421 ret
= pUnhookWinEvent(hEvent_hook
);
17422 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17423 pUnhookWinEvent
= 0;
17427 test_SendMessage_other_thread(1);
17428 test_SendMessage_other_thread(2);
17429 test_InSendMessage();
17432 test_PostMessage();
17435 test_PeekMessage();
17436 test_PeekMessage2();
17437 test_PeekMessage3();
17438 test_WaitForInputIdle( test_argv
[0] );
17439 test_scrollwindowex();
17441 test_setwindowpos();
17443 invisible_parent_tests();
17444 test_mdi_messages();
17445 test_button_messages();
17446 test_autoradio_BM_CLICK();
17447 test_autoradio_kbd_move();
17448 test_static_messages();
17449 test_listbox_messages();
17450 test_combobox_messages();
17451 test_wmime_keydown_message();
17452 test_paint_messages();
17453 test_interthread_messages();
17454 test_message_conversion();
17455 test_accelerators();
17457 test_timers_no_wnd();
17458 test_timers_exceptions();
17462 test_recursive_hook();
17464 test_DestroyWindow();
17465 test_DispatchMessage();
17466 test_SendMessageTimeout();
17467 test_edit_messages();
17468 test_quit_message();
17469 test_notify_message();
17470 test_SetActiveWindow();
17472 if (!pTrackMouseEvent
)
17473 win_skip("TrackMouseEvent is not available\n");
17475 test_TrackMouseEvent();
17477 test_SetWindowRgn();
17479 test_dialog_messages();
17481 test_nullCallback();
17482 test_dbcs_wm_char();
17483 test_unicode_wm_char();
17484 test_menu_messages();
17485 test_paintingloop();
17487 test_clipboard_viewers();
17490 test_layered_window();
17491 test_TrackPopupMenu();
17492 test_TrackPopupMenuEmpty();
17493 test_DoubleSetCapture();
17494 /* keep it the last test, under Windows it tends to break the tests
17495 * which rely on active/foreground windows being correct.
17497 test_SetForegroundWindow();
17499 UnhookWindowsHookEx(hCBT_hook
);
17500 if (pUnhookWinEvent
&& hEvent_hook
)
17502 ret
= pUnhookWinEvent(hEvent_hook
);
17503 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17504 SetLastError(0xdeadbeef);
17505 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
17506 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
17507 GetLastError() == 0xdeadbeef, /* Win9x */
17508 "unexpected error %d\n", GetLastError());
17510 DeleteCriticalSection( &sequence_cs
);
17512 #endif /* __REACTOS__ */
17514 static void init_tests()
17516 HMODULE hModuleImm32
;
17517 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
17521 InitializeCriticalSection( &sequence_cs
);
17524 hModuleImm32
= LoadLibraryA("imm32.dll");
17525 if (hModuleImm32
) {
17526 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
17527 if (pImmDisableIME
)
17530 pImmDisableIME
= NULL
;
17531 FreeLibrary(hModuleImm32
);
17533 if (!RegisterWindowClasses()) assert(0);
17535 cbt_hook_thread_id
= GetCurrentThreadId();
17536 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
17537 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
17540 static void cleanup_tests()
17543 UnhookWindowsHookEx(hCBT_hook
);
17544 if (pUnhookWinEvent
&& hEvent_hook
)
17546 ret
= pUnhookWinEvent(hEvent_hook
);
17547 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17548 SetLastError(0xdeadbeef);
17549 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
17550 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
17551 GetLastError() == 0xdeadbeef, /* Win9x */
17552 "unexpected error %d\n", GetLastError());
17554 DeleteCriticalSection( &sequence_cs
);
17558 START_TEST(msg_queue
)
17562 argc
= winetest_get_mainargs( &test_argv
);
17566 /* Child process. */
17567 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
17568 do_wait_idle_child( arg
);
17573 test_SendMessage_other_thread(1);
17574 test_SendMessage_other_thread(2);
17575 test_InSendMessage();
17576 test_PostMessage();
17578 test_PeekMessage();
17579 test_PeekMessage2();
17580 test_PeekMessage3();
17581 test_interthread_messages();
17582 test_DispatchMessage();
17583 test_SendMessageTimeout();
17584 test_quit_message();
17585 test_notify_message();
17586 test_WaitForInputIdle( test_argv
[0] );
17587 test_DestroyWindow();
17591 START_TEST(msg_messages
)
17594 test_message_conversion();
17596 test_wmime_keydown_message();
17597 test_nullCallback();
17598 test_dbcs_wm_char();
17599 test_unicode_wm_char();
17604 START_TEST(msg_focus
)
17610 /* HACK: For some reason the tests fail on Windows if run consecutively.
17611 * Putting these in between helps, and is essentially what happens in the
17612 * "normal" msg test. */
17613 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
17616 test_SetActiveWindow();
17619 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
17622 test_DoubleSetCapture();
17624 /* keep it the last test, under Windows it tends to break the tests
17625 * which rely on active/foreground windows being correct.
17627 test_SetForegroundWindow();
17631 START_TEST(msg_winpos
)
17636 test_setwindowpos();
17638 test_SetWindowRgn();
17639 invisible_parent_tests();
17643 START_TEST(msg_paint
)
17646 test_scrollwindowex();
17647 test_paint_messages();
17649 if (!winetest_interactive
&&
17650 !strcmp(winetest_platform
, "windows"))
17652 skip("ROSTESTS-185: Skipping user32_winetest:msg_paint test_paintingloop because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
17656 test_paintingloop();
17660 START_TEST(msg_input
)
17663 test_accelerators();
17664 if (!pTrackMouseEvent
)
17665 win_skip("TrackMouseEvent is not available\n");
17667 test_TrackMouseEvent();
17674 START_TEST(msg_timer
)
17678 test_timers_no_wnd();
17679 test_timers_exceptions();
17683 typedef BOOL (WINAPI
*IS_WINEVENT_HOOK_INSTALLED
)(DWORD
);
17685 START_TEST(msg_hook
)
17687 // HMODULE user32 = GetModuleHandleA("user32.dll");
17688 // IS_WINEVENT_HOOK_INSTALLED pIsWinEventHookInstalled = (IS_WINEVENT_HOOK_INSTALLED)GetProcAddress(user32, "IsWinEventHookInstalled");
17689 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
17693 if (pSetWinEventHook
)
17695 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
17696 GetModuleHandleA(0), win_event_proc
,
17697 0, GetCurrentThreadId(),
17698 WINEVENT_INCONTEXT
);
17699 if (pIsWinEventHookInstalled
&& hEvent_hook
)
17702 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
17703 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
17706 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
17710 /* Fix message sequences before removing 4 lines below */
17711 if (pUnhookWinEvent
&& hEvent_hook
)
17714 ret
= pUnhookWinEvent(hEvent_hook
);
17715 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17716 pUnhookWinEvent
= 0;
17722 test_recursive_hook();
17727 START_TEST(msg_menu
)
17731 test_menu_messages();
17732 test_TrackPopupMenu();
17733 test_TrackPopupMenuEmpty();
17737 START_TEST(msg_mdi
)
17740 test_mdi_messages();
17744 START_TEST(msg_controls
)
17747 test_button_messages();
17748 test_autoradio_BM_CLICK();
17749 test_autoradio_kbd_move();
17750 test_static_messages();
17751 test_listbox_messages();
17752 test_combobox_messages();
17753 test_edit_messages();
17757 START_TEST(msg_layered_window
)
17760 test_layered_window();
17764 START_TEST(msg_dialog
)
17767 test_dialog_messages();
17772 START_TEST(msg_clipboard
)
17775 test_clipboard_viewers();