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
23 //#define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */
24 //#define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */
37 #include "wine/test.h"
39 #define MDI_FIRST_CHILD_ID 2004
41 /* undocumented SWP flags - from SDK 3.1 */
42 #define SWP_NOCLIENTSIZE 0x0800
43 #define SWP_NOCLIENTMOVE 0x1000
44 #define SWP_STATECHANGED 0x8000
46 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
49 #define WM_KEYF1 0x004d
53 #define WM_SYSTIMER 0x0118
56 #define WND_PARENT_ID 1
57 #define WND_POPUP_ID 2
58 #define WND_CHILD_ID 3
60 #ifndef WM_LBTRACKPOINT
61 #define WM_LBTRACKPOINT 0x0131
66 #elif defined __x86_64__
70 #elif defined __aarch64__
76 static BOOL (WINAPI
*pActivateActCtx
)(HANDLE
,ULONG_PTR
*);
77 static HANDLE (WINAPI
*pCreateActCtxW
)(PCACTCTXW
);
78 static BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
,ULONG_PTR
);
79 static BOOL (WINAPI
*pGetCurrentActCtx
)(HANDLE
*);
80 static BOOL (WINAPI
*pQueryActCtxW
)(DWORD
,HANDLE
,void*,ULONG
,void*,SIZE_T
,SIZE_T
*);
81 static void (WINAPI
*pReleaseActCtx
)(HANDLE
);
83 /* encoded DRAWITEMSTRUCT into an LPARAM */
90 UINT type
: 4; /* ODT_* flags */
91 UINT ctl_id
: 4; /* Control ID */
92 UINT item_id
: 4; /* Menu item ID */
93 UINT action
: 4; /* ODA_* flags */
94 UINT state
: 16; /* ODS_* flags */
100 /* encoded MEASUREITEMSTRUCT into a WPARAM */
114 } MEASURE_ITEM_STRUCT
;
116 static BOOL test_DestroyWindow_flag
;
117 static HWINEVENTHOOK hEvent_hook
;
118 static HHOOK hKBD_hook
;
119 static HHOOK hCBT_hook
;
120 static DWORD cbt_hook_thread_id
;
122 static const WCHAR testWindowClassW
[] =
123 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
125 static LRESULT WINAPI
ParentMsgCheckProcA(HWND
, UINT
, WPARAM
, LPARAM
);
128 FIXME: add tests for these
129 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
130 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
131 WS_THICKFRAME: thick border
132 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
133 WS_BORDER (default for overlapped windows): single black border
134 none (default for child (and popup?) windows): no border
152 UINT message
; /* the WM_* code */
153 msg_flags_t flags
; /* message props */
154 WPARAM wParam
; /* expected value of wParam */
155 LPARAM lParam
; /* expected value of lParam */
156 WPARAM wp_mask
; /* mask for wParam checks */
157 LPARAM lp_mask
; /* mask for lParam checks */
160 struct recvd_message
{
161 UINT message
; /* the WM_* code */
162 msg_flags_t flags
; /* message props */
163 HWND hwnd
; /* window that received the message */
164 WPARAM wParam
; /* expected value of wParam */
165 LPARAM lParam
; /* expected value of lParam */
166 int line
; /* source line where logged */
167 const char *descr
; /* description for trace output */
168 char output
[512]; /* trace output */
171 /* Empty message sequence */
172 static const struct message WmEmptySeq
[] =
176 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
177 static const struct message WmCreateOverlappedSeq
[] = {
178 { HCBT_CREATEWND
, hook
},
179 { WM_GETMINMAXINFO
, sent
},
180 { WM_NCCREATE
, sent
},
181 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
182 { 0x0093, sent
|defwinproc
|optional
},
183 { 0x0094, sent
|defwinproc
|optional
},
184 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
186 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
189 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
190 * for a not visible overlapped window.
192 static const struct message WmSWP_ShowOverlappedSeq
[] = {
193 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
194 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
195 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
196 { WM_GETTEXT
, sent
|defwinproc
|optional
},
197 { WM_ERASEBKGND
, sent
|optional
},
198 { HCBT_ACTIVATE
, hook
},
199 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
200 { WM_NOTIFYFORMAT
, sent
|optional
},
201 { WM_QUERYUISTATE
, sent
|optional
},
202 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
203 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
204 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
205 { WM_NCACTIVATE
, sent
},
206 { WM_GETTEXT
, sent
|defwinproc
|optional
},
207 { WM_ACTIVATE
, sent
|wparam
, 1 },
208 { HCBT_SETFOCUS
, hook
},
209 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
210 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
211 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
212 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
213 { WM_GETTEXT
, sent
|optional
},
214 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
215 { WM_GETTEXT
, sent
|defwinproc
|optional
},
216 { WM_ERASEBKGND
, sent
|optional
},
217 /* Win9x adds SWP_NOZORDER below */
218 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
219 { WM_GETTEXT
, sent
|optional
},
220 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
221 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
222 { WM_ERASEBKGND
, sent
|optional
},
223 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
224 { WM_SYNCPAINT
, sent
|optional
},
225 { WM_GETTITLEBARINFOEX
, sent
|optional
},
226 { WM_PAINT
, sent
|optional
},
227 { WM_NCPAINT
, sent
|beginpaint
|optional
},
228 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
229 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
232 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
233 * for a visible overlapped window.
235 static const struct message WmSWP_HideOverlappedSeq
[] = {
236 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
237 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
238 { HCBT_ACTIVATE
, hook
|optional
},
239 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
240 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
241 { WM_NCACTIVATE
, sent
|optional
},
242 { WM_ACTIVATE
, sent
|optional
},
243 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
247 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
248 * for a visible overlapped window.
250 static const struct message WmSWP_ResizeSeq
[] = {
251 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
252 { WM_GETMINMAXINFO
, sent
|defwinproc
},
253 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
254 { WM_NCPAINT
, sent
|optional
},
255 { WM_GETTEXT
, sent
|defwinproc
|optional
},
256 { WM_ERASEBKGND
, sent
|optional
},
257 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
258 { WM_SIZE
, sent
|defwinproc
|optional
},
259 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
260 { WM_NCPAINT
, sent
|optional
},
261 { WM_GETTEXT
, sent
|defwinproc
|optional
},
262 { WM_ERASEBKGND
, sent
|optional
},
263 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
264 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
268 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
269 * for a visible popup window.
271 static const struct message WmSWP_ResizePopupSeq
[] = {
272 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
273 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* Win9x */
274 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
275 { WM_NCPAINT
, sent
|optional
},
276 { WM_GETTEXT
, sent
|defwinproc
|optional
},
277 { WM_ERASEBKGND
, sent
|optional
},
278 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
279 { WM_SIZE
, sent
|defwinproc
|wparam
|optional
, SIZE_RESTORED
},
280 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
281 { WM_NCPAINT
, sent
|optional
},
282 { WM_GETTEXT
, sent
|defwinproc
|optional
},
283 { WM_ERASEBKGND
, sent
|optional
},
284 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
288 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
289 * for a visible overlapped window.
291 static const struct message WmSWP_MoveSeq
[] = {
292 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
},
293 { WM_NCPAINT
, sent
|optional
},
294 { WM_GETTEXT
, sent
|defwinproc
|optional
},
295 { WM_ERASEBKGND
, sent
|optional
},
296 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
297 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
298 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
301 /* Resize with SetWindowPos(SWP_NOZORDER)
302 * for a visible overlapped window
303 * SWP_NOZORDER is stripped by the logging code
305 static const struct message WmSWP_ResizeNoZOrder
[] = {
306 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
},
307 { WM_GETMINMAXINFO
, sent
|defwinproc
},
308 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
309 { WM_NCPAINT
, sent
|optional
},
310 { WM_GETTEXT
, sent
|defwinproc
|optional
},
311 { WM_ERASEBKGND
, sent
|optional
},
312 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
, 0,
313 SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
314 { WM_MOVE
, sent
|defwinproc
|optional
},
315 { WM_SIZE
, sent
|defwinproc
|optional
},
316 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
317 { WM_NCPAINT
, sent
|optional
}, /* Win9x doesn't send it */
318 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
319 { WM_ERASEBKGND
, sent
|optional
}, /* Win9x doesn't send it */
320 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
321 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
325 /* Switch visible mdi children */
326 static const struct message WmSwitchChild
[] = {
327 /* Switch MDI child */
328 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
329 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 1st MDI child */
330 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
331 { WM_CHILDACTIVATE
, sent
},/* in the 1st MDI child */
332 /* Deactivate 2nd MDI child */
333 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
334 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
335 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
336 /* Preparing for maximize and maximize the 1st MDI child */
337 { WM_GETMINMAXINFO
, sent
|defwinproc
}, /* in the 1st MDI child */
338 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
}, /* in the 1st MDI child */
339 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
340 { WM_CHILDACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
341 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 1st MDI child */
342 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
}, /* in the 1st MDI child */
343 /* Lock redraw 2nd MDI child */
344 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
345 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
346 /* Restore 2nd MDI child */
347 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},/* in the 2nd MDI child */
348 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
349 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
350 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 2nd MDI child */
351 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
}, /* in the 2nd MDI child */
352 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
353 /* Redraw 2nd MDI child */
354 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
355 /* Redraw MDI frame */
356 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},/* in MDI frame */
357 { WM_NCCALCSIZE
, sent
|wparam
, 1 },/* in MDI frame */
358 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in MDI frame */
359 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in MDI frame */
360 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
361 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
362 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
363 { HCBT_SETFOCUS
, hook
},
364 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
365 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },/* in the 1st MDI child */
366 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
367 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
368 { WM_SETFOCUS
, sent
},/* in the MDI client */
369 { HCBT_SETFOCUS
, hook
},
370 { WM_KILLFOCUS
, sent
},/* in the MDI client */
371 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
372 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 }, /* in the 1st MDI child */
373 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
374 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
375 { WM_MDIACTIVATE
, sent
|defwinproc
},/* in the 1st MDI child */
376 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 1st MDI child */
380 /* Switch visible not maximized mdi children */
381 static const struct message WmSwitchNotMaximizedChild
[] = {
382 /* Switch not maximized MDI child */
383 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
384 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 2nd MDI child */
385 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
386 { WM_CHILDACTIVATE
, sent
},/* in the 2nd MDI child */
387 /* Deactivate 1st MDI child */
388 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
389 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
390 /* Activate 2nd MDI child */
391 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
}, /* in the 2nd MDI child */
392 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 2nd MDI child */
393 { HCBT_SETFOCUS
, hook
}, /* in the 1st MDI child */
394 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
395 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
396 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
397 { WM_SETFOCUS
, sent
, 0 }, /* in the MDI client */
398 { HCBT_SETFOCUS
, hook
},
399 { WM_KILLFOCUS
, sent
}, /* in the MDI client */
400 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
401 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
402 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
403 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
404 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 2nd MDI child */
409 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
410 SWP_NOZORDER|SWP_FRAMECHANGED)
411 * for a visible overlapped window with WS_CLIPCHILDREN style set.
413 static const struct message WmSWP_FrameChanged_clip
[] = {
414 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
415 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
416 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
417 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
418 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
419 { WM_NCPAINT
, sent
}, /* wparam != 1 */
420 { WM_ERASEBKGND
, sent
},
421 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
422 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
426 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
427 SWP_NOZORDER|SWP_FRAMECHANGED)
428 * for a visible overlapped window.
430 static const struct message WmSWP_FrameChangedDeferErase
[] = {
431 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
432 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
433 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
434 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
435 { WM_PAINT
, sent
|parent
|optional
},
436 { WM_NCPAINT
, sent
|beginpaint
|parent
|optional
}, /* wparam != 1 */
437 { WM_GETTEXT
, sent
|beginpaint
|parent
|defwinproc
|optional
},
439 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
440 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
444 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
445 SWP_NOZORDER|SWP_FRAMECHANGED)
446 * for a visible overlapped window without WS_CLIPCHILDREN style set.
448 static const struct message WmSWP_FrameChanged_noclip
[] = {
449 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
450 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
451 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
452 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
453 { WM_ERASEBKGND
, sent
|parent
|optional
},
454 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
455 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
457 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
458 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
462 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
463 static const struct message WmShowOverlappedSeq
[] = {
464 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
465 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
466 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
467 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
468 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
469 { WM_GETTEXT
, sent
|defwinproc
|optional
},
470 { WM_ERASEBKGND
, sent
|optional
},
471 { HCBT_ACTIVATE
, hook
|optional
},
472 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
473 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
474 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
475 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
476 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
477 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
478 { WM_GETTEXT
, sent
|defwinproc
|optional
},
479 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
480 { HCBT_SETFOCUS
, hook
|optional
},
481 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
482 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
483 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
484 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
485 { WM_GETTEXT
, sent
|optional
},
486 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
487 { WM_GETTEXT
, sent
|defwinproc
|optional
},
488 { WM_ERASEBKGND
, sent
|optional
},
489 /* Win9x adds SWP_NOZORDER below */
490 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
491 { WM_NCCALCSIZE
, sent
|optional
},
492 { WM_GETTEXT
, sent
|optional
},
493 { WM_NCPAINT
, sent
|optional
},
494 { WM_ERASEBKGND
, sent
|optional
},
495 { WM_SYNCPAINT
, sent
|optional
},
496 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
497 * messages. Does that mean that CreateWindow doesn't set initial
498 * window dimensions for overlapped windows?
503 { WM_PAINT
, sent
|optional
},
504 { WM_NCPAINT
, sent
|beginpaint
|optional
},
507 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
508 static const struct message WmShowMaxOverlappedSeq
[] = {
509 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
510 { WM_GETMINMAXINFO
, sent
},
511 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
512 { WM_GETMINMAXINFO
, sent
|defwinproc
},
513 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
514 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
515 { HCBT_ACTIVATE
, hook
|optional
},
516 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
517 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
518 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
519 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
520 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
521 { WM_GETTEXT
, sent
|defwinproc
|optional
},
522 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
523 { HCBT_SETFOCUS
, hook
|optional
},
524 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
525 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
526 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
527 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
528 { WM_GETTEXT
, sent
|optional
},
529 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
530 { WM_GETTEXT
, sent
|defwinproc
|optional
},
531 { WM_ERASEBKGND
, sent
|optional
},
532 /* Win9x adds SWP_NOZORDER below */
533 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
534 { WM_MOVE
, sent
|defwinproc
},
535 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
536 { WM_GETTEXT
, sent
|optional
},
537 { WM_NCCALCSIZE
, sent
|optional
},
538 { WM_NCPAINT
, sent
|optional
},
539 { WM_ERASEBKGND
, sent
|optional
},
540 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
541 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
542 { WM_SYNCPAINT
, sent
|optional
},
543 { WM_GETTITLEBARINFOEX
, sent
|optional
},
544 { WM_PAINT
, sent
|optional
},
545 { WM_NCPAINT
, sent
|beginpaint
|optional
},
546 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
549 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
550 static const struct message WmShowRestoreMaxOverlappedSeq
[] = {
551 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
552 { WM_GETTEXT
, sent
|optional
},
553 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
554 { WM_GETMINMAXINFO
, sent
|defwinproc
},
555 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
556 { WM_NCPAINT
, sent
|optional
},
557 { WM_GETTEXT
, sent
|defwinproc
|optional
},
558 { WM_ERASEBKGND
, sent
|optional
},
559 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
560 { WM_MOVE
, sent
|defwinproc
|optional
},
561 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
562 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
563 { WM_NCPAINT
, sent
|optional
},
564 { WM_ERASEBKGND
, sent
|optional
},
565 { WM_PAINT
, sent
|optional
},
566 { WM_GETTITLEBARINFOEX
, sent
|optional
},
567 { WM_NCPAINT
, sent
|beginpaint
|optional
},
568 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
571 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
572 static const struct message WmShowRestoreMinOverlappedSeq
[] = {
573 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
574 { WM_QUERYOPEN
, sent
|optional
},
575 { WM_GETTEXT
, sent
|optional
},
576 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
577 { WM_WINDOWPOSCHANGING
, sent
|optional
}, /* SWP_NOSIZE|SWP_NOMOVE */
578 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
579 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
580 { WM_MOVE
, sent
|optional
},
581 { WM_SIZE
, sent
|wparam
|optional
, SIZE_RESTORED
},
582 { WM_GETTEXT
, sent
|optional
},
583 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
|SWP_NOCOPYBITS
},
584 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
},
585 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
586 { HCBT_ACTIVATE
, hook
|optional
},
587 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
588 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
589 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
590 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
591 { WM_GETTEXT
, sent
|defwinproc
|optional
},
592 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
593 { HCBT_SETFOCUS
, hook
|optional
},
594 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
595 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
596 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
597 { WM_GETTEXT
, sent
|optional
},
598 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
599 { WM_GETTEXT
, sent
|defwinproc
|optional
},
600 { WM_ERASEBKGND
, sent
},
601 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_STATECHANGED
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
},
602 { WM_MOVE
, sent
|defwinproc
},
603 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
604 { HCBT_SETFOCUS
, hook
|optional
},
605 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
606 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
607 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
608 { WM_ERASEBKGND
, sent
|optional
},
609 { HCBT_SETFOCUS
, hook
|optional
},
610 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
611 { WM_ACTIVATE
, sent
|wparam
, 1 },
612 { WM_GETTEXT
, sent
|optional
},
613 { WM_PAINT
, sent
|optional
},
614 { WM_GETTITLEBARINFOEX
, sent
|optional
},
615 { WM_NCPAINT
, sent
|beginpaint
|optional
},
616 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
619 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
620 static const struct message WmShowMinOverlappedSeq
[] = {
621 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
622 { HCBT_SETFOCUS
, hook
|optional
},
623 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
624 { WM_KILLFOCUS
, sent
|optional
},
625 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
626 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
627 { WM_GETTEXT
, sent
|optional
},
628 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCOPYBITS
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
629 { WM_GETMINMAXINFO
, sent
|defwinproc
},
630 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
631 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
632 { WM_NCPAINT
, sent
|optional
},
633 { WM_GETTEXT
, sent
|defwinproc
|optional
},
634 { WM_WINDOWPOSCHANGED
, sent
},
635 { WM_MOVE
, sent
|defwinproc
},
636 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
637 { WM_NCCALCSIZE
, sent
|optional
},
638 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
639 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
640 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
641 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
642 { WM_GETTEXT
, sent
|defwinproc
|optional
},
643 { WM_ACTIVATE
, sent
|optional
},
644 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
646 /* Vista sometimes restores the window right away... */
647 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
648 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
649 { HCBT_MINMAX
, hook
|optional
|lparam
, 0, SW_RESTORE
},
650 { WM_QUERYOPEN
, sent
|optional
},
651 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
652 { WM_GETMINMAXINFO
, sent
|optional
|defwinproc
},
653 { WM_NCCALCSIZE
, sent
|optional
|wparam
, TRUE
},
654 { HCBT_ACTIVATE
, hook
|optional
},
655 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 1 },
656 { WM_NCACTIVATE
, sent
|optional
},
657 { WM_GETTEXT
, sent
|optional
},
658 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
659 { HCBT_SETFOCUS
, hook
|optional
},
660 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
661 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
662 { WM_SETFOCUS
, sent
|optional
},
663 { WM_NCPAINT
, sent
|optional
},
664 { WM_GETTEXT
, sent
|defwinproc
|optional
},
665 { WM_ERASEBKGND
, sent
|optional
},
666 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
667 { WM_MOVE
, sent
|defwinproc
|optional
},
668 { WM_SIZE
, sent
|defwinproc
|optional
|wparam
, SIZE_RESTORED
},
669 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
670 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
671 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
673 { WM_PAINT
, sent
|optional
},
674 { WM_NCPAINT
, sent
|beginpaint
|optional
},
675 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
678 /* ShowWindow(SW_HIDE) for a visible overlapped window */
679 static const struct message WmHideOverlappedSeq
[] = {
680 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
681 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
682 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
683 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
684 { WM_SIZE
, sent
|optional
}, /* XP doesn't send it */
685 { WM_MOVE
, sent
|optional
}, /* XP doesn't send it */
686 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
687 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
688 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
689 { HCBT_SETFOCUS
, hook
|optional
},
690 { WM_KILLFOCUS
, sent
|wparam
|optional
, 0 },
691 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
692 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
695 /* DestroyWindow for a visible overlapped window */
696 static const struct message WmDestroyOverlappedSeq
[] = {
697 { HCBT_DESTROYWND
, hook
},
698 { 0x0090, sent
|optional
},
699 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
700 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
701 { 0x0090, sent
|optional
},
702 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
703 { WM_NCACTIVATE
, sent
|optional
|wparam
, 0 },
704 { WM_ACTIVATE
, sent
|optional
},
705 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 0 },
706 { WM_KILLFOCUS
, sent
|optional
|wparam
, 0 },
707 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
708 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
709 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
710 { WM_DESTROY
, sent
},
711 { WM_NCDESTROY
, sent
},
714 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
715 static const struct message WmCreateMaxPopupSeq
[] = {
716 { HCBT_CREATEWND
, hook
},
717 { WM_NCCREATE
, sent
},
718 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
720 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
721 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
723 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
724 { WM_GETMINMAXINFO
, sent
},
725 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
726 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
727 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
728 { WM_MOVE
, sent
|defwinproc
},
729 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
730 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
731 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
732 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
733 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
734 { HCBT_ACTIVATE
, hook
},
735 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
736 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
737 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
738 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
739 { WM_ERASEBKGND
, sent
|optional
},
740 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_NOMOVE
|SWP_NOSIZE
},
741 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
742 { WM_NCACTIVATE
, sent
},
743 { WM_ACTIVATE
, sent
|wparam
, 1 },
744 { HCBT_SETFOCUS
, hook
},
745 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
746 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
747 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
748 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
749 { WM_GETTEXT
, sent
|optional
},
750 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
751 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
752 { WM_ERASEBKGND
, sent
|optional
},
753 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
754 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
755 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
758 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
759 static const struct message WmCreateInvisibleMaxPopupSeq
[] = {
760 { HCBT_CREATEWND
, hook
},
761 { WM_NCCREATE
, sent
},
762 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
764 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
765 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
767 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
768 { WM_GETMINMAXINFO
, sent
},
769 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
770 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
771 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
772 { WM_MOVE
, sent
|defwinproc
},
773 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
774 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
777 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
778 static const struct message WmShowMaxPopupResizedSeq_todo
[] = {
779 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
780 { WM_GETMINMAXINFO
, sent
},
781 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
782 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
783 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
784 { HCBT_ACTIVATE
, hook
},
785 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
786 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
787 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
788 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
789 { WM_ERASEBKGND
, sent
|optional
},
790 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
791 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
792 { WM_NCACTIVATE
, sent
},
793 { WM_ACTIVATE
, sent
|wparam
, 1 },
794 { HCBT_SETFOCUS
, hook
},
795 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
796 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
797 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
798 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
799 { WM_GETTEXT
, sent
|optional
},
800 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
801 { WM_ERASEBKGND
, sent
|optional
},
802 { WM_WINDOWPOSCHANGED
, sent
},
803 /* WinNT4.0 sends WM_MOVE */
804 { WM_MOVE
, sent
|defwinproc
|optional
},
805 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
806 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
809 static const struct message WmShowMaxPopupResizedSeq
[] = {
810 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
811 { WM_GETMINMAXINFO
, sent
},
812 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
813 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
814 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
815 { HCBT_ACTIVATE
, hook
},
816 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
817 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
818 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
819 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
820 { WM_ERASEBKGND
, sent
|optional
},
821 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
822 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
823 { WM_NCACTIVATE
, sent
},
824 { WM_ACTIVATE
, sent
|wparam
, 1 },
825 { HCBT_SETFOCUS
, hook
},
826 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
827 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
828 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
829 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
830 { WM_GETTEXT
, sent
|optional
},
831 { WM_NCPAINT
, sent
|optional
}, /* We'll check WM_NCPAINT behaviour in another test */
832 { WM_ERASEBKGND
, sent
|optional
},
833 { WM_WINDOWPOSCHANGED
, sent
},
834 /* WinNT4.0 sends WM_MOVE */
835 { WM_MOVE
, sent
|defwinproc
|optional
},
836 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
837 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
840 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
841 static const struct message WmShowMaxPopupSeq
[] = {
842 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
843 { WM_GETMINMAXINFO
, sent
},
844 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
845 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
846 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
847 { HCBT_ACTIVATE
, hook
},
848 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
849 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
850 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
851 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
852 { WM_ERASEBKGND
, sent
|optional
},
853 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOMOVE
|SWP_NOSIZE
},
854 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
855 { WM_NCACTIVATE
, sent
},
856 { WM_ACTIVATE
, sent
|wparam
, 1 },
857 { HCBT_SETFOCUS
, hook
},
858 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
859 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
860 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
861 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
862 { WM_GETTEXT
, sent
|optional
},
863 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
864 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
865 { WM_ERASEBKGND
, sent
|optional
},
866 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
867 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
868 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
},
869 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
872 /* CreateWindow(WS_VISIBLE) for popup window */
873 static const struct message WmCreatePopupSeq
[] = {
874 { HCBT_CREATEWND
, hook
},
875 { WM_NCCREATE
, sent
},
876 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
878 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
879 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
881 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
882 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
883 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
884 { HCBT_ACTIVATE
, hook
},
885 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
886 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
887 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
888 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
889 { WM_ERASEBKGND
, sent
|optional
},
890 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
891 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
892 { WM_NCACTIVATE
, sent
},
893 { WM_ACTIVATE
, sent
|wparam
, 1 },
894 { HCBT_SETFOCUS
, hook
},
895 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
896 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
897 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
898 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
899 { WM_GETTEXT
, sent
|optional
},
900 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
901 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
902 { WM_ERASEBKGND
, sent
|optional
},
903 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
906 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
907 static const struct message WmShowVisMaxPopupSeq
[] = {
908 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
909 { WM_GETMINMAXINFO
, sent
},
910 { WM_GETTEXT
, sent
|optional
},
911 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
912 { WM_GETTEXT
, sent
|optional
},
913 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
914 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
915 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
916 { WM_ERASEBKGND
, sent
|optional
},
917 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
918 { WM_MOVE
, sent
|defwinproc
},
919 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
920 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
923 /* CreateWindow (for a child popup window, not initially visible) */
924 static const struct message WmCreateChildPopupSeq
[] = {
925 { HCBT_CREATEWND
, hook
},
926 { WM_NCCREATE
, sent
},
927 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
929 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
930 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
934 /* CreateWindow (for a popup window, not initially visible,
935 * which sets WS_VISIBLE in WM_CREATE handler)
937 static const struct message WmCreateInvisiblePopupSeq
[] = {
938 { HCBT_CREATEWND
, hook
},
939 { WM_NCCREATE
, sent
},
940 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
942 { WM_STYLECHANGING
, sent
},
943 { WM_STYLECHANGED
, sent
},
944 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
945 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
949 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
950 * for a popup window with WS_VISIBLE style set
952 static const struct message WmShowVisiblePopupSeq_2
[] = {
953 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
956 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
957 * for a popup window with WS_VISIBLE style set
959 static const struct message WmShowVisiblePopupSeq_3
[] = {
960 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
961 { HCBT_ACTIVATE
, hook
},
962 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
963 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
964 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
965 { WM_NCACTIVATE
, sent
},
966 { WM_ACTIVATE
, sent
|wparam
, 1 },
967 { HCBT_SETFOCUS
, hook
},
968 { WM_KILLFOCUS
, sent
|parent
},
969 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
970 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
971 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
972 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
973 { WM_SETFOCUS
, sent
|defwinproc
},
974 { WM_GETTEXT
, sent
|optional
},
975 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_SHOWWINDOW
},
978 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
980 static const struct message WmShowPopupExtremeLocationSeq
[] = {
981 { HCBT_CREATEWND
, hook
},
982 { WM_NCCREATE
, sent
},
983 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
985 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
986 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
988 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
989 { WM_WINDOWPOSCHANGING
, sent
},
990 { HCBT_ACTIVATE
, hook
},
991 { WM_WINDOWPOSCHANGING
, sent
|optional
},
992 { WM_QUERYNEWPALETTE
, sent
|optional
},
993 { WM_ACTIVATEAPP
, sent
},
994 { WM_NCACTIVATE
, sent
},
995 { WM_ACTIVATE
, sent
},
996 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
997 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
998 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
999 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1000 { HCBT_SETFOCUS
, hook
},
1001 { WM_SETFOCUS
, sent
|defwinproc
},
1002 { WM_NCPAINT
, sent
|wparam
, 1 },
1003 { WM_ERASEBKGND
, sent
},
1004 { WM_WINDOWPOSCHANGED
, sent
},
1005 /* occasionally received on test machines */
1006 { WM_NCPAINT
, sent
|optional
},
1007 { WM_ERASEBKGND
, sent
|optional
},
1010 /* CreateWindow (for a popup window with WS_VISIBLE style set)
1012 static const struct message WmShowPopupFirstDrawSeq_1
[] = {
1013 { HCBT_CREATEWND
, hook
},
1014 { WM_NCCREATE
, sent
},
1015 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1016 { WM_CREATE
, sent
},
1017 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1018 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1020 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1021 { WM_WINDOWPOSCHANGING
, sent
},
1022 { HCBT_ACTIVATE
, hook
},
1023 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1024 { WM_QUERYNEWPALETTE
, sent
|optional
},
1025 { WM_ACTIVATEAPP
, sent
},
1026 { WM_NCACTIVATE
, sent
},
1027 { WM_ACTIVATE
, sent
},
1028 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1029 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1030 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1031 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1032 { HCBT_SETFOCUS
, hook
},
1033 { WM_SETFOCUS
, sent
|defwinproc
},
1034 { WM_NCPAINT
, sent
|wparam
, 1 },
1035 { WM_ERASEBKGND
, sent
},
1036 { WM_WINDOWPOSCHANGED
, sent
},
1038 /* occasionally received on test machines */
1039 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1040 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1043 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1045 static const struct message WmShowPopupFirstDrawSeq_2
[] = {
1046 { HCBT_CREATEWND
, hook
},
1047 { WM_NCCREATE
, sent
},
1048 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1049 { WM_CREATE
, sent
},
1050 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1051 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1053 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1054 { WM_GETMINMAXINFO
, sent
},
1055 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_STATECHANGED
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
1056 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
1057 { HCBT_ACTIVATE
, hook
},
1058 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1059 { WM_NCPAINT
, sent
|optional
|wparam
, 1 },
1060 { WM_ERASEBKGND
, sent
|optional
},
1061 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1062 { WM_QUERYNEWPALETTE
, sent
|optional
},
1063 { WM_ACTIVATEAPP
, sent
},
1064 { WM_NCACTIVATE
, sent
},
1065 { WM_ACTIVATE
, sent
},
1066 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1067 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1068 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1069 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1070 { HCBT_SETFOCUS
, hook
},
1071 { WM_SETFOCUS
, sent
|defwinproc
},
1072 { WM_NCPAINT
, sent
|wparam
, 1 },
1073 { WM_ERASEBKGND
, sent
},
1074 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1075 { WM_MOVE
, sent
|defwinproc
},
1076 { WM_SIZE
, sent
|defwinproc
, 0 },
1078 /* occasionally received on test machines */
1079 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1080 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1083 static const struct message WmFirstDrawSetWindowPosSeq1
[] = {
1084 { HCBT_CREATEWND
, hook
},
1085 { WM_NCCREATE
, sent
},
1086 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1087 { WM_CREATE
, sent
},
1088 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1089 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1091 { WM_WINDOWPOSCHANGING
, sent
},
1092 { HCBT_ACTIVATE
, hook
},
1093 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1094 { WM_QUERYNEWPALETTE
, sent
|optional
},
1095 { WM_ACTIVATEAPP
, sent
},
1096 { WM_NCACTIVATE
, sent
},
1097 { WM_ACTIVATE
, sent
},
1098 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1099 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1100 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1101 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1102 { HCBT_SETFOCUS
, hook
},
1103 { WM_SETFOCUS
, sent
|defwinproc
},
1104 { WM_NCPAINT
, sent
|wparam
, 1 },
1105 { WM_ERASEBKGND
, sent
},
1106 { WM_WINDOWPOSCHANGED
, sent
},
1107 { WM_MOVE
, sent
|defwinproc
},
1110 static const struct message WmFirstDrawSetWindowPosSeq2
[] = {
1111 { HCBT_CREATEWND
, hook
},
1112 { WM_NCCREATE
, sent
},
1113 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1114 { WM_CREATE
, sent
},
1115 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1116 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1118 { WM_WINDOWPOSCHANGING
, sent
},
1119 { HCBT_ACTIVATE
, hook
},
1120 { WM_QUERYNEWPALETTE
, sent
|optional
},
1121 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1122 { WM_ACTIVATEAPP
, sent
},
1123 { WM_NCACTIVATE
, sent
},
1124 { WM_ACTIVATE
, sent
},
1125 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1126 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1127 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1128 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1129 { HCBT_SETFOCUS
, hook
},
1130 { WM_SETFOCUS
, sent
|defwinproc
},
1131 { WM_WINDOWPOSCHANGED
, sent
},
1132 { WM_MOVE
, sent
|defwinproc
},
1135 static const struct message WmFirstDrawSetWindowPosSeq3
[] = {
1136 { HCBT_CREATEWND
, hook
},
1137 { WM_NCCREATE
, sent
},
1138 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1139 { WM_CREATE
, sent
},
1140 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1141 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1143 { HCBT_ACTIVATE
, hook
|optional
},
1144 /* Probably shouldn't happen, but not part of this test */
1145 { WM_QUERYNEWPALETTE
, sent
|optional
},
1146 { WM_ACTIVATEAPP
, sent
|optional
},
1147 { WM_NCACTIVATE
, sent
|optional
},
1148 { WM_ACTIVATE
, sent
|optional
},
1149 { HCBT_SETFOCUS
, hook
|optional
},
1150 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
1153 static const struct message WmFirstDrawSetWindowPosSeq4
[] = {
1154 { HCBT_CREATEWND
, hook
},
1155 { WM_NCCREATE
, sent
},
1156 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1157 { WM_CREATE
, sent
},
1158 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1159 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1161 { WM_WINDOWPOSCHANGING
, sent
},
1162 { HCBT_ACTIVATE
, hook
},
1163 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1164 { WM_QUERYNEWPALETTE
, sent
|optional
},
1165 { WM_ACTIVATEAPP
, sent
},
1166 { WM_NCACTIVATE
, sent
},
1167 { WM_ACTIVATE
, sent
},
1168 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1169 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1170 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1171 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1172 { HCBT_SETFOCUS
, hook
},
1173 { WM_SETFOCUS
, sent
|defwinproc
},
1174 { WM_NCPAINT
, sent
|wparam
, 1 },
1175 { WM_ERASEBKGND
, sent
},
1176 { WM_WINDOWPOSCHANGED
, sent
},
1179 static const struct message WmFirstDrawSetWindowPosSeq5
[] = {
1180 { HCBT_CREATEWND
, hook
},
1181 { WM_NCCREATE
, sent
},
1182 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1183 { WM_CREATE
, sent
},
1184 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1185 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1187 { WM_WINDOWPOSCHANGING
, sent
},
1188 { HCBT_ACTIVATE
, hook
},
1189 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1190 { WM_QUERYNEWPALETTE
, sent
|optional
},
1191 { WM_ACTIVATEAPP
, sent
},
1192 { WM_NCACTIVATE
, sent
},
1193 { WM_ACTIVATE
, sent
},
1194 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1195 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1196 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1197 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1198 { HCBT_SETFOCUS
, hook
},
1199 { WM_SETFOCUS
, sent
|defwinproc
},
1200 { WM_WINDOWPOSCHANGED
, sent
},
1203 static const struct message WmFirstDrawChildSeq1
[] = {
1206 static const struct message WmFirstDrawChildSeq2
[] = {
1207 { WM_NCPAINT
, sent
|wparam
, 1 },
1208 { WM_ERASEBKGND
, sent
},
1209 /* occasionally received on test machines */
1210 { WM_NCPAINT
, sent
|optional
},
1211 { WM_ERASEBKGND
, sent
|optional
},
1214 /* CreateWindow (for child window, not initially visible) */
1215 static const struct message WmCreateChildSeq
[] = {
1216 { HCBT_CREATEWND
, hook
},
1217 { WM_NCCREATE
, sent
},
1218 /* child is inserted into parent's child list after WM_NCCREATE returns */
1219 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1220 { WM_CREATE
, sent
},
1221 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1222 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1224 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1227 /* CreateWindow (for maximized child window, not initially visible) */
1228 static const struct message WmCreateMaximizedChildSeq
[] = {
1229 { HCBT_CREATEWND
, hook
},
1230 { WM_NCCREATE
, sent
},
1231 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1232 { WM_CREATE
, sent
},
1233 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1234 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1236 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1237 { WM_GETMINMAXINFO
, sent
},
1238 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
1239 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1240 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1241 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1242 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1243 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1246 /* CreateWindow (for a child window, initially visible) */
1247 static const struct message WmCreateVisibleChildSeq
[] = {
1248 { HCBT_CREATEWND
, hook
},
1249 { WM_NCCREATE
, sent
},
1250 /* child is inserted into parent's child list after WM_NCCREATE returns */
1251 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1252 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1253 { WM_CREATE
, sent
},
1254 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1255 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1257 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1258 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1259 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1260 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1261 { WM_ERASEBKGND
, sent
|parent
|optional
},
1262 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1263 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
1264 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1267 /* ShowWindow(SW_SHOW) for a not visible child window */
1268 static const struct message WmShowChildSeq
[] = {
1269 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1270 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1271 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1272 { WM_ERASEBKGND
, sent
|parent
|optional
},
1273 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1276 /* ShowWindow(SW_HIDE) for a visible child window */
1277 static const struct message WmHideChildSeq
[] = {
1278 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1279 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1280 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1281 { WM_ERASEBKGND
, sent
|parent
|optional
},
1282 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1285 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1286 static const struct message WmHideChildSeq2
[] = {
1287 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1288 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1289 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1290 { WM_ERASEBKGND
, sent
|parent
|optional
},
1291 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1294 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1295 * for a not visible child window
1297 static const struct message WmShowChildSeq_2
[] = {
1298 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1299 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1300 { WM_CHILDACTIVATE
, sent
},
1301 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1304 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1305 * for a not visible child window
1307 static const struct message WmShowChildSeq_3
[] = {
1308 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1309 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1310 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1313 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1314 * for a visible child window with a caption
1316 static const struct message WmShowChildSeq_4
[] = {
1317 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1318 { WM_CHILDACTIVATE
, sent
},
1321 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1322 static const struct message WmShowChildInvisibleParentSeq_1
[] = {
1323 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1324 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1325 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1326 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1327 { WM_CHILDACTIVATE
, sent
|optional
},
1328 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1329 { WM_MOVE
, sent
|defwinproc
},
1330 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1331 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1332 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1333 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1334 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1335 { WM_GETTEXT
, sent
|optional
},
1338 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1339 static const struct message WmShowChildInvisibleParentSeq_1r
[] = {
1340 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1343 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1344 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
1345 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1346 { WM_GETMINMAXINFO
, sent
},
1347 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
1348 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1349 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1350 { WM_CHILDACTIVATE
, sent
},
1351 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1352 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1353 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1356 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1357 static const struct message WmShowChildInvisibleParentSeq_2r
[] = {
1358 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1361 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1362 static const struct message WmShowChildInvisibleParentSeq_3
[] = {
1363 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1364 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1365 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1366 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1367 { WM_CHILDACTIVATE
, sent
},
1368 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1369 { WM_MOVE
, sent
|defwinproc
},
1370 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1371 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1372 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1373 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1374 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1375 { WM_GETTEXT
, sent
|optional
},
1378 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1379 static const struct message WmShowChildInvisibleParentSeq_3r
[] = {
1380 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1383 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1384 static const struct message WmShowChildInvisibleParentSeq_4
[] = {
1385 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1386 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1387 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1388 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1389 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1390 { WM_MOVE
, sent
|defwinproc
},
1391 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1392 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1393 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1394 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1395 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1396 { WM_GETTEXT
, sent
|optional
},
1399 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1400 static const struct message WmShowChildInvisibleParentSeq_4r
[] = {
1401 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1404 /* ShowWindow(SW_SHOW) for child with invisible parent */
1405 static const struct message WmShowChildInvisibleParentSeq_5
[] = {
1406 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1409 /* ShowWindow(SW_HIDE) for child with invisible parent */
1410 static const struct message WmHideChildInvisibleParentSeq
[] = {
1411 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1414 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1415 static const struct message WmShowChildInvisibleParentSeq_6
[] = {
1416 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1417 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1418 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1421 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1422 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
1423 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1424 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1425 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1428 /* DestroyWindow for a visible child window */
1429 static const struct message WmDestroyChildSeq
[] = {
1430 { HCBT_DESTROYWND
, hook
},
1431 { 0x0090, sent
|optional
},
1432 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1433 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1434 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1435 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1436 { WM_ERASEBKGND
, sent
|parent
|optional
},
1437 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1438 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
1439 { WM_KILLFOCUS
, sent
},
1440 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1441 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
1442 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1443 { WM_SETFOCUS
, sent
|parent
},
1444 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1445 { WM_DESTROY
, sent
},
1446 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
1447 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
1448 { WM_NCDESTROY
, sent
},
1451 /* visible child window destroyed by thread exit */
1452 static const struct message WmExitThreadSeq
[] = {
1453 { WM_NCDESTROY
, sent
}, /* actually in grandchild */
1454 { WM_PAINT
, sent
|parent
},
1455 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
1458 /* DestroyWindow for a visible child window with invisible parent */
1459 static const struct message WmDestroyInvisibleChildSeq
[] = {
1460 { HCBT_DESTROYWND
, hook
},
1461 { 0x0090, sent
|optional
},
1462 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1463 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1464 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1465 { WM_DESTROY
, sent
},
1466 { WM_NCDESTROY
, sent
},
1469 /* Resizing child window with MoveWindow (32) */
1470 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1471 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1472 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1473 { WM_ERASEBKGND
, sent
|parent
|optional
},
1474 { WM_ERASEBKGND
, sent
|optional
},
1475 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1476 { WM_MOVE
, sent
|defwinproc
},
1477 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1478 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1481 /* Creation of a custom dialog (32) */
1482 static const struct message WmCreateCustomDialogSeq
[] = {
1483 { HCBT_CREATEWND
, hook
},
1484 { WM_GETMINMAXINFO
, sent
},
1485 { WM_NCCREATE
, sent
},
1486 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1487 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1488 { WM_CREATE
, sent
},
1489 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1490 { WM_NOTIFYFORMAT
, sent
|optional
},
1491 { WM_QUERYUISTATE
, sent
|optional
},
1492 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1493 { WM_GETMINMAXINFO
, sent
|optional
},
1494 { WM_NCCALCSIZE
, sent
|optional
},
1495 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1496 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1497 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1498 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1499 { HCBT_ACTIVATE
, hook
},
1500 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1503 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1505 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1507 { WM_NCACTIVATE
, sent
},
1508 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1509 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1510 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1511 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1512 { WM_ACTIVATE
, sent
|wparam
, 1 },
1513 { WM_GETTEXT
, sent
|optional
},
1514 { WM_KILLFOCUS
, sent
|parent
},
1515 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1516 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1517 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1518 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1519 { WM_SETFOCUS
, sent
},
1520 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1521 { WM_NCPAINT
, sent
|wparam
, 1 },
1522 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1523 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1524 { WM_ERASEBKGND
, sent
},
1525 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1526 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1527 { WM_GETTEXT
, sent
|optional
},
1528 { WM_GETTEXT
, sent
|optional
},
1529 { WM_NCCALCSIZE
, sent
|optional
},
1530 { WM_NCPAINT
, sent
|optional
},
1531 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1532 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1533 { WM_ERASEBKGND
, sent
|optional
},
1534 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1535 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1536 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1540 /* Calling EndDialog for a custom dialog (32) */
1541 static const struct message WmEndCustomDialogSeq
[] = {
1542 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1543 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1544 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1545 { WM_GETTEXT
, sent
|optional
},
1546 { HCBT_ACTIVATE
, hook
},
1547 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1548 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1549 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1550 { WM_ACTIVATE
, sent
|wparam
, 0 },
1551 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1552 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1553 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1554 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1555 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1556 { HCBT_SETFOCUS
, hook
},
1557 { WM_KILLFOCUS
, sent
},
1558 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1559 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1560 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1561 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1562 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1565 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1566 static const struct message WmShowCustomDialogSeq
[] = {
1567 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1568 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1569 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1570 { HCBT_ACTIVATE
, hook
},
1571 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1573 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1575 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1576 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1577 { WM_NCACTIVATE
, sent
},
1578 { WM_ACTIVATE
, sent
|wparam
, 1 },
1579 { WM_GETTEXT
, sent
|optional
},
1581 { WM_KILLFOCUS
, sent
|parent
},
1582 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1583 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1584 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1585 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1586 { WM_SETFOCUS
, sent
},
1587 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1588 { WM_NCPAINT
, sent
|wparam
, 1 },
1589 { WM_ERASEBKGND
, sent
},
1590 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1591 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1594 /* Creation and destruction of a modal dialog (32) */
1595 static const struct message WmModalDialogSeq
[] = {
1596 { WM_CANCELMODE
, sent
|parent
},
1597 { HCBT_SETFOCUS
, hook
},
1598 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1599 { WM_KILLFOCUS
, sent
|parent
},
1600 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1601 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1602 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1603 { HCBT_CREATEWND
, hook
},
1604 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1605 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1606 { WM_SETFONT
, sent
},
1607 { WM_INITDIALOG
, sent
},
1608 { WM_CHANGEUISTATE
, sent
|optional
},
1609 { WM_UPDATEUISTATE
, sent
|optional
},
1610 { WM_SHOWWINDOW
, sent
},
1611 { HCBT_ACTIVATE
, hook
},
1612 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1613 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1614 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1615 { WM_NCACTIVATE
, sent
},
1616 { WM_GETTEXT
, sent
|optional
},
1617 { WM_ACTIVATE
, sent
|wparam
, 1 },
1618 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1619 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1620 { WM_NCPAINT
, sent
|optional
},
1621 { WM_GETTEXT
, sent
|optional
},
1622 { WM_ERASEBKGND
, sent
|optional
},
1623 { WM_CTLCOLORDLG
, sent
|optional
},
1624 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1625 { WM_GETTEXT
, sent
|optional
},
1626 { WM_NCCALCSIZE
, sent
|optional
},
1627 { WM_NCPAINT
, sent
|optional
},
1628 { WM_GETTEXT
, sent
|optional
},
1629 { WM_ERASEBKGND
, sent
|optional
},
1630 { WM_CTLCOLORDLG
, sent
|optional
},
1631 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1632 { WM_PAINT
, sent
|optional
},
1633 { WM_CTLCOLORBTN
, sent
|optional
},
1634 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1635 { WM_ENTERIDLE
, sent
|parent
|optional
},
1636 { WM_ENTERIDLE
, sent
|parent
|optional
},
1637 { WM_ENTERIDLE
, sent
|parent
|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
},
1656 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1657 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1658 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1659 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1660 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1661 { WM_GETTEXT
, sent
|optional
},
1662 { HCBT_ACTIVATE
, hook
},
1663 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1664 { WM_GETTEXT
, sent
|optional
},
1665 { WM_ACTIVATE
, sent
|wparam
, 0 },
1666 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1667 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1668 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1669 { HCBT_SETFOCUS
, hook
},
1670 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1671 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1672 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1673 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1674 { HCBT_DESTROYWND
, hook
},
1675 { 0x0090, sent
|optional
},
1676 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1677 { WM_DESTROY
, sent
},
1678 { WM_NCDESTROY
, sent
},
1681 static const struct message WmModalDialogSeq_2
[] = {
1682 { WM_CANCELMODE
, sent
},
1683 { HCBT_SETFOCUS
, hook
},
1684 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1685 { WM_KILLFOCUS
, sent
},
1686 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1687 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1688 { WM_ENABLE
, sent
|wparam
, 0 },
1689 { HCBT_CREATEWND
, hook
},
1690 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1691 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1692 { WM_SETFONT
, sent
},
1693 { WM_INITDIALOG
, sent
},
1694 { WM_CHANGEUISTATE
, sent
|optional
},
1695 { WM_UPDATEUISTATE
, sent
|optional
},
1696 { WM_ENABLE
, sent
|wparam
, 1 },
1697 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1698 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1699 { WM_CHANGEUISTATE
, sent
|optional
},
1700 { WM_UPDATEUISTATE
, sent
|optional
},
1701 { HCBT_DESTROYWND
, hook
},
1702 { 0x0090, sent
|optional
},
1703 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1704 { WM_DESTROY
, sent
},
1705 { WM_NCDESTROY
, sent
},
1708 /* SetMenu for NonVisible windows with size change*/
1709 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1710 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1711 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1712 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1713 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1714 { WM_MOVE
, sent
|defwinproc
},
1715 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1716 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1717 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1718 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1719 { WM_GETTEXT
, sent
|optional
},
1720 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1723 /* SetMenu for NonVisible windows with no size change */
1724 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1725 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1726 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1727 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1728 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1731 /* SetMenu for Visible windows with size change */
1732 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1733 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1734 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1735 { 0x0093, sent
|defwinproc
|optional
},
1736 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1737 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1738 { 0x0093, sent
|defwinproc
|optional
},
1739 { 0x0093, sent
|defwinproc
|optional
},
1740 { 0x0091, sent
|defwinproc
|optional
},
1741 { 0x0092, sent
|defwinproc
|optional
},
1742 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1743 { WM_ERASEBKGND
, sent
|optional
},
1744 { WM_ACTIVATE
, sent
|optional
},
1745 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1746 { WM_MOVE
, sent
|defwinproc
},
1747 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1748 { 0x0093, sent
|optional
},
1749 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1750 { 0x0093, sent
|defwinproc
|optional
},
1751 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1752 { 0x0093, sent
|defwinproc
|optional
},
1753 { 0x0093, sent
|defwinproc
|optional
},
1754 { 0x0091, sent
|defwinproc
|optional
},
1755 { 0x0092, sent
|defwinproc
|optional
},
1756 { WM_ERASEBKGND
, sent
|optional
},
1757 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1758 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1761 /* SetMenu for Visible windows with no size change */
1762 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1763 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1764 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1765 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1766 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1767 { WM_ERASEBKGND
, sent
|optional
},
1768 { WM_ACTIVATE
, sent
|optional
},
1769 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1770 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1773 /* DrawMenuBar for a visible window */
1774 static const struct message WmDrawMenuBarSeq
[] =
1776 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1777 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1778 { 0x0093, sent
|defwinproc
|optional
},
1779 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1780 { 0x0093, sent
|defwinproc
|optional
},
1781 { 0x0093, sent
|defwinproc
|optional
},
1782 { 0x0091, sent
|defwinproc
|optional
},
1783 { 0x0092, sent
|defwinproc
|optional
},
1784 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1785 { WM_ERASEBKGND
, sent
|optional
},
1786 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1787 { 0x0093, sent
|optional
},
1788 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1792 static const struct message WmSetRedrawFalseSeq
[] =
1794 { WM_SETREDRAW
, sent
|wparam
, 0 },
1798 static const struct message WmSetRedrawTrueSeq
[] =
1800 { WM_SETREDRAW
, sent
|wparam
, 1 },
1804 static const struct message WmEnableWindowSeq_1
[] =
1806 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1807 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1808 { HCBT_SETFOCUS
, hook
|optional
},
1809 { WM_KILLFOCUS
, sent
|optional
},
1810 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
1814 static const struct message WmEnableWindowSeq_2
[] =
1816 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1817 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1821 static const struct message WmEnableWindowSeq_3
[] =
1823 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1824 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
1828 static const struct message WmEnableWindowSeq_4
[] =
1830 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1834 static const struct message WmGetScrollRangeSeq
[] =
1836 { SBM_GETRANGE
, sent
},
1839 static const struct message WmGetScrollInfoSeq
[] =
1841 { SBM_GETSCROLLINFO
, sent
},
1844 static const struct message WmSetScrollRangeSeq
[] =
1846 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1847 sends SBM_SETSCROLLINFO.
1849 { SBM_SETSCROLLINFO
, sent
},
1852 /* SetScrollRange for a window without a non-client area */
1853 static const struct message WmSetScrollRangeHSeq_empty
[] =
1855 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 0 },
1858 static const struct message WmSetScrollRangeVSeq_empty
[] =
1860 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 0 },
1863 static const struct message WmSetScrollRangeHVSeq
[] =
1865 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1866 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1867 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1868 { WM_ERASEBKGND
, sent
|optional
},
1869 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1870 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1871 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1874 /* SetScrollRange for a window with a non-client area */
1875 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
1877 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1878 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1879 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1880 { WM_NCPAINT
, sent
|optional
},
1881 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1882 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1883 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1884 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1885 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1886 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1887 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1888 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1889 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1890 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1891 { WM_ERASEBKGND
, sent
|optional
},
1892 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
1893 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
1894 { WM_SIZE
, sent
|defwinproc
|optional
},
1895 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1896 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1897 { WM_GETTEXT
, sent
|optional
},
1898 { WM_GETTEXT
, sent
|optional
},
1899 { WM_GETTEXT
, sent
|optional
},
1900 { WM_GETTEXT
, sent
|optional
},
1903 /* test if we receive the right sequence of messages */
1904 /* after calling ShowWindow( SW_SHOWNA) */
1905 static const struct message WmSHOWNAChildInvisParInvis
[] = {
1906 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1909 static const struct message WmSHOWNAChildVisParInvis
[] = {
1910 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1913 static const struct message WmSHOWNAChildVisParVis
[] = {
1914 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1915 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1918 static const struct message WmSHOWNAChildInvisParVis
[] = {
1919 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1920 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1921 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1922 { WM_ERASEBKGND
, sent
|optional
},
1923 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
1926 static const struct message WmSHOWNATopVisible
[] = {
1927 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1928 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1929 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1930 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1931 { WM_ERASEBKGND
, sent
|optional
},
1932 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1935 static const struct message WmSHOWNATopInvisible
[] = {
1936 { WM_NOTIFYFORMAT
, sent
|optional
},
1937 { WM_QUERYUISTATE
, sent
|optional
},
1938 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1939 { WM_GETMINMAXINFO
, sent
|optional
},
1940 { WM_NCCALCSIZE
, sent
|optional
},
1941 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1942 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1943 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1944 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1945 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1946 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1947 { WM_ERASEBKGND
, sent
|optional
},
1948 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1949 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1950 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1951 { WM_ERASEBKGND
, sent
|optional
},
1952 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1953 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1958 static const struct message WmTrackPopupMenu
[] = {
1959 { HCBT_CREATEWND
, hook
},
1960 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1961 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1962 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1963 { 0x0093, sent
|optional
},
1964 { 0x0094, sent
|optional
},
1965 { 0x0094, sent
|optional
},
1966 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1967 { WM_CAPTURECHANGED
, sent
},
1968 { HCBT_DESTROYWND
, hook
},
1969 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1970 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1971 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1975 static const struct message WmTrackPopupMenuEsc
[] = {
1979 static const struct message WmTrackPopupMenuCapture
[] = {
1980 { HCBT_CREATEWND
, hook
},
1981 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1982 { WM_CAPTURECHANGED
, sent
},
1983 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1984 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1985 { 0x0093, sent
|optional
},
1986 { 0x0094, sent
|optional
},
1987 { 0x0094, sent
|optional
},
1988 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1989 { WM_CAPTURECHANGED
, sent
},
1990 { HCBT_DESTROYWND
, hook
},
1991 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1992 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1993 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1997 static const struct message WmTrackPopupMenuEmpty
[] = {
1998 { HCBT_CREATEWND
, hook
},
1999 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2000 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2001 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2002 { 0x0093, sent
|optional
},
2003 { 0x0094, sent
|optional
},
2004 { 0x0094, sent
|optional
},
2005 { WM_CAPTURECHANGED
, sent
},
2006 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2007 { HCBT_DESTROYWND
, hook
},
2008 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2012 static const struct message WmTrackPopupMenuAbort
[] = {
2013 { HCBT_CREATEWND
, hook
},
2014 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2015 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2016 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2017 { 0x0093, sent
|optional
},
2018 { 0x0094, sent
|optional
},
2019 { 0x0094, sent
|optional
},
2020 { WM_CAPTURECHANGED
, sent
},
2021 { HCBT_DESTROYWND
, hook
},
2022 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2023 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2024 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2028 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
2029 static int sequence_cnt
, sequence_size
;
2030 static struct recvd_message
* sequence
;
2031 static int log_all_parent_messages
;
2032 static CRITICAL_SECTION sequence_cs
;
2034 /* user32 functions */
2035 static HWND (WINAPI
*pGetAncestor
)(HWND
,UINT
);
2036 static BOOL (WINAPI
*pGetMenuInfo
)(HMENU
,LPCMENUINFO
);
2037 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
2038 static BOOL (WINAPI
*pSetMenuInfo
)(HMENU
,LPCMENUINFO
);
2039 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
2040 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
2041 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
2042 static BOOL (WINAPI
*pGetMonitorInfoA
)(HMONITOR
,LPMONITORINFO
);
2043 static HMONITOR (WINAPI
*pMonitorFromPoint
)(POINT
,DWORD
);
2044 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
2045 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
2046 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
2047 static UINT_PTR (WINAPI
*pSetCoalescableTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
, ULONG
);
2048 /* kernel32 functions */
2049 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
2051 static void init_procs(void)
2053 HMODULE user32
= GetModuleHandleA("user32.dll");
2054 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
2056 #define GET_PROC(dll, func) \
2057 p ## func = (void*)GetProcAddress(dll, #func); \
2059 trace("GetProcAddress(%s) failed\n", #func); \
2062 GET_PROC(user32
, GetAncestor
)
2063 GET_PROC(user32
, GetMenuInfo
)
2064 GET_PROC(user32
, NotifyWinEvent
)
2065 GET_PROC(user32
, SetMenuInfo
)
2066 GET_PROC(user32
, SetWinEventHook
)
2067 GET_PROC(user32
, TrackMouseEvent
)
2068 GET_PROC(user32
, UnhookWinEvent
)
2069 GET_PROC(user32
, GetMonitorInfoA
)
2070 GET_PROC(user32
, MonitorFromPoint
)
2071 GET_PROC(user32
, UpdateLayeredWindow
)
2072 GET_PROC(user32
, SetSystemTimer
)
2073 GET_PROC(user32
, KillSystemTimer
)
2074 GET_PROC(user32
, SetCoalescableTimer
)
2076 GET_PROC(kernel32
, GetCPInfoExA
)
2081 static const char *get_winpos_flags(UINT flags
)
2083 static char buffer
[300];
2086 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2087 DUMP( SWP_SHOWWINDOW
);
2088 DUMP( SWP_HIDEWINDOW
);
2089 DUMP( SWP_NOACTIVATE
);
2090 DUMP( SWP_FRAMECHANGED
);
2091 DUMP( SWP_NOCOPYBITS
);
2092 DUMP( SWP_NOOWNERZORDER
);
2093 DUMP( SWP_NOSENDCHANGING
);
2094 DUMP( SWP_DEFERERASE
);
2095 DUMP( SWP_ASYNCWINDOWPOS
);
2096 DUMP( SWP_NOZORDER
);
2097 DUMP( SWP_NOREDRAW
);
2100 DUMP( SWP_NOCLIENTSIZE
);
2101 DUMP( SWP_NOCLIENTMOVE
);
2102 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
2107 static BOOL
ignore_message( UINT message
)
2109 /* these are always ignored */
2110 return (message
>= 0xc000 ||
2111 message
== WM_GETICON
||
2112 message
== WM_GETOBJECT
||
2113 message
== WM_TIMECHANGE
||
2114 message
== WM_DISPLAYCHANGE
||
2115 message
== WM_DEVICECHANGE
||
2116 message
== WM_DWMNCRENDERINGCHANGED
);
2119 static unsigned hash_Ly_W(const WCHAR
*str
)
2124 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2129 static unsigned hash_Ly(const char *str
)
2134 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2139 #define add_message(msg) add_message_(__LINE__,msg);
2140 static void add_message_(int line
, const struct recvd_message
*msg
)
2142 struct recvd_message
*seq
;
2144 EnterCriticalSection( &sequence_cs
);
2148 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
) );
2150 if (sequence_cnt
== sequence_size
)
2153 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof(*sequence
) );
2157 seq
= &sequence
[sequence_cnt
++];
2158 seq
->hwnd
= msg
->hwnd
;
2159 seq
->message
= msg
->message
;
2160 seq
->flags
= msg
->flags
;
2161 seq
->wParam
= msg
->wParam
;
2162 seq
->lParam
= msg
->lParam
;
2164 seq
->descr
= msg
->descr
;
2166 LeaveCriticalSection( &sequence_cs
);
2170 if (msg
->flags
& hook
)
2172 static const char * const CBT_code_name
[10] =
2180 "HCBT_CLICKSKIPPED",
2185 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
2187 sprintf( seq
->output
, "%s: hook %d (%s) wp %08lx lp %08lx",
2188 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
2190 else if (msg
->flags
& winevent_hook
)
2192 sprintf( seq
->output
, "%s: winevent %p %08x %08lx %08lx",
2193 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2197 switch (msg
->message
)
2199 case WM_WINDOWPOSCHANGING
:
2200 case WM_WINDOWPOSCHANGED
:
2202 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
2204 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s",
2205 msg
->descr
, msg
->hwnd
,
2206 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
2207 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
2208 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
2209 get_winpos_flags(winpos
->flags
) );
2211 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2212 * in the high word for internal purposes
2214 seq
->wParam
= winpos
->flags
& 0xffff;
2215 /* We are not interested in the flags that don't match under XP and Win9x */
2216 seq
->wParam
&= ~SWP_NOZORDER
;
2222 DRAW_ITEM_STRUCT di
;
2223 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
2225 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2226 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
2227 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
2230 di
.u
.item
.type
= dis
->CtlType
;
2231 di
.u
.item
.ctl_id
= dis
->CtlID
;
2232 if (dis
->CtlType
== ODT_LISTBOX
||
2233 dis
->CtlType
== ODT_COMBOBOX
||
2234 dis
->CtlType
== ODT_MENU
)
2235 di
.u
.item
.item_id
= dis
->itemID
;
2236 di
.u
.item
.action
= dis
->itemAction
;
2237 di
.u
.item
.state
= dis
->itemState
;
2239 seq
->lParam
= di
.u
.lp
;
2243 case WM_MEASUREITEM
:
2245 MEASURE_ITEM_STRUCT mi
;
2246 MEASUREITEMSTRUCT
*mis
= (MEASUREITEMSTRUCT
*)msg
->lParam
;
2247 BOOL is_unicode_data
= TRUE
;
2249 sprintf( seq
->output
, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx",
2250 msg
->descr
, msg
->hwnd
, mis
->CtlType
, mis
->CtlID
,
2251 mis
->itemID
, mis
->itemData
);
2253 if (mis
->CtlType
== ODT_LISTBOX
)
2255 HWND ctrl
= GetDlgItem(msg
->hwnd
, mis
->CtlID
);
2256 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2260 mi
.u
.item
.CtlType
= mis
->CtlType
;
2261 mi
.u
.item
.CtlID
= mis
->CtlID
;
2262 mi
.u
.item
.itemID
= mis
->itemID
;
2263 mi
.u
.item
.wParam
= msg
->wParam
;
2264 seq
->wParam
= mi
.u
.wp
;
2265 if (is_unicode_data
)
2266 seq
->lParam
= mis
->itemData
? hash_Ly_W((const WCHAR
*)mis
->itemData
) : 0;
2268 seq
->lParam
= mis
->itemData
? hash_Ly((const char *)mis
->itemData
) : 0;
2272 case WM_COMPAREITEM
:
2274 COMPAREITEMSTRUCT
*cis
= (COMPAREITEMSTRUCT
*)msg
->lParam
;
2275 HWND ctrl
= GetDlgItem(msg
->hwnd
, cis
->CtlID
);
2276 BOOL is_unicode_data
= TRUE
;
2278 ok(msg
->wParam
== cis
->CtlID
, "expected %#x, got %#lx\n", cis
->CtlID
, msg
->wParam
);
2279 ok(cis
->hwndItem
== ctrl
, "expected %p, got %p\n", ctrl
, cis
->hwndItem
);
2280 ok((int)cis
->itemID1
>= 0, "expected >= 0, got %d\n", cis
->itemID1
);
2281 ok((int)cis
->itemID2
== -1, "expected -1, got %d\n", cis
->itemID2
);
2283 sprintf( seq
->output
, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx",
2284 msg
->descr
, msg
->hwnd
, cis
->CtlType
, cis
->CtlID
,
2285 cis
->itemID1
, cis
->itemData1
, cis
->itemID2
, cis
->itemData2
);
2287 if (cis
->CtlType
== ODT_LISTBOX
)
2288 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2290 if (is_unicode_data
)
2292 seq
->wParam
= cis
->itemData1
? hash_Ly_W((const WCHAR
*)cis
->itemData1
) : 0;
2293 seq
->lParam
= cis
->itemData2
? hash_Ly_W((const WCHAR
*)cis
->itemData2
) : 0;
2297 seq
->wParam
= cis
->itemData1
? hash_Ly((const char *)cis
->itemData1
) : 0;
2298 seq
->lParam
= cis
->itemData2
? hash_Ly((const char *)cis
->itemData2
) : 0;
2304 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
2305 sprintf( seq
->output
, "%s: %p %04x wp %08lx lp %08lx",
2306 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2308 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
2309 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
2314 /* try to make sure pending X events have been processed before continuing */
2315 static void flush_events(void)
2319 int min_timeout
= 100;
2320 DWORD time
= GetTickCount() + diff
;
2324 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
2325 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2326 diff
= time
- GetTickCount();
2330 static void flush_sequence(void)
2332 EnterCriticalSection( &sequence_cs
);
2333 HeapFree(GetProcessHeap(), 0, sequence
);
2335 sequence_cnt
= sequence_size
= 0;
2336 LeaveCriticalSection( &sequence_cs
);
2339 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
2341 const struct recvd_message
*actual
= sequence
;
2342 unsigned int count
= 0;
2344 trace_(file
, line
)("Failed sequence %s:\n", context
);
2345 while (expected
->message
&& actual
->message
)
2347 if (actual
->output
[0])
2349 if (expected
->flags
& hook
)
2351 trace_(file
, line
)( " %u: expected: hook %04x - actual: %s\n",
2352 count
, expected
->message
, actual
->output
);
2354 else if (expected
->flags
& winevent_hook
)
2356 trace_(file
, line
)( " %u: expected: winevent %04x - actual: %s\n",
2357 count
, expected
->message
, actual
->output
);
2359 else if (expected
->flags
& kbd_hook
)
2361 trace_(file
, line
)( " %u: expected: kbd %04x - actual: %s\n",
2362 count
, expected
->message
, actual
->output
);
2366 trace_(file
, line
)( " %u: expected: msg %04x - actual: %s\n",
2367 count
, expected
->message
, actual
->output
);
2371 if (expected
->message
== actual
->message
)
2373 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) &&
2374 (expected
->flags
& optional
))
2376 /* don't match messages if their defwinproc status differs */
2385 /* silently drop winevent messages if there is no support for them */
2386 else if ((expected
->flags
& optional
) || ((expected
->flags
& winevent_hook
) && !hEvent_hook
))
2396 /* optional trailing messages */
2397 while (expected
->message
&& ((expected
->flags
& optional
) ||
2398 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2400 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2405 if (expected
->message
)
2407 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2411 while (actual
->message
&& actual
->output
[0])
2413 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
2419 #define ok_sequence( exp, contx, todo) \
2420 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2423 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2424 const char *file
, int line
)
2426 static const struct recvd_message end_of_sequence
;
2427 const struct message
*expected
= expected_list
;
2428 const struct recvd_message
*actual
;
2429 int failcount
= 0, dump
= 0;
2430 unsigned int count
= 0;
2432 add_message(&end_of_sequence
);
2436 while (expected
->message
&& actual
->message
)
2438 if (expected
->message
== actual
->message
&&
2439 !((expected
->flags
^ actual
->flags
) & (hook
|winevent_hook
|kbd_hook
)))
2441 if (expected
->flags
& wparam
)
2443 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2447 if (strcmp(winetest_platform
, "wine")) dump
++;
2448 ok_( file
, line
) (FALSE
,
2449 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2450 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2455 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2456 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2457 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2458 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2462 if (expected
->flags
& lparam
)
2464 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2468 if (strcmp(winetest_platform
, "wine")) dump
++;
2469 ok_( file
, line
) (FALSE
,
2470 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2471 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2476 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2477 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2478 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2479 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2482 if ((expected
->flags
& optional
) &&
2483 ((expected
->flags
^ actual
->flags
) & (defwinproc
|parent
)))
2485 /* don't match optional messages if their defwinproc or parent status differs */
2490 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2494 if (strcmp(winetest_platform
, "wine")) dump
++;
2495 ok_( file
, line
) (FALSE
,
2496 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2497 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2502 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2503 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2504 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2505 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2508 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2509 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n",
2510 context
, count
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2511 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2513 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2514 "%s: %u: the msg 0x%04x should have been %s\n",
2515 context
, count
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2516 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2518 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2519 "%s: %u: the msg 0x%04x was expected in %s\n",
2520 context
, count
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2521 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2523 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
2524 "%s: %u: the msg 0x%04x should have been sent by a hook\n",
2525 context
, count
, expected
->message
);
2526 if ((expected
->flags
& hook
) != (actual
->flags
& hook
)) dump
++;
2528 ok_( file
, line
) ((expected
->flags
& winevent_hook
) == (actual
->flags
& winevent_hook
),
2529 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n",
2530 context
, count
, expected
->message
);
2531 if ((expected
->flags
& winevent_hook
) != (actual
->flags
& winevent_hook
)) dump
++;
2533 ok_( file
, line
) ((expected
->flags
& kbd_hook
) == (actual
->flags
& kbd_hook
),
2534 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n",
2535 context
, count
, expected
->message
);
2536 if ((expected
->flags
& kbd_hook
) != (actual
->flags
& kbd_hook
)) dump
++;
2541 /* silently drop hook messages if there is no support for them */
2542 else if ((expected
->flags
& optional
) ||
2543 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2544 ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2545 ((expected
->flags
& kbd_hook
) && !hKBD_hook
))
2551 if (strcmp(winetest_platform
, "wine")) dump
++;
2552 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2553 context
, count
, expected
->message
, actual
->message
);
2559 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2560 context
, count
, expected
->message
, actual
->message
);
2568 /* skip all optional trailing messages */
2569 while (expected
->message
&& ((expected
->flags
& optional
) ||
2570 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2571 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2577 if (expected
->message
|| actual
->message
) {
2579 if (strcmp(winetest_platform
, "wine")) dump
++;
2580 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2581 context
, count
, expected
->message
, actual
->message
);
2587 if (expected
->message
|| actual
->message
)
2590 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2591 context
, count
, expected
->message
, actual
->message
);
2594 if( todo
&& !failcount
) /* succeeded yet marked todo */
2596 if (!strcmp(winetest_platform
, "wine")) dump
++;
2597 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
2601 if (dump
) dump_sequence(expected_list
, context
, file
, line
);
2605 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
2607 /******************************** MDI test **********************************/
2609 /* CreateWindow for MDI frame window, initially visible */
2610 static const struct message WmCreateMDIframeSeq
[] = {
2611 { HCBT_CREATEWND
, hook
},
2612 { WM_GETMINMAXINFO
, sent
},
2613 { WM_NCCREATE
, sent
},
2614 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2615 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
2616 { WM_CREATE
, sent
},
2617 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2618 { WM_NOTIFYFORMAT
, sent
|optional
},
2619 { WM_QUERYUISTATE
, sent
|optional
},
2620 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2621 { WM_GETMINMAXINFO
, sent
|optional
},
2622 { WM_NCCALCSIZE
, sent
|optional
},
2623 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2624 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2625 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2626 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2627 { HCBT_ACTIVATE
, hook
},
2628 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
2629 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2630 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2631 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2632 { WM_NCACTIVATE
, sent
},
2633 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2634 { WM_ACTIVATE
, sent
|wparam
, 1 },
2635 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2636 { HCBT_SETFOCUS
, hook
},
2637 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2638 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2639 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2640 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2641 /* Win9x adds SWP_NOZORDER below */
2642 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2643 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2644 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2645 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2649 /* DestroyWindow for MDI frame window, initially visible */
2650 static const struct message WmDestroyMDIframeSeq
[] = {
2651 { HCBT_DESTROYWND
, hook
},
2652 { 0x0090, sent
|optional
},
2653 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2654 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2655 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2656 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2657 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
2658 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2659 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
2660 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
2661 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2662 { WM_DESTROY
, sent
},
2663 { WM_NCDESTROY
, sent
},
2666 /* CreateWindow for MDI client window, initially visible */
2667 static const struct message WmCreateMDIclientSeq
[] = {
2668 { HCBT_CREATEWND
, hook
},
2669 { WM_NCCREATE
, sent
},
2670 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2671 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2672 { WM_CREATE
, sent
},
2673 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2674 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2675 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2677 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
2678 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2679 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2680 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2681 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2684 /* ShowWindow(SW_SHOW) for MDI client window */
2685 static const struct message WmShowMDIclientSeq
[] = {
2686 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2687 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2688 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2689 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2692 /* ShowWindow(SW_HIDE) for MDI client window */
2693 static const struct message WmHideMDIclientSeq
[] = {
2694 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2695 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2696 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
2697 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
2698 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2701 /* DestroyWindow for MDI client window, initially visible */
2702 static const struct message WmDestroyMDIclientSeq
[] = {
2703 { HCBT_DESTROYWND
, hook
},
2704 { 0x0090, sent
|optional
},
2705 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
2706 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2707 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2708 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2709 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2710 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2711 { WM_DESTROY
, sent
},
2712 { WM_NCDESTROY
, sent
},
2715 /* CreateWindow for MDI child window, initially visible */
2716 static const struct message WmCreateMDIchildVisibleSeq
[] = {
2717 { HCBT_CREATEWND
, hook
},
2718 { WM_NCCREATE
, sent
},
2719 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2720 { WM_CREATE
, sent
},
2721 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2722 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2724 /* Win2k sends wparam set to
2725 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2726 * while Win9x doesn't bother to set child window id according to
2727 * CLIENTCREATESTRUCT.idFirstChild
2729 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2730 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2731 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2732 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2733 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2734 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2735 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2736 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2737 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2739 /* Win9x: message sequence terminates here. */
2741 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2742 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2743 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2744 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2745 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2746 { WM_SETFOCUS
, sent
}, /* in MDI client */
2747 { HCBT_SETFOCUS
, hook
},
2748 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2749 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2750 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2751 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2752 { WM_SETFOCUS
, sent
|defwinproc
},
2753 { WM_MDIACTIVATE
, sent
|defwinproc
},
2756 /* WM_CHILDACTIVATE sent to disabled window */
2757 static const struct message WmChildActivateDisabledWindowSeq
[] = {
2758 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2761 /* WM_CHILDACTIVATE sent to enabled window */
2762 static const struct message WmChildActivateWindowSeq
[] = {
2763 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2764 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 },
2765 { WM_MDIACTIVATE
, sent
|defwinproc
},
2766 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2767 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2768 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2769 { HCBT_SETFOCUS
, hook
},
2770 { WM_KILLFOCUS
, sent
|defwinproc
},
2771 { WM_SETFOCUS
, sent
},
2772 { HCBT_SETFOCUS
, hook
},
2773 { WM_KILLFOCUS
, sent
},
2774 { WM_SETFOCUS
, sent
|defwinproc
},
2775 { WM_MDIACTIVATE
, sent
|defwinproc
},
2778 /* CreateWindow for MDI child window with invisible parent */
2779 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
2780 { HCBT_CREATEWND
, hook
},
2781 { WM_GETMINMAXINFO
, sent
},
2782 { WM_NCCREATE
, sent
},
2783 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2784 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2785 { WM_CREATE
, sent
},
2786 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2787 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2789 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2790 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2791 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
2792 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2793 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2794 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2796 /* Win9x: message sequence terminates here. */
2798 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2799 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2800 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2801 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2802 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2803 { WM_SETFOCUS
, sent
}, /* in MDI client */
2804 { HCBT_SETFOCUS
, hook
},
2805 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2806 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2807 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2808 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2809 { WM_SETFOCUS
, sent
|defwinproc
},
2810 { WM_MDIACTIVATE
, sent
|defwinproc
},
2813 /* DestroyWindow for MDI child window, initially visible */
2814 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
2815 { HCBT_DESTROYWND
, hook
},
2816 /* Win2k sends wparam set to
2817 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2818 * while Win9x doesn't bother to set child window id according to
2819 * CLIENTCREATESTRUCT.idFirstChild
2821 { 0x0090, sent
|optional
},
2822 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2823 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2824 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2825 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2826 { WM_ERASEBKGND
, sent
|parent
|optional
},
2827 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2829 /* { WM_DESTROY, sent }
2830 * Win9x: message sequence terminates here.
2833 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2834 { WM_KILLFOCUS
, sent
},
2835 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2836 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2837 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2838 { WM_SETFOCUS
, sent
}, /* in MDI client */
2840 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2841 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2842 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2843 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2844 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2845 { WM_SETFOCUS
, sent
}, /* in MDI client */
2847 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2849 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2850 { WM_KILLFOCUS
, sent
},
2851 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2852 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2853 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2854 { WM_SETFOCUS
, sent
}, /* in MDI client */
2856 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2857 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2858 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2859 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2860 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2861 { WM_SETFOCUS
, sent
}, /* in MDI client */
2863 { WM_DESTROY
, sent
},
2865 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2866 { WM_KILLFOCUS
, sent
},
2867 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2868 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2869 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2870 { WM_SETFOCUS
, sent
}, /* in MDI client */
2872 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2873 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2874 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2875 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2876 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2877 { WM_SETFOCUS
, sent
}, /* in MDI client */
2879 { WM_NCDESTROY
, sent
},
2882 /* CreateWindow for MDI child window, initially invisible */
2883 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
2884 { HCBT_CREATEWND
, hook
},
2885 { WM_NCCREATE
, sent
},
2886 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2887 { WM_CREATE
, sent
},
2888 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2889 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2891 /* Win2k sends wparam set to
2892 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2893 * while Win9x doesn't bother to set child window id according to
2894 * CLIENTCREATESTRUCT.idFirstChild
2896 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2899 /* DestroyWindow for MDI child window, initially invisible */
2900 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
2901 { HCBT_DESTROYWND
, hook
},
2902 /* Win2k sends wparam set to
2903 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2904 * while Win9x doesn't bother to set child window id according to
2905 * CLIENTCREATESTRUCT.idFirstChild
2907 { 0x0090, sent
|optional
},
2908 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2909 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2910 { WM_DESTROY
, sent
},
2911 { WM_NCDESTROY
, sent
},
2912 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
2913 { WM_PARENTNOTIFY
, sent
|wparam
|optional
, WM_DESTROY
}, /* MDI client */
2916 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
2917 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
2918 { HCBT_CREATEWND
, hook
},
2919 { WM_NCCREATE
, sent
},
2920 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2921 { WM_CREATE
, sent
},
2922 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2923 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2925 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2926 { WM_GETMINMAXINFO
, sent
},
2927 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2928 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2929 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2930 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2932 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2933 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2934 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2935 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2936 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2937 /* Win2k sends wparam set to
2938 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2939 * while Win9x doesn't bother to set child window id according to
2940 * CLIENTCREATESTRUCT.idFirstChild
2942 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2943 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2944 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2945 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2946 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2947 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2948 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2949 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2950 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
2952 /* Win9x: message sequence terminates here. */
2954 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
2955 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
2956 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2957 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2958 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2959 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2960 { HCBT_SETFOCUS
, hook
|optional
},
2961 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
2962 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2963 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2964 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2965 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
2966 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
2968 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2969 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2970 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2971 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2974 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
2975 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
2976 /* restore the 1st MDI child */
2977 { WM_SETREDRAW
, sent
|wparam
, 0 },
2978 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
2979 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
2980 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2981 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2982 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2983 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2985 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2986 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2987 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2988 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2989 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2990 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
2991 /* create the 2nd MDI child */
2992 { HCBT_CREATEWND
, hook
},
2993 { WM_NCCREATE
, sent
},
2994 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2995 { WM_CREATE
, sent
},
2996 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2997 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2999 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3000 { WM_GETMINMAXINFO
, sent
},
3001 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3002 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3003 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3004 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3005 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3007 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3008 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3009 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3010 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3011 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3012 /* Win2k sends wparam set to
3013 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3014 * while Win9x doesn't bother to set child window id according to
3015 * CLIENTCREATESTRUCT.idFirstChild
3017 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3018 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3019 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3020 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3021 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3022 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3023 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3024 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3026 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3027 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3029 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3031 /* Win9x: message sequence terminates here. */
3033 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3034 { HCBT_SETFOCUS
, hook
},
3035 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
3036 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
3037 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3038 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3039 { WM_SETFOCUS
, sent
}, /* in MDI client */
3040 { HCBT_SETFOCUS
, hook
},
3041 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3042 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3043 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3044 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3045 { WM_SETFOCUS
, sent
|defwinproc
},
3047 { WM_MDIACTIVATE
, sent
|defwinproc
},
3049 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3050 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3051 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3052 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3055 /* WM_MDICREATE MDI child window, initially visible and maximized */
3056 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
3057 { WM_MDICREATE
, sent
},
3058 { HCBT_CREATEWND
, hook
},
3059 { WM_NCCREATE
, sent
},
3060 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3061 { WM_CREATE
, sent
},
3062 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3063 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3065 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3066 { WM_GETMINMAXINFO
, sent
},
3067 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3068 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3069 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3070 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3073 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3074 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3075 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3076 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3077 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3079 /* Win2k sends wparam set to
3080 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3081 * while Win9x doesn't bother to set child window id according to
3082 * CLIENTCREATESTRUCT.idFirstChild
3084 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3085 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3086 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3088 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3090 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3091 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3092 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3094 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3095 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3097 /* Win9x: message sequence terminates here. */
3099 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3100 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3101 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3102 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3103 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
3104 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
3105 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3106 { HCBT_SETFOCUS
, hook
|optional
},
3107 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3108 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3109 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3110 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3111 { WM_SETFOCUS
, sent
|defwinproc
},
3113 { WM_MDIACTIVATE
, sent
|defwinproc
},
3116 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3117 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3118 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3119 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3122 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3123 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3124 { 0x0093, sent
|defwinproc
|optional
},
3125 { 0x0093, sent
|defwinproc
|optional
},
3126 { 0x0093, sent
|defwinproc
|optional
},
3127 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3128 { WM_MOVE
, sent
|defwinproc
},
3129 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3132 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3133 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3134 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3135 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3138 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3139 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3140 { 0x0093, sent
|optional
},
3141 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3142 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3144 { 0x0093, sent
|optional
},
3145 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3146 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3147 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
3148 { 0x0093, sent
|defwinproc
|optional
},
3149 { 0x0093, sent
|defwinproc
|optional
},
3150 { 0x0093, sent
|defwinproc
|optional
},
3151 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3152 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3156 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3157 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
3158 { HCBT_CREATEWND
, hook
},
3159 { WM_GETMINMAXINFO
, sent
},
3160 { WM_NCCREATE
, sent
},
3161 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3162 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
3163 { WM_CREATE
, sent
},
3164 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3165 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3166 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3167 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
3168 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3170 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3171 { WM_GETMINMAXINFO
, sent
},
3172 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3173 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3174 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3175 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3176 { WM_MOVE
, sent
|defwinproc
},
3177 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3179 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3180 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3181 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3182 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3183 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
3184 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3185 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3186 /* Win2k sends wparam set to
3187 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3188 * while Win9x doesn't bother to set child window id according to
3189 * CLIENTCREATESTRUCT.idFirstChild
3191 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3194 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3195 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
3196 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
3197 { HCBT_SYSCOMMAND
, hook
},
3198 { WM_CLOSE
, sent
|defwinproc
},
3199 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3201 /* bring the 1st MDI child to top */
3202 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
3203 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
3205 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3207 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
3208 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3209 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3211 /* maximize the 1st MDI child */
3212 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3213 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3214 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3215 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3216 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3217 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3218 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3220 /* restore the 2nd MDI child */
3221 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
3222 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
3223 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3224 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3226 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3228 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3229 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3231 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3233 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
3235 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3236 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3237 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3238 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3239 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3241 /* bring the 1st MDI child to top */
3242 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3243 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3244 { HCBT_SETFOCUS
, hook
},
3245 { WM_KILLFOCUS
, sent
|defwinproc
},
3246 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
3247 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3248 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3249 { WM_SETFOCUS
, sent
}, /* in MDI client */
3250 { HCBT_SETFOCUS
, hook
},
3251 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3252 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3253 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3254 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3255 { WM_SETFOCUS
, sent
|defwinproc
},
3256 { WM_MDIACTIVATE
, sent
|defwinproc
},
3257 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3259 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3260 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3261 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3262 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3263 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3264 { WM_MDIREFRESHMENU
, sent
},
3266 { HCBT_DESTROYWND
, hook
},
3267 /* Win2k sends wparam set to
3268 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3269 * while Win9x doesn't bother to set child window id according to
3270 * CLIENTCREATESTRUCT.idFirstChild
3272 { 0x0090, sent
|defwinproc
|optional
},
3273 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3274 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
3275 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3276 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3277 { WM_ERASEBKGND
, sent
|parent
|optional
},
3278 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3280 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3281 { WM_DESTROY
, sent
|defwinproc
},
3282 { WM_NCDESTROY
, sent
|defwinproc
},
3285 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3286 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
3287 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3288 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3289 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3290 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3291 { WM_ERASEBKGND
, sent
|parent
|optional
},
3292 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3294 { HCBT_SETFOCUS
, hook
},
3295 { WM_KILLFOCUS
, sent
},
3296 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3297 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3298 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3299 { WM_SETFOCUS
, sent
}, /* in MDI client */
3300 { HCBT_SETFOCUS
, hook
},
3301 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3302 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3303 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3304 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3305 { WM_SETFOCUS
, sent
},
3308 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3309 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3310 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3311 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3314 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3315 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3316 { 0x0093, sent
|defwinproc
|optional
},
3317 { 0x0093, sent
|defwinproc
|optional
},
3318 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3319 { WM_MOVE
, sent
|defwinproc
},
3320 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3323 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3324 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3325 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3326 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3329 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3330 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3331 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3332 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3335 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3336 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3337 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3338 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3341 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3342 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3343 { 0x0093, sent
|defwinproc
|optional
},
3344 { 0x0093, sent
|defwinproc
|optional
},
3345 { 0x0093, sent
|defwinproc
|optional
},
3346 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3347 { WM_MOVE
, sent
|defwinproc
},
3348 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3351 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3352 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3353 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3354 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3357 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3358 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3359 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3360 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3361 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3362 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3364 { 0x0093, sent
|defwinproc
|optional
},
3365 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
3366 { 0x0093, sent
|defwinproc
|optional
},
3367 { 0x0093, sent
|defwinproc
|optional
},
3368 { 0x0093, sent
|defwinproc
|optional
},
3369 { 0x0093, sent
|optional
},
3371 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3372 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3373 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3374 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3375 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3378 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3379 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3380 { 0x0093, sent
|defwinproc
|optional
},
3381 { 0x0093, sent
|defwinproc
|optional
},
3382 { 0x0093, sent
|defwinproc
|optional
},
3383 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3384 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3385 { 0x0093, sent
|optional
},
3387 { WM_NCACTIVATE
, sent
|wparam
, 0 },
3388 { WM_MDIACTIVATE
, sent
},
3390 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3391 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3392 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3394 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3396 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3397 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3398 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3401 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3402 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3403 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3404 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3407 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3408 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3409 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3410 { WM_MOVE
, sent
|defwinproc
},
3411 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3414 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3415 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3416 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3417 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3418 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3419 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3420 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3421 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3422 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3424 { HCBT_SETFOCUS
, hook
},
3425 { WM_KILLFOCUS
, sent
},
3426 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3427 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3428 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3429 { WM_SETFOCUS
, sent
}, /* in MDI client */
3431 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3433 { HCBT_DESTROYWND
, hook
},
3434 /* Win2k sends wparam set to
3435 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3436 * while Win9x doesn't bother to set child window id according to
3437 * CLIENTCREATESTRUCT.idFirstChild
3439 { 0x0090, sent
|optional
},
3440 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3442 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3443 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3444 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3445 { WM_ERASEBKGND
, sent
|parent
|optional
},
3446 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3448 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3449 { WM_DESTROY
, sent
},
3450 { WM_NCDESTROY
, sent
},
3453 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3454 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3455 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3456 { WM_GETMINMAXINFO
, sent
},
3457 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3458 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3459 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3460 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3462 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3463 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3464 { HCBT_SETFOCUS
, hook
|optional
},
3465 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3466 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3467 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3468 { HCBT_SETFOCUS
, hook
|optional
},
3469 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3470 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3471 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3472 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3473 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3474 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3475 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3476 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3478 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3479 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3480 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3481 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3482 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3485 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3486 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3487 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3488 { WM_GETMINMAXINFO
, sent
},
3489 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
3490 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3491 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3492 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3493 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3495 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3496 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3497 { HCBT_SETFOCUS
, hook
|optional
},
3498 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3499 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3500 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3501 { HCBT_SETFOCUS
, hook
|optional
},
3502 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3503 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3504 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3505 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3506 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3507 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3508 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3509 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3512 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3513 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3514 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3515 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3516 { WM_GETMINMAXINFO
, sent
},
3517 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3518 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3519 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3520 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3521 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3522 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3523 { WM_MOVE
, sent
|defwinproc
},
3524 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3526 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3527 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3528 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3529 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3530 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3531 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3533 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3534 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3535 { 0x0093, sent
|defwinproc
|optional
},
3536 { 0x0094, sent
|defwinproc
|optional
},
3537 { 0x0094, sent
|defwinproc
|optional
},
3538 { 0x0094, sent
|defwinproc
|optional
},
3539 { 0x0094, sent
|defwinproc
|optional
},
3540 { 0x0093, sent
|defwinproc
|optional
},
3541 { 0x0093, sent
|defwinproc
|optional
},
3542 { 0x0091, sent
|defwinproc
|optional
},
3543 { 0x0092, sent
|defwinproc
|optional
},
3544 { 0x0092, sent
|defwinproc
|optional
},
3545 { 0x0092, sent
|defwinproc
|optional
},
3546 { 0x0092, sent
|defwinproc
|optional
},
3547 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3548 { WM_MOVE
, sent
|defwinproc
},
3549 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3550 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3552 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3553 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3554 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3555 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3557 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3558 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3559 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3560 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3561 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3562 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3563 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3564 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3565 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3566 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3568 { 0x0093, sent
|optional
},
3569 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3570 { 0x0093, sent
|defwinproc
|optional
},
3571 { 0x0093, sent
|defwinproc
|optional
},
3572 { 0x0093, sent
|defwinproc
|optional
},
3573 { 0x0091, sent
|defwinproc
|optional
},
3574 { 0x0092, sent
|defwinproc
|optional
},
3575 { 0x0092, sent
|defwinproc
|optional
},
3576 { 0x0092, sent
|defwinproc
|optional
},
3577 { 0x0092, sent
|defwinproc
|optional
},
3578 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3579 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3580 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3583 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3584 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3585 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3586 { WM_GETMINMAXINFO
, sent
},
3587 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3588 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3589 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3590 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3591 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3593 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3594 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3595 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3596 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3597 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3600 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3601 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3602 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3603 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3604 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3605 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3606 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3607 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3609 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3610 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3611 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3612 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3613 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3616 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3617 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3618 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3619 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3620 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3621 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3622 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3623 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3624 { WM_MOVE
, sent
|defwinproc
},
3625 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3626 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3627 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3628 { HCBT_SETFOCUS
, hook
},
3629 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3630 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3631 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3632 { WM_SETFOCUS
, sent
},
3635 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3636 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
3637 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
3638 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3639 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3640 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3641 { WM_MOVE
, sent
|defwinproc
},
3642 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
3643 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
3644 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3645 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3646 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3647 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
}, /* MDI client */
3650 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3651 static const struct message WmRestoreMDIchildInvisibleSeq
[] = {
3652 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3653 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3654 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3655 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3656 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3657 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3658 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3660 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3661 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3662 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3663 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3664 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3668 static HWND mdi_client
;
3669 static WNDPROC old_mdi_client_proc
;
3671 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3673 struct recvd_message msg
;
3675 /* do not log painting messages */
3676 if (message
!= WM_PAINT
&&
3677 message
!= WM_NCPAINT
&&
3678 message
!= WM_SYNCPAINT
&&
3679 message
!= WM_ERASEBKGND
&&
3680 message
!= WM_NCHITTEST
&&
3681 message
!= WM_GETTEXT
&&
3682 message
!= WM_MDIGETACTIVE
&&
3683 !ignore_message( message
))
3686 msg
.message
= message
;
3687 msg
.flags
= sent
|wparam
|lparam
;
3688 msg
.wParam
= wParam
;
3689 msg
.lParam
= lParam
;
3690 msg
.descr
= "mdi client";
3694 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
3697 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3699 static LONG defwndproc_counter
= 0;
3701 struct recvd_message msg
;
3703 /* do not log painting messages */
3704 if (message
!= WM_PAINT
&&
3705 message
!= WM_NCPAINT
&&
3706 message
!= WM_SYNCPAINT
&&
3707 message
!= WM_ERASEBKGND
&&
3708 message
!= WM_NCHITTEST
&&
3709 message
!= WM_GETTEXT
&&
3710 !ignore_message( message
))
3714 case WM_MDIACTIVATE
:
3716 HWND active
, client
= GetParent(hwnd
);
3718 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
3720 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
3721 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
3723 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
3729 msg
.message
= message
;
3730 msg
.flags
= sent
|wparam
|lparam
;
3731 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3732 msg
.wParam
= wParam
;
3733 msg
.lParam
= lParam
;
3734 msg
.descr
= "mdi child";
3738 defwndproc_counter
++;
3739 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
3740 defwndproc_counter
--;
3745 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3747 static LONG defwndproc_counter
= 0;
3749 struct recvd_message msg
;
3751 /* do not log painting messages */
3752 if (message
!= WM_PAINT
&&
3753 message
!= WM_NCPAINT
&&
3754 message
!= WM_SYNCPAINT
&&
3755 message
!= WM_ERASEBKGND
&&
3756 message
!= WM_NCHITTEST
&&
3757 message
!= WM_GETTEXT
&&
3758 !ignore_message( message
))
3761 msg
.message
= message
;
3762 msg
.flags
= sent
|wparam
|lparam
;
3763 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3764 msg
.wParam
= wParam
;
3765 msg
.lParam
= lParam
;
3766 msg
.descr
= "mdi frame";
3770 defwndproc_counter
++;
3771 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
3772 defwndproc_counter
--;
3777 static BOOL
mdi_RegisterWindowClasses(void)
3782 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
3785 cls
.hInstance
= GetModuleHandleA(0);
3787 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
3788 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
3789 cls
.lpszMenuName
= NULL
;
3790 cls
.lpszClassName
= "MDI_frame_class";
3791 if (!RegisterClassA(&cls
)) return FALSE
;
3793 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
3794 cls
.lpszClassName
= "MDI_child_class";
3795 if (!RegisterClassA(&cls
)) return FALSE
;
3797 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
3798 old_mdi_client_proc
= cls
.lpfnWndProc
;
3799 cls
.hInstance
= GetModuleHandleA(0);
3800 cls
.lpfnWndProc
= mdi_client_hook_proc
;
3801 cls
.lpszClassName
= "MDI_client_class";
3802 if (!RegisterClassA(&cls
)) assert(0);
3807 static void test_mdi_messages(void)
3809 MDICREATESTRUCTA mdi_cs
;
3810 CLIENTCREATESTRUCT client_cs
;
3811 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
3814 HMENU hMenu
= CreateMenu();
3817 if (!mdi_RegisterWindowClasses()) assert(0);
3821 trace("creating MDI frame window\n");
3822 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
3823 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
3824 WS_MAXIMIZEBOX
| WS_VISIBLE
,
3825 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
3826 GetDesktopWindow(), hMenu
,
3827 GetModuleHandleA(0), NULL
);
3829 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
3831 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3832 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
3834 trace("creating MDI client window\n");
3835 GetClientRect(mdi_frame
, &rc
);
3836 client_cs
.hWindowMenu
= 0;
3837 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
3838 mdi_client
= CreateWindowExA(0, "MDI_client_class",
3840 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
3841 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
3842 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
3844 SetWindowLongA(mdi_client
, 0, 0xdeadbeef);
3846 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
3847 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3848 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
3850 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3851 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3852 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3857 trace("creating invisible MDI child window\n");
3858 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3860 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3861 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3865 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
3866 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
3868 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3869 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3871 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3872 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3874 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3875 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3876 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3878 ShowWindow(mdi_child
, SW_HIDE
);
3879 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
3882 ShowWindow(mdi_child
, SW_SHOW
);
3883 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
3885 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3886 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3888 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3889 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3891 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3892 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3893 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3895 DestroyWindow(mdi_child
);
3898 trace("creating visible MDI child window\n");
3899 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3900 WS_CHILD
| WS_VISIBLE
,
3901 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3902 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3904 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
3906 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3907 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3909 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3910 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3912 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3913 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3914 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3917 DestroyWindow(mdi_child
);
3918 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3920 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3921 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3923 /* Win2k: MDI client still returns a just destroyed child as active
3924 * Win9x: MDI client returns 0
3926 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3927 ok(active_child
== mdi_child
|| /* win2k */
3928 !active_child
, /* win9x */
3929 "wrong active MDI child %p\n", active_child
);
3930 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3934 trace("creating invisible MDI child window\n");
3935 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3937 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3938 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3940 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
3942 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
3943 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
3945 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3946 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3948 /* Win2k: MDI client still returns a just destroyed child as active
3949 * Win9x: MDI client returns mdi_child2
3951 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3952 ok(active_child
== mdi_child
|| /* win2k */
3953 active_child
== mdi_child2
, /* win9x */
3954 "wrong active MDI child %p\n", active_child
);
3955 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3958 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3959 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
3961 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3962 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3964 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3965 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3966 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3969 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3970 ok(GetFocus() == mdi_child2
|| /* win2k */
3971 GetFocus() == 0, /* win9x */
3972 "wrong focus window %p\n", GetFocus());
3977 ShowWindow(mdi_child2
, SW_HIDE
);
3978 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3980 ShowWindow(mdi_child2
, SW_RESTORE
);
3981 ok_sequence(WmRestoreMDIchildInvisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
3984 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3985 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3987 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3988 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3989 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3995 ShowWindow(mdi_child2
, SW_HIDE
);
3996 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3998 ShowWindow(mdi_child2
, SW_SHOW
);
3999 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
4001 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4002 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4004 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4005 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
4007 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4008 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4010 ShowWindow(mdi_child2
, SW_RESTORE
);
4011 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
4013 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4014 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4016 ShowWindow(mdi_child2
, SW_MINIMIZE
);
4017 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", TRUE
);
4019 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4020 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4022 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4023 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4024 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4027 ShowWindow(mdi_child2
, SW_RESTORE
);
4028 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
4030 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4031 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4033 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4034 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4035 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4041 ShowWindow(mdi_child2
, SW_HIDE
);
4042 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4044 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4045 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4047 DestroyWindow(mdi_child2
);
4048 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
4050 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4051 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4053 trace("Testing WM_CHILDACTIVATE\n");
4055 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4056 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_DISABLED
,
4057 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4058 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4060 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4061 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
,
4062 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4063 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4065 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4066 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4067 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4070 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4071 ok_sequence(WmChildActivateDisabledWindowSeq
, "WM_CHILDACTIVATE sent to disabled window", FALSE
);
4073 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4074 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4075 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4078 EnableWindow(mdi_child
, TRUE
);
4080 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4081 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4082 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4085 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4086 ok_sequence(WmChildActivateWindowSeq
, "WM_CHILDACTIVATE sent to enabled window", FALSE
);
4088 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4089 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4090 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4093 DestroyWindow(mdi_child
);
4094 DestroyWindow(mdi_child2
);
4097 /* test for maximized MDI children */
4098 trace("creating maximized visible MDI child window 1\n");
4099 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4100 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4101 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4102 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4104 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
4105 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4107 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4108 ok(GetFocus() == mdi_child
|| /* win2k */
4109 GetFocus() == 0, /* win9x */
4110 "wrong focus window %p\n", GetFocus());
4112 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4113 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4114 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4117 trace("creating maximized visible MDI child window 2\n");
4118 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4119 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4120 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4121 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4123 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4124 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4125 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4127 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4128 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4130 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4131 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4132 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4135 trace("destroying maximized visible MDI child window 2\n");
4136 DestroyWindow(mdi_child2
);
4137 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4139 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4141 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4142 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4144 /* Win2k: MDI client still returns a just destroyed child as active
4145 * Win9x: MDI client returns 0
4147 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4148 ok(active_child
== mdi_child2
|| /* win2k */
4149 !active_child
, /* win9x */
4150 "wrong active MDI child %p\n", active_child
);
4153 ShowWindow(mdi_child
, SW_MAXIMIZE
);
4154 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4157 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4158 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4160 trace("re-creating maximized visible MDI child window 2\n");
4161 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4162 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4163 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4164 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4166 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4167 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4168 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4170 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4171 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4173 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4174 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4175 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4178 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
4179 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
4180 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
4182 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4183 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4184 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4186 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4187 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4188 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4191 DestroyWindow(mdi_child
);
4192 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4194 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4195 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4197 /* Win2k: MDI client still returns a just destroyed child as active
4198 * Win9x: MDI client returns 0
4200 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4201 ok(active_child
== mdi_child
|| /* win2k */
4202 !active_child
, /* win9x */
4203 "wrong active MDI child %p\n", active_child
);
4206 trace("creating maximized invisible MDI child window\n");
4207 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4208 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
4209 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4210 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4212 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
4213 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4214 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
4215 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
4217 /* Win2k: MDI client still returns a just destroyed child as active
4218 * Win9x: MDI client returns 0
4220 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4221 ok(active_child
== mdi_child
|| /* win2k */
4222 !active_child
|| active_child
== mdi_child2
, /* win9x */
4223 "wrong active MDI child %p\n", active_child
);
4226 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4227 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4228 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
4229 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4230 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4231 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4233 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4234 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4235 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4238 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4241 /* end of test for maximized MDI children */
4244 trace("creating maximized visible MDI child window 1(Switch test)\n");
4245 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4246 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4247 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4248 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4250 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
4251 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
4253 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4254 ok(GetFocus() == mdi_child
|| /* win2k */
4255 GetFocus() == 0, /* win9x */
4256 "wrong focus window %p(Switch test)\n", GetFocus());
4258 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4259 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4260 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4263 trace("creating maximized visible MDI child window 2(Switch test)\n");
4264 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4265 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4266 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4267 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4269 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
4271 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
4272 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
4274 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4275 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
4277 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4278 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
4279 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4282 trace("Switch child window.\n");
4283 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
4284 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
4285 trace("end of test for switch maximized MDI children\n");
4288 /* Prepare for switching test of not maximized MDI children */
4289 ShowWindow( mdi_child
, SW_NORMAL
);
4290 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
4291 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
4292 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
4293 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4296 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
4297 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
4298 trace("end of test for switch not maximized MDI children\n");
4301 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4304 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4309 /* end of tests for switch maximized/not maximized MDI children */
4311 mdi_cs
.szClass
= "MDI_child_Class";
4312 mdi_cs
.szTitle
= "MDI child";
4313 mdi_cs
.hOwner
= GetModuleHandleA(0);
4316 mdi_cs
.cx
= CW_USEDEFAULT
;
4317 mdi_cs
.cy
= CW_USEDEFAULT
;
4318 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
4320 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
4321 ok(mdi_child
!= 0, "MDI child creation failed\n");
4322 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
4324 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
4326 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4327 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4329 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
4330 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4331 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4333 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4334 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4335 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4338 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4339 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
4341 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
4342 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4343 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4348 val
= GetWindowLongA(mdi_client
, 0);
4349 ok(val
== 0xdeadbeef || broken(val
== 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val
);
4350 DestroyWindow(mdi_client
);
4351 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4353 /* test maximization of MDI child with invisible parent */
4354 client_cs
.hWindowMenu
= 0;
4355 mdi_client
= CreateWindowA("MDI_client_class",
4357 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
4359 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4360 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
4362 ShowWindow(mdi_client
, SW_HIDE
);
4363 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
4365 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4366 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
4368 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4369 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
4371 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
4372 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
4373 zoomed
= IsZoomed(mdi_child
);
4374 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4376 ShowWindow(mdi_client
, SW_SHOW
);
4377 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
4379 DestroyWindow(mdi_child
);
4380 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
4382 /* end of test for maximization of MDI child with invisible parent */
4384 DestroyWindow(mdi_client
);
4385 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4387 DestroyWindow(mdi_frame
);
4388 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
4390 /************************* End of MDI test **********************************/
4392 static void test_WM_SETREDRAW(HWND hwnd
)
4394 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4399 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
4400 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
4402 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
4403 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
4406 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
4407 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
4409 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4410 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
4412 /* restore original WS_VISIBLE state */
4413 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4419 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4421 struct recvd_message msg
;
4423 if (ignore_message( message
)) return 0;
4429 case WM_NCMOUSEMOVE
:
4430 case WM_NCMOUSELEAVE
:
4438 msg
.message
= message
;
4439 msg
.flags
= sent
|wparam
|lparam
;
4440 msg
.wParam
= wParam
;
4441 msg
.lParam
= lParam
;
4442 msg
.descr
= "dialog";
4445 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
4446 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
4450 static INT_PTR CALLBACK
TestModalDlgProc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4452 struct recvd_message msg
;
4454 if (ignore_message( message
)) return 0;
4460 case WM_NCMOUSEMOVE
:
4461 case WM_NCMOUSELEAVE
:
4469 msg
.message
= message
;
4470 msg
.flags
= sent
|wparam
|lparam
;
4471 msg
.wParam
= wParam
;
4472 msg
.lParam
= lParam
;
4473 msg
.descr
= "dialog";
4476 if (message
== WM_INITDIALOG
) EndDialog( hwnd
, 0 );
4480 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4482 DWORD style
, exstyle
;
4486 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4487 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4488 /* do not be confused by WS_DLGFRAME set */
4489 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4491 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4492 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4494 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4495 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4496 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4497 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
4499 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
4501 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4502 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4503 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4505 /* a subsequent call should do nothing */
4506 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4507 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4508 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4512 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
4513 ok( ret
, "GetScrollRange(%d) error %d\n", ctl
, GetLastError());
4514 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4515 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
4516 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
4519 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4521 DWORD style
, exstyle
;
4525 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4526 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4527 /* do not be confused by WS_DLGFRAME set */
4528 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4530 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4531 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4533 si
.cbSize
= sizeof(si
);
4534 si
.fMask
= SIF_RANGE
;
4537 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4538 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4539 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4541 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4543 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4544 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4545 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4547 /* a subsequent call should do nothing */
4548 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4549 if (style
& WS_HSCROLL
)
4550 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4551 else if (style
& WS_VSCROLL
)
4552 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4554 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4556 si
.fMask
= SIF_PAGE
;
4558 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4559 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4563 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4564 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4566 si
.fMask
= SIF_RANGE
;
4567 si
.nMin
= 0xdeadbeef;
4568 si
.nMax
= 0xdeadbeef;
4569 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4570 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4571 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4572 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4573 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4576 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4577 static void test_scroll_messages(HWND hwnd
)
4588 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4589 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4590 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4591 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4592 /* values of min and max are undefined */
4595 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4596 ok( ret
, "SetScrollRange error %d\n", GetLastError());
4597 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4598 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4603 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4604 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4605 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4606 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4607 /* values of min and max are undefined */
4610 si
.cbSize
= sizeof(si
);
4611 si
.fMask
= SIF_RANGE
;
4614 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4615 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4616 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4619 si
.fMask
= SIF_PAGE
;
4621 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4622 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4623 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4628 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4629 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4630 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4633 si
.fMask
= SIF_RANGE
;
4634 si
.nMin
= 0xdeadbeef;
4635 si
.nMax
= 0xdeadbeef;
4636 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
4637 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4638 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
4639 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4640 /* values of min and max are undefined */
4643 /* set WS_HSCROLL */
4644 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4645 /* clear WS_HSCROLL */
4646 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4648 /* set WS_HSCROLL */
4649 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4650 /* clear WS_HSCROLL */
4651 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4653 /* set WS_VSCROLL */
4654 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4655 /* clear WS_VSCROLL */
4656 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4658 /* set WS_VSCROLL */
4659 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4660 /* clear WS_VSCROLL */
4661 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4664 static void test_showwindow(void)
4669 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4670 100, 100, 200, 200, 0, 0, 0, NULL
);
4671 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4672 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4673 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
4674 ok (hchild
!= 0, "Failed to create child\n");
4677 /* ShowWindow( SW_SHOWNA) for invisible top level window */
4678 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
4679 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4680 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
4682 /* ShowWindow( SW_SHOWNA) for now visible top level window */
4683 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
4684 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4685 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
4686 /* back to invisible */
4687 ShowWindow(hchild
, SW_HIDE
);
4688 ShowWindow(hwnd
, SW_HIDE
);
4690 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
4691 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
4692 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4693 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
4694 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
4695 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
4697 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
4698 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4699 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
4700 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
4701 ShowWindow( hwnd
, SW_SHOW
);
4703 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
4704 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4705 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
4707 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
4708 ShowWindow( hchild
, SW_HIDE
);
4710 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
4711 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4712 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
4715 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
4716 DestroyWindow(hchild
);
4717 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
4719 DestroyWindow(hwnd
);
4724 * 1. Create invisible maximized popup window.
4725 * 2. Move and resize it.
4726 * 3. Show it maximized.
4728 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4729 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4730 100, 100, 200, 200, 0, 0, 0, NULL
);
4731 ok (hwnd
!= 0, "Failed to create popup window\n");
4732 ok(IsZoomed(hwnd
), "window should be maximized\n");
4733 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4735 GetWindowRect(hwnd
, &rc
);
4736 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4737 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4738 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc
));
4739 /* Reset window's size & position */
4740 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4741 ok(IsZoomed(hwnd
), "window should be maximized\n");
4744 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4745 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4746 ok(IsZoomed(hwnd
), "window should be maximized\n");
4747 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
4749 GetWindowRect(hwnd
, &rc
);
4750 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4751 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4752 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc
));
4753 DestroyWindow(hwnd
);
4756 /* Test again, this time the NC_PAINT message */
4757 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4758 100, 100, 200, 200, 0, 0, 0, NULL
);
4759 ok (hwnd
!= 0, "Failed to create popup window\n");
4760 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4762 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4763 ok_sequence(WmShowMaxPopupResizedSeq_todo
,
4764 "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup TODO", TRUE
);
4765 DestroyWindow(hwnd
);
4769 * 1. Create invisible maximized popup window.
4770 * 2. Show it maximized.
4772 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4773 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4774 100, 100, 200, 200, 0, 0, 0, NULL
);
4775 ok (hwnd
!= 0, "Failed to create popup window\n");
4776 ok(IsZoomed(hwnd
), "window should be maximized\n");
4777 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4779 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4780 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4781 ok(IsZoomed(hwnd
), "window should be maximized\n");
4782 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
4783 DestroyWindow(hwnd
);
4787 * 1. Create visible maximized popup window.
4789 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
4790 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
4791 100, 100, 200, 200, 0, 0, 0, NULL
);
4792 ok (hwnd
!= 0, "Failed to create popup window\n");
4793 ok(IsZoomed(hwnd
), "window should be maximized\n");
4794 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4795 DestroyWindow(hwnd
);
4799 * 1. Create visible popup window.
4802 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
4803 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
4804 100, 100, 200, 200, 0, 0, 0, NULL
);
4805 ok (hwnd
!= 0, "Failed to create popup window\n");
4806 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
4807 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
4809 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
4810 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4811 ok(IsZoomed(hwnd
), "window should be maximized\n");
4812 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
4813 DestroyWindow(hwnd
);
4817 static void test_sys_menu(void)
4823 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4824 100, 100, 200, 200, 0, 0, 0, NULL
);
4825 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4829 /* test existing window without CS_NOCLOSE style */
4830 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4831 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4833 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4834 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4835 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4837 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
4838 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4840 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4841 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4842 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
4844 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
4845 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4847 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4848 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4849 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4851 /* test whether removing WS_SYSMENU destroys a system menu */
4852 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
4853 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
4855 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4856 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4858 DestroyWindow(hwnd
);
4860 /* test new window with CS_NOCLOSE style */
4861 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4862 100, 100, 200, 200, 0, 0, 0, NULL
);
4863 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4865 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4866 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4868 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4869 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4871 DestroyWindow(hwnd
);
4873 /* test new window without WS_SYSMENU style */
4874 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
4875 100, 100, 200, 200, 0, 0, 0, NULL
);
4876 ok(hwnd
!= 0, "Failed to create overlapped window\n");
4878 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4879 ok(!hmenu
, "GetSystemMenu error %d\n", GetLastError());
4881 DestroyWindow(hwnd
);
4884 /* For shown WS_OVERLAPPEDWINDOW */
4885 static const struct message WmSetIcon_1
[] = {
4886 { WM_SETICON
, sent
},
4887 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
4888 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4889 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
4893 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
4894 static const struct message WmSetIcon_2
[] = {
4895 { WM_SETICON
, sent
},
4899 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
4900 static const struct message WmInitEndSession
[] = {
4902 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4906 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
4907 static const struct message WmInitEndSession_2
[] = {
4909 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4913 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
4914 static const struct message WmInitEndSession_3
[] = {
4916 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4920 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
4921 static const struct message WmInitEndSession_4
[] = {
4923 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4927 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
4928 static const struct message WmInitEndSession_5
[] = {
4930 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
4934 static const struct message WmOptionalPaint
[] = {
4935 { WM_PAINT
, sent
|optional
},
4936 { WM_NCPAINT
, sent
|beginpaint
|optional
},
4937 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
4938 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
4942 static const struct message WmZOrder
[] = {
4943 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
4944 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
4945 { HCBT_ACTIVATE
, hook
},
4946 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
4947 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
4948 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
4949 { WM_GETTEXT
, sent
|optional
},
4950 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
4951 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
4952 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
4953 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4954 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4955 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
4956 { HCBT_SETFOCUS
, hook
},
4957 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
4958 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
4959 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
4960 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
4961 { WM_GETTEXT
, sent
|optional
},
4962 { WM_NCCALCSIZE
, sent
|optional
},
4966 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
4971 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
4976 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4977 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4979 PostMessageA(hwnd
, WM_USER
, 0, 0);
4981 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4982 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4984 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4985 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4987 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4988 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4990 PostMessageA(hwnd
, WM_USER
, 0, 0);
4992 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4993 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4995 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
4996 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4998 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
4999 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5000 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
5002 PostMessageA(hwnd
, WM_USER
, 0, 0);
5004 /* new incoming message causes it to become signaled again */
5005 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5006 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
5008 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5009 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5010 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5011 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5013 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
5014 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5015 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5016 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5018 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_INPUTAVAILABLE
);
5019 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5021 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5022 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5024 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
5025 ret
= QueueUserAPC( apc_test_proc
, GetCurrentThread(), 0 );
5026 ok(ret
, "QueueUserAPC failed %u\n", GetLastError());
5028 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, 0 );
5029 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5031 /* but even with MWMO_ALERTABLE window events are preferred */
5032 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5034 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5035 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5037 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5038 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5040 /* the APC call is still queued */
5041 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5042 ok(ret
== WAIT_IO_COMPLETION
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
5045 static void test_WM_DEVICECHANGE(HWND hwnd
)
5050 static const WPARAM wparams
[] = {0,
5051 DBT_DEVNODES_CHANGED
,
5052 DBT_QUERYCHANGECONFIG
,
5054 DBT_CONFIGCHANGECANCELED
,
5057 DBT_CONFIGMGPRIVATE
, /* 0x7fff */
5058 DBT_DEVICEARRIVAL
, /* 0x8000 */
5059 DBT_DEVICEQUERYREMOVE
,
5060 DBT_DEVICEQUERYREMOVEFAILED
,
5061 DBT_DEVICEREMOVEPENDING
,
5062 DBT_DEVICEREMOVECOMPLETE
,
5063 DBT_DEVICETYPESPECIFIC
,
5066 for (i
= 0; i
< sizeof(wparams
)/sizeof(wparams
[0]); i
++)
5068 SetLastError(0xdeadbeef);
5069 ret
= PostMessageA(hwnd
, WM_DEVICECHANGE
, wparams
[i
], 0);
5070 if (wparams
[i
] & 0x8000)
5072 ok(ret
== FALSE
, "PostMessage should returned %d\n", ret
);
5073 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY
, "PostMessage error %08x\n", GetLastError());
5077 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5078 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
5079 memset(&msg
, 0, sizeof(msg
));
5080 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5081 ok(msg
.message
== WM_DEVICECHANGE
, "got %04x instead of WM_DEVICECHANGE\n", msg
.message
);
5086 static DWORD CALLBACK
show_window_thread(LPVOID arg
)
5090 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
5091 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5096 /* Helper function to easier test SetWindowPos messages */
5097 #define test_msg_setpos( expected_list, flags, todo ) \
5098 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
5099 static void test_msg_setpos_(const struct message
*expected_list
, UINT flags
, BOOL todo
, const char *file
, int line
)
5105 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5106 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5107 ok (hwnd
!= 0, "Failed to create popup window\n");
5108 SetWindowPos(hwnd
, NULL
, 0, 0, 100, 100, flags
);
5109 ok_sequence_(expected_list
, "SetWindowPos:show_popup_first_show_window", todo
, file
, line
);
5110 DestroyWindow(hwnd
);
5113 /* test if we receive the right sequence of messages */
5114 static void test_messages(void)
5118 HWND hwnd
, hparent
, hchild
;
5119 HWND hchild2
, hbutton
;
5128 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5129 100, 100, 200, 200, 0, 0, 0, NULL
);
5130 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5131 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5133 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5134 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
5135 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
5137 /* test WM_SETREDRAW on a not visible top level window */
5138 test_WM_SETREDRAW(hwnd
);
5140 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5142 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
5143 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
5145 ok(GetActiveWindow() == hwnd
, "window should be active\n");
5146 ok(GetFocus() == hwnd
, "window should have input focus\n");
5147 ShowWindow(hwnd
, SW_HIDE
);
5149 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5151 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5152 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5154 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5156 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5157 hthread
= CreateThread(NULL
, 0, show_window_thread
, hwnd
, 0, &tid
);
5158 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
5159 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5160 CloseHandle(hthread
);
5162 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5164 ShowWindow(hwnd
, SW_SHOW
);
5166 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
5168 ShowWindow(hwnd
, SW_HIDE
);
5170 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5172 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5174 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
5177 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
5179 ShowWindow(hwnd
, SW_RESTORE
);
5181 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5185 ShowWindow(hwnd
, SW_MINIMIZE
);
5187 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE
);
5190 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
5192 ShowWindow(hwnd
, SW_RESTORE
);
5194 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5198 ShowWindow(hwnd
, SW_SHOW
);
5200 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
5202 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5203 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
5204 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
5205 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
5207 /* test WM_SETREDRAW on a visible top level window */
5208 ShowWindow(hwnd
, SW_SHOW
);
5210 test_WM_SETREDRAW(hwnd
);
5212 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
5213 test_scroll_messages(hwnd
);
5215 /* test resizing and moving */
5216 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
5217 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
5220 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
5221 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
5224 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
5225 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
5229 /* popups don't get WM_GETMINMAXINFO */
5230 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
5231 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5233 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
5234 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
5236 DestroyWindow(hwnd
);
5237 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
5239 /* Test if windows are correctly drawn when first shown */
5241 /* Visible, redraw */
5244 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5245 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5246 ok (hwnd
!= 0, "Failed to create popup window\n");
5247 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5248 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_visible", FALSE
);
5249 DestroyWindow(hwnd
);
5251 /* Invisible, show, message */
5254 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5255 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5256 ok (hwnd
!= 0, "Failed to create popup window\n");
5257 ShowWindow(hwnd
, SW_SHOW
);
5258 SendMessageW(hwnd
, WM_PAINT
, 0, 0);
5259 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_show", FALSE
);
5260 DestroyWindow(hwnd
);
5262 /* Invisible, show maximized, redraw */
5265 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5266 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5267 ok (hwnd
!= 0, "Failed to create popup window\n");
5268 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5269 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5270 ok_sequence(WmShowPopupFirstDrawSeq_2
, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE
);
5271 DestroyWindow(hwnd
);
5273 /* Test SetWindowPos */
5274 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
, FALSE
);
5275 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, 0, FALSE
);
5276 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
,
5277 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_NOZORDER
, FALSE
);
5279 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOSIZE
, FALSE
);
5280 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOMOVE
, FALSE
);
5281 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTSIZE
, FALSE
);
5282 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTMOVE
, FALSE
);
5283 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOZORDER
, FALSE
);
5285 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
, FALSE
);
5286 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTMOVE
, FALSE
);
5287 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTSIZE
, FALSE
);
5288 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOMOVE
, FALSE
);
5289 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOSIZE
, FALSE
);
5290 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOZORDER
, FALSE
);
5292 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
, FALSE
);
5293 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTMOVE
, FALSE
);
5294 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTSIZE
, FALSE
);
5295 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOMOVE
, FALSE
);
5296 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOSIZE
, FALSE
);
5297 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOZORDER
, FALSE
);
5299 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
, FALSE
);
5300 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTMOVE
, FALSE
);
5301 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTSIZE
, FALSE
);
5302 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOMOVE
, FALSE
);
5303 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOSIZE
, FALSE
);
5304 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOZORDER
, FALSE
);
5306 /* Test SetWindowPos with child windows */
5308 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5309 100, 100, 200, 200, 0, 0, 0, NULL
);
5310 ok (hparent
!= 0, "Failed to create parent window\n");
5312 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5313 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5314 ok (hchild
!= 0, "Failed to create child window\n");
5316 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5317 ok_sequence(WmFirstDrawChildSeq1
, /* Expect no messages for the child */
5318 "SetWindowPos:show_popup_first_show_window_child1", FALSE
);
5319 DestroyWindow(hchild
);
5320 DestroyWindow(hparent
);
5323 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
,
5324 100, 100, 200, 200, 0, 0, 0, NULL
);
5325 ok (hparent
!= 0, "Failed to create parent window\n");
5327 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5328 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5329 ok (hchild
!= 0, "Failed to create child window\n");
5331 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5332 ok_sequence(WmFirstDrawChildSeq2
, /* Expect child to be redrawn */
5333 "SetWindowPos:show_popup_first_show_window_child2", FALSE
);
5334 DestroyWindow(hchild
);
5335 DestroyWindow(hparent
);
5337 /* Test message sequence for extreme position and size */
5340 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5341 -10, -10, 10000, 10000, NULL
, 0, 0, NULL
);
5342 ok (hwnd
!= 0, "Failed to create popup window\n");
5343 ok_sequence(WmShowPopupExtremeLocationSeq
, "RedrawWindow:show_popup_extreme_location", TRUE
);
5344 DestroyWindow(hwnd
);
5347 /* Test child windows */
5349 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5350 100, 100, 200, 200, 0, 0, 0, NULL
);
5351 ok (hparent
!= 0, "Failed to create parent window\n");
5354 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
5355 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5356 ok (hchild
!= 0, "Failed to create child window\n");
5357 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
5358 DestroyWindow(hchild
);
5361 /* visible child window with a caption */
5362 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
5363 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
5364 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5365 ok (hchild
!= 0, "Failed to create child window\n");
5366 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
5368 trace("testing scroll APIs on a visible child window %p\n", hchild
);
5369 test_scroll_messages(hchild
);
5371 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5372 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
5374 DestroyWindow(hchild
);
5377 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5378 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5379 ok (hchild
!= 0, "Failed to create child window\n");
5380 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5382 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
5383 100, 100, 50, 50, hparent
, 0, 0, NULL
);
5384 ok (hchild2
!= 0, "Failed to create child2 window\n");
5387 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
5388 0, 100, 50, 50, hchild
, 0, 0, NULL
);
5389 ok (hbutton
!= 0, "Failed to create button window\n");
5391 /* test WM_SETREDRAW on a not visible child window */
5392 test_WM_SETREDRAW(hchild
);
5394 ShowWindow(hchild
, SW_SHOW
);
5395 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5397 /* check parent messages too */
5398 log_all_parent_messages
++;
5399 ShowWindow(hchild
, SW_HIDE
);
5400 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
5401 log_all_parent_messages
--;
5403 ShowWindow(hchild
, SW_SHOW
);
5404 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5406 ShowWindow(hchild
, SW_HIDE
);
5407 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
5409 ShowWindow(hchild
, SW_SHOW
);
5410 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5412 /* test WM_SETREDRAW on a visible child window */
5413 test_WM_SETREDRAW(hchild
);
5415 log_all_parent_messages
++;
5416 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
5417 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
5418 log_all_parent_messages
--;
5420 ShowWindow(hchild
, SW_HIDE
);
5422 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5423 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
5425 ShowWindow(hchild
, SW_HIDE
);
5427 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
5428 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
5430 /* DestroyWindow sequence below expects that a child has focus */
5434 DestroyWindow(hchild
);
5435 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
5436 DestroyWindow(hchild2
);
5437 DestroyWindow(hbutton
);
5440 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
5441 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5442 ok (hchild
!= 0, "Failed to create child popup window\n");
5443 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
5444 DestroyWindow(hchild
);
5446 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5448 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
5449 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5450 ok (hchild
!= 0, "Failed to create popup window\n");
5451 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5452 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5453 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5455 ShowWindow(hchild
, SW_SHOW
);
5456 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5458 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5459 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5461 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5462 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
5463 DestroyWindow(hchild
);
5465 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5466 * changes nothing in message sequences.
5469 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5470 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5471 ok (hchild
!= 0, "Failed to create popup window\n");
5472 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5473 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5474 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5476 ShowWindow(hchild
, SW_SHOW
);
5477 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5479 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5480 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5481 DestroyWindow(hchild
);
5484 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
5485 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5486 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5487 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
5490 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
5491 test_scroll_messages(hwnd
);
5497 SendMessageA(hwnd
, WM_NULL
, 0, 0);
5500 after_end_dialog
= TRUE
;
5501 EndDialog( hwnd
, 0 );
5502 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
5504 DestroyWindow(hwnd
);
5505 after_end_dialog
= FALSE
;
5506 test_def_id
= FALSE
;
5508 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
5509 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5511 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
5512 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
5513 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5515 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
5516 ShowWindow(hwnd
, SW_SHOW
);
5517 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
5521 ret
= DrawMenuBar(hwnd
);
5522 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
5524 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5525 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
5527 DestroyWindow(hwnd
);
5529 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_CHILD
|WS_VISIBLE
,
5530 0, 0, 100, 100, hparent
, 0, GetModuleHandleA(0), NULL
);
5531 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5534 ret
= DrawMenuBar(hwnd
);
5535 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
5537 ok_sequence(WmEmptySeq
, "DrawMenuBar for a child window", FALSE
);
5539 DestroyWindow(hwnd
);
5542 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
5543 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
5545 DestroyWindow(hparent
);
5548 /* Message sequence for SetMenu */
5549 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
5550 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %d\n", GetLastError());
5551 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
5553 hmenu
= CreateMenu();
5554 ok (hmenu
!= 0, "Failed to create menu\n");
5555 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
5556 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5557 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
5558 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5559 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5560 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
5561 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5562 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
5563 ShowWindow(hwnd
, SW_SHOW
);
5564 UpdateWindow( hwnd
);
5567 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5568 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
5569 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
5570 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
5572 UpdateWindow( hwnd
);
5575 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
5577 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5579 DestroyWindow(hwnd
);
5582 /* Message sequence for EnableWindow */
5583 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5584 100, 100, 200, 200, 0, 0, 0, NULL
);
5585 ok (hparent
!= 0, "Failed to create parent window\n");
5586 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5587 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5588 ok (hchild
!= 0, "Failed to create child window\n");
5594 EnableWindow(hparent
, FALSE
);
5595 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
5597 EnableWindow(hparent
, FALSE
);
5598 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(FALSE)", FALSE
);
5600 EnableWindow(hparent
, TRUE
);
5601 ok_sequence(WmEnableWindowSeq_3
, "EnableWindow(TRUE)", FALSE
);
5603 EnableWindow(hparent
, TRUE
);
5604 ok_sequence(WmEnableWindowSeq_4
, "EnableWindow(TRUE)", FALSE
);
5609 test_MsgWaitForMultipleObjects(hparent
);
5610 test_WM_DEVICECHANGE(hparent
);
5612 /* the following test causes an exception in user.exe under win9x */
5613 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
5615 DestroyWindow(hparent
);
5619 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
5620 /* PeekMessage(NULL) fails, but still removes the message */
5621 SetLastError(0xdeadbeef);
5622 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
5623 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
5624 GetLastError() == 0xdeadbeef, /* NT4 */
5625 "last error is %d\n", GetLastError() );
5626 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
5627 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
5629 DestroyWindow(hchild
);
5630 DestroyWindow(hparent
);
5633 /* Message sequences for WM_SETICON */
5634 trace("testing WM_SETICON\n");
5635 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5636 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5638 ShowWindow(hwnd
, SW_SHOW
);
5642 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5643 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
5645 ShowWindow(hwnd
, SW_HIDE
);
5648 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5649 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
5650 DestroyWindow(hwnd
);
5653 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
5654 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5656 ShowWindow(hwnd
, SW_SHOW
);
5660 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5661 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
5663 ShowWindow(hwnd
, SW_HIDE
);
5666 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5667 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
5670 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
5673 todo_wine
win_skip( "Message 0x3b not supported\n" );
5676 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
5677 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res
);
5678 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
5679 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
5680 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res
);
5681 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
5682 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
5683 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res
);
5686 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
5687 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
5688 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res
);
5689 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
5690 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
5691 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res
);
5693 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
5694 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
5695 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res
);
5697 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
5698 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
5699 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res
);
5702 DestroyWindow(hwnd
);
5706 static void test_setwindowpos(void)
5711 const INT winX
= 100;
5712 const INT winY
= 100;
5713 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
5715 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
5716 0, 0, winX
, winY
, 0,
5719 GetWindowRect(hwnd
, &rc
);
5720 expect(sysX
, rc
.right
);
5721 expect(winY
, rc
.bottom
);
5725 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, winX
, winY
, 0);
5726 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
5727 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %ld\n", res
);
5729 GetWindowRect(hwnd
, &rc
);
5730 expect(sysX
, rc
.right
);
5731 expect(winY
, rc
.bottom
);
5732 DestroyWindow(hwnd
);
5735 static void invisible_parent_tests(void)
5737 HWND hparent
, hchild
;
5739 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
5740 100, 100, 200, 200, 0, 0, 0, NULL
);
5741 ok (hparent
!= 0, "Failed to create parent window\n");
5744 /* test showing child with hidden parent */
5746 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5747 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5748 ok (hchild
!= 0, "Failed to create child window\n");
5749 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5751 ShowWindow( hchild
, SW_MINIMIZE
);
5752 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5753 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5754 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5759 ShowWindow( hchild
, SW_MINIMIZE
);
5760 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5762 DestroyWindow(hchild
);
5763 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5764 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5767 ShowWindow( hchild
, SW_MAXIMIZE
);
5768 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5769 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5770 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5775 ShowWindow( hchild
, SW_MAXIMIZE
);
5776 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5778 DestroyWindow(hchild
);
5779 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5780 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5783 ShowWindow( hchild
, SW_RESTORE
);
5784 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
5785 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5786 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5788 DestroyWindow(hchild
);
5789 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5790 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5793 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5794 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5795 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5796 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5801 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5802 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5804 DestroyWindow(hchild
);
5805 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5806 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5809 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
5810 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
5811 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
5812 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5813 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5815 DestroyWindow(hchild
);
5816 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5817 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5820 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5821 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5822 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5823 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5828 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5829 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5831 DestroyWindow(hchild
);
5832 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5833 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5836 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
5837 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
5838 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
5840 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5842 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5844 DestroyWindow(hchild
);
5845 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5846 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5849 ShowWindow( hchild
, SW_SHOWNA
);
5850 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5851 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5852 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5857 ShowWindow( hchild
, SW_SHOWNA
);
5858 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5860 DestroyWindow(hchild
);
5861 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5862 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5865 ShowWindow( hchild
, SW_SHOW
);
5866 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5867 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5868 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5873 ShowWindow( hchild
, SW_SHOW
);
5874 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5876 ShowWindow( hchild
, SW_HIDE
);
5877 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
5878 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5879 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5881 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5882 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
5883 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5884 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5886 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5887 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
5888 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
5889 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5891 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5893 DestroyWindow(hchild
);
5894 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
5896 DestroyWindow(hparent
);
5900 /****************** button message test *************************/
5901 #define ID_BUTTON 0x000e
5903 static const struct message WmSetFocusButtonSeq
[] =
5905 { HCBT_SETFOCUS
, hook
},
5906 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5907 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5908 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5909 { WM_SETFOCUS
, sent
|wparam
, 0 },
5910 { WM_CTLCOLORBTN
, sent
|parent
},
5911 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5912 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5915 static const struct message WmKillFocusButtonSeq
[] =
5917 { HCBT_SETFOCUS
, hook
},
5918 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5919 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5920 { WM_CTLCOLORBTN
, sent
|parent
},
5921 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5922 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5923 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5924 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5926 { WM_CTLCOLORBTN
, sent
|parent
},
5929 static const struct message WmSetFocusStaticSeq
[] =
5931 { HCBT_SETFOCUS
, hook
},
5932 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5933 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5934 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5935 { WM_SETFOCUS
, sent
|wparam
, 0 },
5936 { WM_CTLCOLORSTATIC
, sent
|parent
},
5937 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5938 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
5939 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5942 static const struct message WmKillFocusStaticSeq
[] =
5944 { HCBT_SETFOCUS
, hook
},
5945 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5946 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5947 { WM_CTLCOLORSTATIC
, sent
|parent
},
5948 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5949 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5950 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5951 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5953 { WM_CTLCOLORSTATIC
, sent
|parent
},
5956 static const struct message WmSetFocusOwnerdrawSeq
[] =
5958 { HCBT_SETFOCUS
, hook
},
5959 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5960 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5961 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5962 { WM_SETFOCUS
, sent
|wparam
, 0 },
5963 { WM_CTLCOLORBTN
, sent
|parent
},
5964 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
5965 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5966 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5969 static const struct message WmKillFocusOwnerdrawSeq
[] =
5971 { HCBT_SETFOCUS
, hook
},
5972 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5973 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5974 { WM_CTLCOLORBTN
, sent
|parent
},
5975 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
5976 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5977 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5978 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5979 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5981 { WM_CTLCOLORBTN
, sent
|parent
},
5982 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
5985 static const struct message WmLButtonDownSeq
[] =
5987 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
5988 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
5989 { HCBT_SETFOCUS
, hook
},
5990 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5991 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5992 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5993 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5994 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5995 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
5996 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5997 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6000 static const struct message WmLButtonDownStaticSeq
[] =
6002 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6003 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
6004 { HCBT_SETFOCUS
, hook
},
6005 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6006 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6007 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6008 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6009 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6010 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6011 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6012 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6015 static const struct message WmLButtonUpSeq
[] =
6017 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6018 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6019 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6020 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6021 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6022 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6025 static const struct message WmLButtonUpStaticSeq
[] =
6027 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6028 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6029 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6030 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6031 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6032 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6035 static const struct message WmLButtonUpAutoSeq
[] =
6037 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6038 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6039 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6040 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6041 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6042 { BM_SETCHECK
, sent
|defwinproc
},
6043 { WM_CTLCOLORSTATIC
, sent
|defwinproc
, 0, 0 },
6044 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6047 static const struct message WmLButtonUpBrokenSeq
[] =
6049 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6052 static const struct message WmSetFontButtonSeq
[] =
6054 { WM_SETFONT
, sent
},
6056 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6057 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6058 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
6061 static const struct message WmSetFontStaticSeq
[] =
6063 { WM_SETFONT
, sent
},
6065 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6066 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6069 static const struct message WmSetTextButtonSeq
[] =
6071 { WM_SETTEXT
, sent
},
6072 { WM_CTLCOLORBTN
, sent
|parent
},
6073 { WM_CTLCOLORBTN
, sent
|parent
},
6074 { WM_COMMAND
, sent
|parent
|optional
},
6075 { WM_DRAWITEM
, sent
|parent
|optional
},
6078 static const struct message WmSetTextStaticSeq
[] =
6080 { WM_SETTEXT
, sent
},
6081 { WM_CTLCOLORSTATIC
, sent
|parent
},
6082 { WM_CTLCOLORSTATIC
, sent
|parent
},
6085 static const struct message WmSetTextGroupSeq
[] =
6087 { WM_SETTEXT
, sent
},
6088 { WM_CTLCOLORSTATIC
, sent
|parent
},
6089 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6090 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
6093 static const struct message WmSetTextInvisibleSeq
[] =
6095 { WM_SETTEXT
, sent
},
6098 static const struct message WmSetStyleButtonSeq
[] =
6100 { BM_SETSTYLE
, sent
},
6101 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6103 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6104 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6105 { WM_CTLCOLORBTN
, sent
|parent
},
6108 static const struct message WmSetStyleStaticSeq
[] =
6110 { BM_SETSTYLE
, sent
},
6111 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6113 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6114 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6115 { WM_CTLCOLORSTATIC
, sent
|parent
},
6118 static const struct message WmSetStyleUserSeq
[] =
6120 { BM_SETSTYLE
, sent
},
6121 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6123 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6124 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6125 { WM_CTLCOLORBTN
, sent
|parent
},
6126 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
6129 static const struct message WmSetStyleOwnerdrawSeq
[] =
6131 { BM_SETSTYLE
, sent
},
6132 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6134 { WM_NCPAINT
, sent
|optional
}, /* FIXME: Wine sends it */
6135 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6136 { WM_CTLCOLORBTN
, sent
|parent
},
6137 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
6138 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6141 static const struct message WmSetStateButtonSeq
[] =
6143 { BM_SETSTATE
, sent
},
6144 { WM_CTLCOLORBTN
, sent
|parent
},
6145 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6148 static const struct message WmSetStateStaticSeq
[] =
6150 { BM_SETSTATE
, sent
},
6151 { WM_CTLCOLORSTATIC
, sent
|parent
},
6152 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6155 static const struct message WmSetStateUserSeq
[] =
6157 { BM_SETSTATE
, sent
},
6158 { WM_CTLCOLORBTN
, sent
|parent
},
6159 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
6160 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6163 static const struct message WmSetStateOwnerdrawSeq
[] =
6165 { BM_SETSTATE
, sent
},
6166 { WM_CTLCOLORBTN
, sent
|parent
},
6167 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
6168 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6171 static const struct message WmClearStateButtonSeq
[] =
6173 { BM_SETSTATE
, sent
},
6174 { WM_CTLCOLORBTN
, sent
|parent
},
6175 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
6176 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6179 static const struct message WmDisableButtonSeq
[] =
6181 { WM_LBUTTONDOWN
, sent
},
6182 { BM_SETSTATE
, sent
|defwinproc
},
6183 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6184 { WM_CTLCOLORBTN
, sent
|optional
},
6185 { WM_LBUTTONUP
, sent
},
6186 { BM_SETSTATE
, sent
|defwinproc
},
6187 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
},
6188 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6189 { BM_SETCHECK
, sent
|defwinproc
|optional
},
6190 { WM_CTLCOLORBTN
, sent
|optional
},
6191 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6192 { WM_CAPTURECHANGED
, sent
|defwinproc
},
6193 { WM_COMMAND
, sent
},
6196 static const struct message WmClearStateOwnerdrawSeq
[] =
6198 { BM_SETSTATE
, sent
},
6199 { WM_CTLCOLORBTN
, sent
|parent
},
6200 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
6201 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6204 static const struct message WmSetCheckIgnoredSeq
[] =
6206 { BM_SETCHECK
, sent
},
6207 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6210 static const struct message WmSetCheckStaticSeq
[] =
6212 { BM_SETCHECK
, sent
},
6213 { WM_CTLCOLORSTATIC
, sent
|parent
},
6214 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6218 static WNDPROC old_button_proc
;
6220 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6222 static LONG defwndproc_counter
= 0;
6224 struct recvd_message msg
;
6226 if (ignore_message( message
)) return 0;
6234 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
6236 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6242 MSG
*msg
= (MSG
*)lParam
;
6243 lParam
= MAKELPARAM(msg
->message
, msg
->wParam
);
6245 wParam
= (ULONG_PTR
)GetMenu(hwnd
);
6250 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6255 msg
.message
= message
;
6256 msg
.flags
= sent
|wparam
|lparam
;
6257 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6258 msg
.wParam
= wParam
;
6259 msg
.lParam
= lParam
;
6260 msg
.descr
= "button";
6264 defwndproc_counter
++;
6265 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
6266 defwndproc_counter
--;
6271 static void subclass_button(void)
6275 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
6277 old_button_proc
= cls
.lpfnWndProc
;
6279 cls
.hInstance
= GetModuleHandleA(NULL
);
6280 cls
.lpfnWndProc
= button_hook_proc
;
6281 cls
.lpszClassName
= "my_button_class";
6282 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6283 if (!RegisterClassA(&cls
)) assert(0);
6286 static void test_button_messages(void)
6292 const struct message
*setfocus
;
6293 const struct message
*killfocus
;
6294 const struct message
*setstyle
;
6295 const struct message
*setstate
;
6296 const struct message
*clearstate
;
6297 const struct message
*setcheck
;
6298 const struct message
*lbuttondown
;
6299 const struct message
*lbuttonup
;
6300 const struct message
*setfont
;
6301 const struct message
*settext
;
6303 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6304 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6305 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6306 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6307 WmSetTextButtonSeq
},
6308 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
6309 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6310 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6311 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6312 WmSetTextButtonSeq
},
6313 { BS_CHECKBOX
, DLGC_BUTTON
,
6314 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6315 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6316 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6317 WmSetTextStaticSeq
},
6318 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
6319 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6320 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6321 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6322 WmSetTextStaticSeq
},
6323 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6324 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6325 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6326 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6327 WmSetTextStaticSeq
},
6328 { BS_3STATE
, DLGC_BUTTON
,
6329 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6330 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6331 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6332 WmSetTextStaticSeq
},
6333 { BS_AUTO3STATE
, DLGC_BUTTON
,
6334 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6335 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6336 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6337 WmSetTextStaticSeq
},
6338 { BS_GROUPBOX
, DLGC_STATIC
,
6339 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6340 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
,
6341 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6342 WmSetTextGroupSeq
},
6343 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6344 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
6345 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
,
6346 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6347 WmSetTextButtonSeq
},
6348 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6349 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6350 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6351 NULL
/* avoid infinite loop */, WmLButtonUpBrokenSeq
, WmSetFontStaticSeq
,
6352 WmSetTextStaticSeq
},
6353 { BS_OWNERDRAW
, DLGC_BUTTON
,
6354 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
6355 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
,
6356 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6357 WmSetTextButtonSeq
},
6359 LOGFONTA logfont
= { 0 };
6360 HFONT zfont
, hfont2
;
6365 /* selection with VK_SPACE should capture button window */
6366 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
6367 0, 0, 50, 14, 0, 0, 0, NULL
);
6368 ok(hwnd
!= 0, "Failed to create button window\n");
6371 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
6372 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6373 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
6374 DestroyWindow(hwnd
);
6378 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6379 100, 100, 200, 200, 0, 0, 0, NULL
);
6380 ok(parent
!= 0, "Failed to create parent window\n");
6382 memset(&logfont
, 0, sizeof(logfont
));
6383 logfont
.lfHeight
= -12;
6384 logfont
.lfWeight
= FW_NORMAL
;
6385 strcpy(logfont
.lfFaceName
, "Tahoma");
6387 hfont2
= CreateFontIndirectA(&logfont
);
6388 ok(hfont2
!= NULL
, "Failed to create Tahoma font\n");
6390 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
6398 trace("button style %08x\n", button
[i
].style
);
6400 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
6401 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
6402 ok(hwnd
!= 0, "Failed to create button window\n");
6404 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6405 style
&= ~(WS_CHILD
| BS_NOTIFY
);
6406 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6407 if (button
[i
].style
== BS_USERBUTTON
)
6408 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %x\n", style
);
6410 ok(style
== button
[i
].style
, "expected style %x got %x\n", button
[i
].style
, style
);
6412 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
6413 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
6415 ShowWindow(hwnd
, SW_SHOW
);
6422 log_all_parent_messages
++;
6424 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6426 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6427 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6428 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
6431 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6432 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6433 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
6435 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6437 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
6438 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6439 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6440 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
6442 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6443 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
6444 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
6445 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6447 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6448 ok(state
== 0, "expected state 0, got %04x\n", state
);
6452 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
6453 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6454 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6455 ok_sequence(button
[i
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
6457 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6458 ok(state
== 0x0004, "expected state 0x0004, got %04x\n", state
);
6460 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6461 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6462 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6466 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
6467 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6468 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6469 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
6471 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6472 ok(state
== 0, "expected state 0, got %04x\n", state
);
6474 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6475 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6476 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6478 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6479 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
6483 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
6484 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6485 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6486 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
6488 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6489 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
6491 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6492 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6493 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6497 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
6498 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6499 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6500 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
6502 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 1");
6503 sprintf(desc
, "button[%i]: WM_SETTEXT on a visible button", i
);
6504 ok_sequence(button
[i
].settext
, desc
, FALSE
);
6506 ShowWindow(hwnd
, SW_HIDE
);
6510 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 2");
6511 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6512 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6514 ShowWindow(hwnd
, SW_SHOW
);
6515 ShowWindow(parent
, SW_HIDE
);
6519 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 3");
6520 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6521 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6523 ShowWindow(parent
, SW_SHOW
);
6526 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6527 if (button
[i
].style
== BS_PUSHBUTTON
||
6528 button
[i
].style
== BS_DEFPUSHBUTTON
||
6529 button
[i
].style
== BS_GROUPBOX
||
6530 button
[i
].style
== BS_USERBUTTON
||
6531 button
[i
].style
== BS_OWNERDRAW
)
6532 ok(state
== BST_UNCHECKED
, "expected check 0, got %04x\n", state
);
6534 ok(state
== BST_CHECKED
, "expected check 1, got %04x\n", state
);
6536 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6537 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6538 if (button
[i
].style
== BS_RADIOBUTTON
||
6539 button
[i
].style
== BS_AUTORADIOBUTTON
)
6540 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04x | WS_TABSTOP got %04x\n", button
[i
].style
, style
);
6542 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6544 log_all_parent_messages
--;
6546 DestroyWindow(hwnd
);
6548 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
6549 0, 0, 50, 14, 0, 0, 0, NULL
);
6550 ok(hwnd
!= 0, "Failed to create button window\n");
6552 SetForegroundWindow(hwnd
);
6555 SetActiveWindow(hwnd
);
6559 if (button
[i
].lbuttondown
)
6561 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
6562 sprintf(desc
, "button[%i]: WM_LBUTTONDOWN on a button", i
);
6563 ok_sequence(button
[i
].lbuttondown
, desc
, FALSE
);
6566 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
6567 sprintf(desc
, "button[%i]: WM_LBUTTONUP on a button", i
);
6568 ok_sequence(button
[i
].lbuttonup
, desc
, FALSE
);
6571 zfont
= GetStockObject(DEFAULT_GUI_FONT
);
6572 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
6574 sprintf(desc
, "button[%i]: WM_SETFONT on a button", i
);
6575 ok_sequence(button
[i
].setfont
, desc
, FALSE
);
6577 /* Test that original font is not selected back after painting */
6578 hdc
= CreateCompatibleDC(0);
6580 prevfont
= SelectObject(hdc
, hfont2
);
6581 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
6582 SendMessageA(hwnd
, WM_PRINTCLIENT
, (WPARAM
)hdc
, 0);
6584 ok(GetStockObject(SYSTEM_FONT
) == GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i
);
6585 SelectObject(hdc
, prevfont
);
6587 prevfont
= SelectObject(hdc
, hfont2
);
6588 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
6589 SendMessageA(hwnd
, WM_PAINT
, (WPARAM
)hdc
, 0);
6591 ok(GetStockObject(SYSTEM_FONT
) == GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PAINT\n", i
);
6592 SelectObject(hdc
, prevfont
);
6596 DestroyWindow(hwnd
);
6599 DeleteObject(hfont2
);
6600 DestroyWindow(parent
);
6602 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
6604 parent
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6605 100, 100, 200, 200, 0, 0, 0, NULL
);
6606 ok (hwnd
!= 0, "Failed to create overlapped window\n");
6608 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON
| WS_VISIBLE
| WS_CHILD
,
6609 0, 0, 50, 14, parent
, 0, 0, NULL
);
6611 EnableWindow(hwnd
, FALSE
);
6613 SendMessageA(hwnd
, WM_LBUTTONDOWN
, MK_LBUTTON
, 0);
6614 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
6615 ok_sequence(WmDisableButtonSeq
, "Mouseclick on a disabled button", FALSE
);
6617 DestroyWindow(hwnd
);
6618 DestroyWindow(parent
);
6621 #define ID_RADIO1 501
6622 #define ID_RADIO2 502
6623 #define ID_RADIO3 503
6626 static const struct message auto_radio_button_BM_CLICK
[] =
6628 { BM_CLICK
, sent
|wparam
|lparam
, 0, 0 },
6629 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6630 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
6631 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
6632 { WM_CTLCOLORSTATIC
, sent
|parent
},
6633 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6634 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6635 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
6636 { WM_CTLCOLORSTATIC
, sent
|parent
},
6637 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6638 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
6639 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
6640 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
6641 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO1
},
6642 { WM_CTLCOLORSTATIC
, sent
|parent
},
6643 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6644 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
6645 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO3
},
6646 { WM_CTLCOLORSTATIC
, sent
|parent
},
6647 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6648 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
6649 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6650 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6651 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO2
, BN_CLICKED
) },
6652 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6653 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6654 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6658 static const struct message auto_radio_button_VK_UP_child
[] =
6660 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_UP
, 0 },
6661 { WM_KEYUP
, sent
|wparam
|lparam
, VK_UP
, 0 },
6665 static const struct message auto_radio_button_VK_UP_parent
[] =
6667 { WM_KEYDOWN
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
6668 { WM_KEYUP
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
6672 static const struct message auto_radio_button_VK_UP_dialog
[] =
6674 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6676 /* optional trailer seen on some windows setups */
6677 { WM_CHANGEUISTATE
, sent
|optional
},
6678 { WM_UPDATEUISTATE
, 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_CTLCOLORSTATIC
, sent
|parent
|optional
},
6697 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6698 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6699 { WM_UPDATEUISTATE
, sent
|optional
},
6700 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6701 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6702 { WM_UPDATEUISTATE
, sent
|optional
},
6703 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
6704 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
6705 { WM_UPDATEUISTATE
, sent
|optional
},
6706 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6707 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
6711 static const struct message auto_radio_button_VK_DOWN_dialog
[] =
6713 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6714 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
6715 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6716 { HCBT_SETFOCUS
, hook
},
6717 { WM_KILLFOCUS
, sent
, 0, 0 },
6718 { WM_CTLCOLORSTATIC
, sent
|parent
},
6719 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO3
, BN_KILLFOCUS
) },
6720 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6721 { WM_SETFOCUS
, sent
, 0, 0 },
6722 { WM_CTLCOLORSTATIC
, sent
|parent
},
6723 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_SETFOCUS
) },
6724 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
6725 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6726 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6727 { DM_GETDEFID
, sent
|parent
, 0, 0 },
6728 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
6729 { BM_CLICK
, sent
|wparam
|lparam
, 1, 0 },
6730 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6731 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
6732 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
6733 { WM_CTLCOLORSTATIC
, sent
|parent
},
6734 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6735 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6736 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO1
},
6737 { WM_CTLCOLORSTATIC
, sent
|parent
},
6738 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6739 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
6740 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
6741 { WM_CTLCOLORSTATIC
, sent
|parent
},
6742 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6743 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
6744 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO3
},
6745 { WM_CTLCOLORSTATIC
, sent
|parent
},
6746 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6747 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
6748 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
6749 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
6750 { WM_CTLCOLORSTATIC
, sent
|parent
},
6751 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6752 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
6753 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
6754 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
6755 { WM_NCHITTEST
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6756 { WM_SETCURSOR
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6757 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
6759 { WM_CTLCOLORSTATIC
, sent
|parent
},
6763 static const struct message auto_radio_button_VK_DOWN_radio3
[] =
6765 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
6766 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO2
},
6767 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO3
},
6768 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6769 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
6770 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6771 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
6772 { WM_GETDLGCODE
, sent
|wparam
|lparam
|parent
, 0, 0 },
6773 { WM_USER
, sent
|parent
, 0, 0 },
6774 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
6778 static const struct message auto_radio_button_VK_UP_radio1
[] =
6780 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
6784 static INT_PTR WINAPI
radio_test_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
6786 ParentMsgCheckProcA(hwnd
, msg
, wp
, lp
);
6790 static void test_autoradio_BM_CLICK(void)
6792 HWND parent
, radio1
, radio2
, radio3
;
6799 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc
, 0);
6800 ok(parent
!= 0, "failed to create parent window\n");
6802 radio1
= GetDlgItem(parent
, ID_RADIO1
);
6803 radio2
= GetDlgItem(parent
, ID_RADIO2
);
6804 radio3
= GetDlgItem(parent
, ID_RADIO3
);
6806 /* this avoids focus messages in the generated sequence */
6812 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6813 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6814 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6815 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6816 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6817 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6819 SendMessageA(radio1
, BM_SETCHECK
, BST_CHECKED
, 0);
6821 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6822 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6823 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6824 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6825 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6826 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6828 SendMessageA(radio2
, BM_SETCHECK
, BST_CHECKED
, 0);
6830 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6831 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6832 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6833 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6834 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6835 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6837 SendMessageA(radio3
, BM_SETCHECK
, BST_CHECKED
, 0);
6839 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6840 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6841 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6842 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6843 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6844 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6846 GetWindowRect(radio2
, &rc
);
6847 SetCursorPos(rc
.left
+1, rc
.top
+1);
6852 log_all_parent_messages
++;
6854 SendMessageA(radio2
, BM_CLICK
, 0, 0);
6855 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6856 ok_sequence(auto_radio_button_BM_CLICK
, "BM_CLICK on auto-radio button", FALSE
);
6858 log_all_parent_messages
--;
6860 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6861 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6862 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6863 ok(ret
== BST_CHECKED
, "got %08x\n", ret
);
6864 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6865 ok(ret
== BST_UNCHECKED
, "got %08x\n", ret
);
6867 DestroyWindow(parent
);
6870 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)
6871 static void test_radio_dbg(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
, int line
)
6875 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
6876 ok_(__FILE__
,line
)(ret
== state1
? BST_CHECKED
: BST_UNCHECKED
, "got %08x\n", ret
);
6877 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
6878 ok_(__FILE__
,line
)(ret
== state2
? BST_CHECKED
: BST_UNCHECKED
, "got %08x\n", ret
);
6879 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
6880 ok_(__FILE__
,line
)(ret
== state3
? BST_CHECKED
: BST_UNCHECKED
, "got %08x\n", ret
);
6883 static void set_radio(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
)
6885 SendMessageA(radio1
, BM_SETCHECK
, state1
? BST_CHECKED
: BST_UNCHECKED
, 0);
6886 SendMessageA(radio2
, BM_SETCHECK
, state2
? BST_CHECKED
: BST_UNCHECKED
, 0);
6887 SendMessageA(radio3
, BM_SETCHECK
, state3
? BST_CHECKED
: BST_UNCHECKED
, 0);
6890 static void test_autoradio_kbd_move(void)
6892 HWND parent
, radio1
, radio2
, radio3
, hwnd
;
6899 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc
, 0);
6900 ok(parent
!= 0, "failed to create parent window\n");
6902 radio1
= GetDlgItem(parent
, ID_RADIO1
);
6903 radio2
= GetDlgItem(parent
, ID_RADIO2
);
6904 radio3
= GetDlgItem(parent
, ID_RADIO3
);
6909 test_radio(radio1
, 0, radio2
, 0, radio3
, 0);
6910 set_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6911 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6918 log_all_parent_messages
++;
6920 SendMessageA(radio3
, WM_KEYDOWN
, VK_UP
, 0);
6921 SendMessageA(radio3
, WM_KEYUP
, VK_UP
, 0);
6922 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6923 ok_sequence(auto_radio_button_VK_UP_child
, "press/release VK_UP on auto-radio button", FALSE
);
6925 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6930 DefDlgProcA(parent
, WM_KEYDOWN
, VK_UP
, 0);
6931 DefDlgProcA(parent
, WM_KEYUP
, VK_UP
, 0);
6932 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6933 ok_sequence(auto_radio_button_VK_UP_parent
, "press/release VK_UP on dialog", FALSE
);
6935 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6938 GetWindowRect(radio3
, &rc
);
6944 msg
.message
= WM_KEYDOWN
;
6947 msg
.pt
.x
= rc
.left
+ 1;
6948 msg
.pt
.y
= rc
.top
+ 1;
6949 ret
= IsDialogMessageA(parent
, &msg
);
6950 ok(ret
, "IsDialogMessage should return TRUE\n");
6951 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6952 if (0) /* actual message sequence is different on every run in some Windows setups */
6953 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #1", FALSE
);
6954 /* what really matters is that nothing has changed */
6955 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
6957 set_radio(radio1
, 0, radio2
, 1, radio3
, 1);
6958 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
6963 ret
= IsDialogMessageA(parent
, &msg
);
6964 ok(ret
, "IsDialogMessage should return TRUE\n");
6965 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6966 if (0) /* actual message sequence is different on every run in some Windows setups */
6967 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #2", FALSE
);
6968 /* what really matters is that nothing has changed */
6969 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
6971 /* switch from radio3 ro radio1 */
6973 GetWindowRect(radio3
, &rc
);
6979 msg
.message
= WM_KEYDOWN
;
6980 msg
.wParam
= VK_DOWN
;
6982 msg
.pt
.x
= rc
.left
+ 1;
6983 msg
.pt
.y
= rc
.top
+ 1;
6984 ret
= IsDialogMessageA(parent
, &msg
);
6985 ok(ret
, "IsDialogMessage should return TRUE\n");
6986 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6987 ok_sequence(auto_radio_button_VK_DOWN_dialog
, "IsDialogMessage(VK_DOWN)", TRUE
);
6989 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
6992 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
6993 GetWindowRect(radio1
, &rc
);
6996 msg
.message
= WM_KEYDOWN
;
6997 msg
.wParam
= VK_DOWN
;
6999 msg
.pt
.x
= rc
.left
+ 1;
7000 msg
.pt
.y
= rc
.top
+ 1;
7001 ret
= IsDialogMessageA(parent
, &msg
);
7002 ok(ret
, "IsDialogMessage should return TRUE\n");
7003 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7004 ok_sequence(auto_radio_button_VK_DOWN_radio3
, "down to radio3", TRUE
);
7006 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7009 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7015 msg
.message
= WM_KEYDOWN
;
7018 msg
.pt
.x
= rc
.left
+ 1;
7019 msg
.pt
.y
= rc
.top
+ 1;
7020 ret
= IsDialogMessageA(parent
, &msg
);
7021 ok(ret
, "IsDialogMessage should return TRUE\n");
7022 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7023 ok_sequence(auto_radio_button_VK_UP_radio1
, "up to radio1", TRUE
);
7025 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7028 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7034 msg
.message
= WM_KEYDOWN
;
7037 msg
.pt
.x
= rc
.left
+ 1;
7038 msg
.pt
.y
= rc
.top
+ 1;
7039 ret
= IsDialogMessageA(parent
, &msg
);
7040 ok(ret
, "IsDialogMessage should return TRUE\n");
7041 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7042 if (0) /* actual message sequence is different on every run in some Windows setups */
7043 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #3", FALSE
);
7044 /* what really matters is that nothing has changed */
7045 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7047 log_all_parent_messages
--;
7049 DestroyWindow(parent
);
7052 /****************** static message test *************************/
7053 static const struct message WmSetFontStaticSeq2
[] =
7055 { WM_SETFONT
, sent
},
7056 { WM_PAINT
, sent
|defwinproc
|optional
},
7057 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
7058 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
7062 static WNDPROC old_static_proc
;
7064 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7066 static LONG defwndproc_counter
= 0;
7068 struct recvd_message msg
;
7070 if (ignore_message( message
)) return 0;
7073 msg
.message
= message
;
7074 msg
.flags
= sent
|wparam
|lparam
;
7075 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7076 msg
.wParam
= wParam
;
7077 msg
.lParam
= lParam
;
7078 msg
.descr
= "static";
7081 defwndproc_counter
++;
7082 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
7083 defwndproc_counter
--;
7088 static void subclass_static(void)
7092 if (!GetClassInfoA(0, "static", &cls
)) assert(0);
7094 old_static_proc
= cls
.lpfnWndProc
;
7096 cls
.hInstance
= GetModuleHandleA(NULL
);
7097 cls
.lpfnWndProc
= static_hook_proc
;
7098 cls
.lpszClassName
= "my_static_class";
7099 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7100 if (!RegisterClassA(&cls
)) assert(0);
7103 static void test_static_messages(void)
7105 /* FIXME: make as comprehensive as the button message test */
7110 const struct message
*setfont
;
7112 { SS_LEFT
, DLGC_STATIC
,
7113 WmSetFontStaticSeq2
}
7121 for (i
= 0; i
< sizeof(static_ctrl
)/sizeof(static_ctrl
[0]); i
++)
7123 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
7124 0, 0, 50, 14, 0, 0, 0, NULL
);
7125 ok(hwnd
!= 0, "Failed to create static window\n");
7127 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
7128 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
7130 ShowWindow(hwnd
, SW_SHOW
);
7135 trace("static style %08x\n", static_ctrl
[i
].style
);
7136 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
7137 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
7139 DestroyWindow(hwnd
);
7143 /****************** ComboBox message test *************************/
7144 #define ID_COMBOBOX 0x000f
7146 static const struct message WmKeyDownComboSeq
[] =
7148 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7149 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
7150 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
7151 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
7152 { WM_CTLCOLOREDIT
, sent
|parent
},
7153 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7157 static const struct message WmSetPosComboSeq
[] =
7159 { WM_WINDOWPOSCHANGING
, sent
},
7160 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
7161 { WM_CHILDACTIVATE
, sent
},
7162 { WM_WINDOWPOSCHANGED
, sent
},
7163 { WM_MOVE
, sent
|defwinproc
},
7164 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7165 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
7166 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
7167 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
7168 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7172 static const struct message WMSetFocusComboBoxSeq
[] =
7174 { WM_SETFOCUS
, sent
},
7175 { WM_KILLFOCUS
, sent
|parent
},
7176 { WM_SETFOCUS
, sent
},
7177 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7178 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7179 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7180 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7181 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7185 static const struct message SetFocusButtonSeq
[] =
7187 { WM_KILLFOCUS
, sent
},
7188 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7189 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7190 { WM_LBUTTONUP
, sent
|defwinproc
},
7191 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7192 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7193 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7194 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7195 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7196 { WM_CTLCOLORBTN
, sent
|parent
},
7200 static const struct message SetFocusComboBoxSeq
[] =
7202 { WM_CTLCOLORBTN
, sent
|parent
},
7203 { WM_SETFOCUS
, sent
},
7204 { WM_KILLFOCUS
, sent
|defwinproc
},
7205 { WM_SETFOCUS
, sent
},
7206 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7207 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7208 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7209 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7210 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7214 static const struct message SetFocusButtonSeq2
[] =
7216 { WM_KILLFOCUS
, sent
},
7217 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7218 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7219 { WM_LBUTTONUP
, sent
|defwinproc
},
7220 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7221 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7222 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
7223 { WM_CTLCOLOREDIT
, sent
|parent
},
7224 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7225 { WM_CTLCOLORBTN
, sent
|parent
},
7229 static WNDPROC old_combobox_proc
, edit_window_proc
;
7231 static LRESULT CALLBACK
combobox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7233 static LONG defwndproc_counter
= 0;
7235 struct recvd_message msg
;
7237 /* do not log painting messages */
7238 if (message
!= WM_PAINT
&&
7239 message
!= WM_NCPAINT
&&
7240 message
!= WM_SYNCPAINT
&&
7241 message
!= WM_ERASEBKGND
&&
7242 message
!= WM_NCHITTEST
&&
7243 message
!= WM_GETTEXT
&&
7244 !ignore_message( message
))
7247 msg
.message
= message
;
7248 msg
.flags
= sent
|wparam
|lparam
;
7249 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7250 msg
.wParam
= wParam
;
7251 msg
.lParam
= lParam
;
7252 msg
.descr
= "combo";
7256 defwndproc_counter
++;
7257 ret
= CallWindowProcA(edit_window_proc
, hwnd
, message
, wParam
, lParam
);
7258 defwndproc_counter
--;
7263 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7265 static LONG defwndproc_counter
= 0;
7267 struct recvd_message msg
;
7269 /* do not log painting messages */
7270 if (message
!= WM_PAINT
&&
7271 message
!= WM_NCPAINT
&&
7272 message
!= WM_SYNCPAINT
&&
7273 message
!= WM_ERASEBKGND
&&
7274 message
!= WM_NCHITTEST
&&
7275 message
!= WM_GETTEXT
&&
7276 !ignore_message( message
))
7279 msg
.message
= message
;
7280 msg
.flags
= sent
|wparam
|lparam
;
7281 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7282 msg
.wParam
= wParam
;
7283 msg
.lParam
= lParam
;
7284 msg
.descr
= "combo";
7288 defwndproc_counter
++;
7289 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
7290 defwndproc_counter
--;
7295 static void subclass_combobox(void)
7299 if (!GetClassInfoA(0, "ComboBox", &cls
)) assert(0);
7301 old_combobox_proc
= cls
.lpfnWndProc
;
7303 cls
.hInstance
= GetModuleHandleA(NULL
);
7304 cls
.lpfnWndProc
= combobox_hook_proc
;
7305 cls
.lpszClassName
= "my_combobox_class";
7306 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7307 if (!RegisterClassA(&cls
)) assert(0);
7310 static void test_combobox_messages(void)
7312 HWND parent
, combo
, button
, edit
;
7314 BOOL (WINAPI
*pGetComboBoxInfo
)(HWND
, PCOMBOBOXINFO
);
7315 COMBOBOXINFO cbInfo
;
7318 subclass_combobox();
7320 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7321 100, 100, 200, 200, 0, 0, 0, NULL
);
7322 ok(parent
!= 0, "Failed to create parent window\n");
7325 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
7326 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
7327 ok(combo
!= 0, "Failed to create combobox window\n");
7329 UpdateWindow(combo
);
7331 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
7332 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", ret
);
7334 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
7335 ok(ret
== 0, "expected 0, got %ld\n", ret
);
7336 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
7337 ok(ret
== 1, "expected 1, got %ld\n", ret
);
7338 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
7339 ok(ret
== 2, "expected 2, got %ld\n", ret
);
7341 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
7345 log_all_parent_messages
++;
7346 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
7347 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
7348 log_all_parent_messages
--;
7349 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
7352 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
7353 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
7355 DestroyWindow(combo
);
7356 DestroyWindow(parent
);
7358 /* Start again. Test combobox text selection when getting and losing focus */
7359 pGetComboBoxInfo
= (void *)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
7360 if (!pGetComboBoxInfo
)
7362 win_skip("GetComboBoxInfo is not available\n");
7366 parent
= CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7367 10, 10, 300, 300, NULL
, NULL
, NULL
, NULL
);
7368 ok(parent
!= 0, "Failed to create parent window\n");
7370 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWN
,
7371 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
7372 ok(combo
!= 0, "Failed to create combobox window\n");
7374 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
7375 SetLastError(0xdeadbeef);
7376 res
= pGetComboBoxInfo(combo
, &cbInfo
);
7377 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError());
7378 edit
= cbInfo
.hwndItem
;
7380 edit_window_proc
= (WNDPROC
)SetWindowLongPtrA(edit
, GWLP_WNDPROC
, (ULONG_PTR
)combobox_subclass_proc
);
7382 button
= CreateWindowExA(0, "Button", "OK", WS_CHILD
| WS_VISIBLE
| BS_DEFPUSHBUTTON
,
7383 5, 50, 100, 20, parent
, NULL
,
7384 (HINSTANCE
)GetWindowLongPtrA(parent
, GWLP_HINSTANCE
), NULL
);
7385 ok(button
!= 0, "Failed to create button window\n");
7388 log_all_parent_messages
++;
7389 SendMessageA(combo
, WM_SETFOCUS
, 0, (LPARAM
)edit
);
7390 log_all_parent_messages
--;
7391 ok_sequence(WMSetFocusComboBoxSeq
, "WM_SETFOCUS on a ComboBox", TRUE
);
7394 log_all_parent_messages
++;
7396 log_all_parent_messages
--;
7397 ok_sequence(SetFocusButtonSeq
, "SetFocus on a Button", TRUE
);
7399 SendMessageA(combo
, WM_SETTEXT
, 0, (LPARAM
)"Wine Test");
7402 log_all_parent_messages
++;
7404 log_all_parent_messages
--;
7405 ok_sequence(SetFocusComboBoxSeq
, "SetFocus on a ComboBox", TRUE
);
7408 log_all_parent_messages
++;
7410 log_all_parent_messages
--;
7411 ok_sequence(SetFocusButtonSeq2
, "SetFocus on a Button (2)", TRUE
);
7413 DestroyWindow(button
);
7414 DestroyWindow(combo
);
7415 DestroyWindow(parent
);
7418 /****************** WM_IME_KEYDOWN message test *******************/
7420 static const struct message WmImeKeydownMsgSeq_0
[] =
7422 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
7423 { WM_CHAR
, wparam
, 'A' },
7427 static const struct message WmImeKeydownMsgSeq_1
[] =
7429 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
7430 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
7434 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7436 struct recvd_message msg
;
7439 msg
.message
= message
;
7440 msg
.flags
= wparam
|lparam
;
7441 msg
.wParam
= wParam
;
7442 msg
.lParam
= lParam
;
7443 msg
.descr
= "wmime_keydown";
7446 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7449 static void register_wmime_keydown_class(void)
7453 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
7454 cls
.lpfnWndProc
= wmime_keydown_procA
;
7455 cls
.hInstance
= GetModuleHandleA(0);
7456 cls
.lpszClassName
= "wmime_keydown_class";
7457 if (!RegisterClassA(&cls
)) assert(0);
7460 static void test_wmime_keydown_message(void)
7465 trace("Message sequences by WM_IME_KEYDOWN\n");
7467 register_wmime_keydown_class();
7468 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
7469 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
7474 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
7475 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
7476 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
7478 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
7480 TranslateMessage(&msg
);
7481 DispatchMessageA(&msg
);
7483 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
7485 DestroyWindow(hwnd
);
7488 /************* painting message test ********************/
7490 void dump_region(HRGN hrgn
)
7493 RGNDATA
*data
= NULL
;
7498 printf( "null region\n" );
7501 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
7502 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
7503 GetRegionData( hrgn
, size
, data
);
7504 printf("%d rects:", data
->rdh
.nCount
);
7505 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
7506 printf( " %s", wine_dbgstr_rect( rect
));
7508 HeapFree( GetProcessHeap(), 0, data
);
7511 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
7515 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
7516 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
7518 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
7519 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
7520 if (ret
== NULLREGION
)
7522 ok( !hrgn
, "Update region shouldn't be empty\n" );
7526 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
7528 ok( 0, "Regions are different\n" );
7529 if (winetest_debug
> 0)
7531 printf( "Update region: " );
7532 dump_region( update
);
7533 printf( "Wanted region: " );
7534 dump_region( hrgn
);
7538 GetRgnBox( update
, &r1
);
7539 GetUpdateRect( hwnd
, &r2
, FALSE
);
7540 ok( EqualRect( &r1
, &r2
), "Rectangles are different: %s / %s\n", wine_dbgstr_rect( &r1
),
7541 wine_dbgstr_rect( &r2
));
7543 DeleteObject( tmp
);
7544 DeleteObject( update
);
7547 static const struct message WmInvalidateRgn
[] = {
7548 { WM_NCPAINT
, sent
},
7549 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7553 static const struct message WmGetUpdateRect
[] = {
7554 { WM_NCPAINT
, sent
},
7555 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7560 static const struct message WmInvalidateFull
[] = {
7561 { WM_NCPAINT
, sent
|wparam
, 1 },
7562 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7566 static const struct message WmInvalidateErase
[] = {
7567 { WM_NCPAINT
, sent
|wparam
, 1 },
7568 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7569 { WM_ERASEBKGND
, sent
},
7573 static const struct message WmInvalidatePaint
[] = {
7575 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
7576 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7580 static const struct message WmInvalidateErasePaint
[] = {
7582 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
7583 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7584 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7588 static const struct message WmInvalidateErasePaint2
[] = {
7590 { WM_NCPAINT
, sent
|beginpaint
},
7591 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7592 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7596 static const struct message WmErase
[] = {
7597 { WM_ERASEBKGND
, sent
},
7601 static const struct message WmPaint
[] = {
7606 static const struct message WmParentOnlyPaint
[] = {
7607 { WM_PAINT
, sent
|parent
},
7611 static const struct message WmInvalidateParent
[] = {
7612 { WM_NCPAINT
, sent
|parent
},
7613 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
7614 { WM_ERASEBKGND
, sent
|parent
},
7618 static const struct message WmInvalidateParentChild
[] = {
7619 { WM_NCPAINT
, sent
|parent
},
7620 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
7621 { WM_ERASEBKGND
, sent
|parent
},
7622 { WM_NCPAINT
, sent
},
7623 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7624 { WM_ERASEBKGND
, sent
},
7628 static const struct message WmInvalidateParentChild2
[] = {
7629 { WM_ERASEBKGND
, sent
|parent
},
7630 { WM_NCPAINT
, sent
},
7631 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7632 { WM_ERASEBKGND
, sent
},
7636 static const struct message WmParentPaint
[] = {
7637 { WM_PAINT
, sent
|parent
},
7642 static const struct message WmParentPaintNc
[] = {
7643 { WM_PAINT
, sent
|parent
},
7645 { WM_NCPAINT
, sent
|beginpaint
},
7646 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7647 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7651 static const struct message WmChildPaintNc
[] = {
7653 { WM_NCPAINT
, sent
|beginpaint
},
7654 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7655 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7659 static const struct message WmParentErasePaint
[] = {
7660 { WM_PAINT
, sent
|parent
},
7661 { WM_NCPAINT
, sent
|parent
|beginpaint
},
7662 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
7663 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
7665 { WM_NCPAINT
, sent
|beginpaint
},
7666 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7667 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7671 static const struct message WmParentOnlyNcPaint
[] = {
7672 { WM_PAINT
, sent
|parent
},
7673 { WM_NCPAINT
, sent
|parent
|beginpaint
},
7674 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
7678 static const struct message WmSetParentStyle
[] = {
7679 { WM_STYLECHANGING
, sent
|parent
},
7680 { WM_STYLECHANGED
, sent
|parent
},
7684 static void test_paint_messages(void)
7690 HWND hparent
, hchild
;
7691 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
7692 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
7693 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
7694 100, 100, 200, 200, 0, 0, 0, NULL
);
7695 ok (hwnd
!= 0, "Failed to create overlapped window\n");
7697 ShowWindow( hwnd
, SW_SHOW
);
7698 UpdateWindow( hwnd
);
7702 check_update_rgn( hwnd
, 0 );
7703 SetRectRgn( hrgn
, 10, 10, 20, 20 );
7704 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7705 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7706 check_update_rgn( hwnd
, hrgn
);
7707 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
7708 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
7709 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7710 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
7711 check_update_rgn( hwnd
, hrgn
);
7712 /* validate everything */
7713 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7714 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7715 check_update_rgn( hwnd
, 0 );
7717 /* test empty region */
7718 SetRectRgn( hrgn
, 10, 10, 10, 15 );
7719 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7720 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7721 check_update_rgn( hwnd
, 0 );
7722 /* test empty rect */
7723 SetRect( &rect
, 10, 10, 10, 15 );
7724 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
7725 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7726 check_update_rgn( hwnd
, 0 );
7728 /* flush pending messages */
7732 GetClientRect( hwnd
, &rect
);
7733 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
7734 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
7735 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
7737 trace("testing InvalidateRect(0, NULL, FALSE)\n");
7738 SetRectEmpty( &rect
);
7739 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) should fail\n");
7740 check_update_rgn( hwnd
, hrgn
);
7741 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7743 ok_sequence( WmPaint
, "Paint", FALSE
);
7744 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7745 check_update_rgn( hwnd
, 0 );
7747 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
7748 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
7750 trace("testing ValidateRect(0, NULL)\n");
7751 SetRectEmpty( &rect
);
7752 if (ValidateRect(0, &rect
) && /* not supported on Win9x */
7753 GetUpdateRect(hwnd
, NULL
, FALSE
)) /* or >= Win 8 */
7755 check_update_rgn( hwnd
, hrgn
);
7756 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7758 ok_sequence( WmPaint
, "Paint", FALSE
);
7759 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7760 check_update_rgn( hwnd
, 0 );
7763 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
7764 SetLastError(0xdeadbeef);
7765 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
7766 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
7767 "wrong error code %d\n", GetLastError());
7768 check_update_rgn( hwnd
, 0 );
7770 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7772 trace("testing ValidateRgn(0, NULL)\n");
7773 SetLastError(0xdeadbeef);
7774 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
7775 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
7776 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
7777 "wrong error code %d\n", GetLastError());
7778 check_update_rgn( hwnd
, 0 );
7780 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7782 trace("testing UpdateWindow(NULL)\n");
7783 SetLastError(0xdeadbeef);
7784 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
7785 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
7786 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
7787 "wrong error code %d\n", GetLastError());
7788 check_update_rgn( hwnd
, 0 );
7790 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7792 /* now with frame */
7793 SetRectRgn( hrgn
, -5, -5, 20, 20 );
7795 /* flush pending messages */
7798 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7799 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
7801 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
7802 check_update_rgn( hwnd
, hrgn
);
7805 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
7806 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
7809 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
7810 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
7812 GetClientRect( hwnd
, &rect
);
7813 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
7814 check_update_rgn( hwnd
, hrgn
);
7817 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
7818 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7821 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
7822 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
7823 check_update_rgn( hwnd
, 0 );
7826 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
7827 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
7828 check_update_rgn( hwnd
, 0 );
7831 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7832 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7833 SetRectRgn( hrgn
, 0, 0, 50, 100 );
7834 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
7835 SetRectRgn( hrgn
, 50, 0, 100, 100 );
7836 check_update_rgn( hwnd
, hrgn
);
7837 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
7838 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
7839 check_update_rgn( hwnd
, 0 );
7842 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7843 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
7844 SetRectRgn( hrgn
, 0, 0, 100, 50 );
7845 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
7846 ok_sequence( WmErase
, "Erase", FALSE
);
7847 SetRectRgn( hrgn
, 0, 50, 100, 100 );
7848 check_update_rgn( hwnd
, hrgn
);
7851 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7852 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
7853 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7854 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
7855 ok_sequence( WmPaint
, "Paint", FALSE
);
7858 SetRectRgn( hrgn
, -4, -4, -2, -2 );
7859 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7860 SetRectRgn( hrgn
, -200, -200, -198, -198 );
7861 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
7862 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
7865 SetRectRgn( hrgn
, -4, -4, -2, -2 );
7866 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7867 SetRectRgn( hrgn
, -4, -4, -3, -3 );
7868 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
7869 SetRectRgn( hrgn
, 0, 0, 1, 1 );
7870 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
7871 ok_sequence( WmPaint
, "Paint", FALSE
);
7874 SetRectRgn( hrgn
, -4, -4, -1, -1 );
7875 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7876 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
7877 /* make sure no WM_PAINT was generated */
7879 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
7882 SetRectRgn( hrgn
, -4, -4, -1, -1 );
7883 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7884 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
7886 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
7888 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
7889 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
7890 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
7891 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
7892 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
7893 /* this will send WM_NCPAINT and validate the non client area */
7894 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
7895 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
7897 DispatchMessageA( &msg
);
7899 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
7901 DestroyWindow( hwnd
);
7903 /* now test with a child window */
7905 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
7906 100, 100, 200, 200, 0, 0, 0, NULL
);
7907 ok (hparent
!= 0, "Failed to create parent window\n");
7909 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
7910 10, 10, 100, 100, hparent
, 0, 0, NULL
);
7911 ok (hchild
!= 0, "Failed to create child window\n");
7913 ShowWindow( hparent
, SW_SHOW
);
7914 UpdateWindow( hparent
);
7915 UpdateWindow( hchild
);
7918 log_all_parent_messages
++;
7920 SetRect( &rect
, 0, 0, 50, 50 );
7921 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7922 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
7923 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
7925 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7927 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
7928 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
7929 check_update_rgn( hchild
, hrgn
);
7930 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7931 check_update_rgn( hparent
, hrgn
);
7932 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
7933 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
7934 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
7935 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
7938 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
7940 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
7941 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
7942 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
7943 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
7944 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
7946 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
7947 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
7948 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
7950 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
7952 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
7953 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
7954 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
7956 /* flush all paint messages */
7960 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
7961 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
7962 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7963 check_update_rgn( hparent
, hrgn
);
7964 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
7965 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
7966 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7967 check_update_rgn( hparent
, hrgn
);
7969 /* flush all paint messages */
7971 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
7974 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
7975 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7976 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7977 check_update_rgn( hparent
, hrgn
);
7978 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
7979 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
7980 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
7981 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
7982 check_update_rgn( hparent
, hrgn
);
7983 /* flush all paint messages */
7987 /* same as above but parent gets completely validated */
7988 SetRect( &rect
, 20, 20, 30, 30 );
7989 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7990 SetRectRgn( hrgn
, 20, 20, 30, 30 );
7991 check_update_rgn( hparent
, hrgn
);
7992 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
7993 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
7994 check_update_rgn( hparent
, 0 ); /* no update region */
7996 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
7998 /* make sure RDW_VALIDATE on child doesn't have the same effect */
8000 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8001 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8002 check_update_rgn( hparent
, hrgn
);
8003 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
8004 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8005 check_update_rgn( hparent
, hrgn
);
8007 /* same as above but normal WM_PAINT doesn't validate parent */
8009 SetRect( &rect
, 20, 20, 30, 30 );
8010 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8011 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8012 check_update_rgn( hparent
, hrgn
);
8013 /* no WM_PAINT in child while parent still pending */
8014 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8015 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8016 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8017 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
8020 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8021 /* no WM_PAINT in child while parent still pending */
8022 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8023 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8024 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
8025 /* now that parent is valid child should get WM_PAINT */
8026 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8027 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8028 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8029 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
8031 /* same thing with WS_CLIPCHILDREN in parent */
8033 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8034 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8035 /* changing style invalidates non client area, but we need to invalidate something else to see it */
8036 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
8037 ok_sequence( WmEmptySeq
, "No message", FALSE
);
8038 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
8039 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
8042 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8043 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8044 check_update_rgn( hparent
, hrgn
);
8045 /* no WM_PAINT in child while parent still pending */
8046 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8047 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8048 /* WM_PAINT in parent first */
8049 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8050 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
8052 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
8054 SetRect( &rect
, 0, 0, 30, 30 );
8055 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
8056 SetRectRgn( hrgn
, 0, 0, 30, 30 );
8057 check_update_rgn( hparent
, hrgn
);
8059 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
8061 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8063 SetRect( &rect
, -10, 0, 30, 30 );
8064 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8065 SetRect( &rect
, 0, 0, 20, 20 );
8066 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8067 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8068 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
8070 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8072 SetRect( &rect
, -10, 0, 30, 30 );
8073 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8074 SetRect( &rect
, 0, 0, 100, 100 );
8075 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8076 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8077 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
8078 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8079 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
8081 /* WS_CLIPCHILDREN doesn't exclude children from update region */
8083 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
8084 GetClientRect( hparent
, &rect
);
8085 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8086 check_update_rgn( hparent
, hrgn
);
8089 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8090 GetClientRect( hparent
, &rect
);
8091 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8092 check_update_rgn( hparent
, hrgn
);
8095 /* test RDW_INTERNALPAINT behavior */
8098 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
8100 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8102 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
8104 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8106 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8108 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8110 assert( GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
);
8111 UpdateWindow( hparent
);
8114 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
8115 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8116 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8117 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8119 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
8121 UpdateWindow( hparent
);
8124 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
8125 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8126 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8127 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8129 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8131 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8132 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8133 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8135 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8137 assert( !(GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
) );
8138 UpdateWindow( hparent
);
8141 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
8142 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8143 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8144 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8146 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
8148 UpdateWindow( hparent
);
8151 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
8152 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8153 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8154 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8156 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8158 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
8159 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
8161 UpdateWindow( hparent
);
8164 trace("testing SetWindowPos(-10000, -10000) on child\n");
8165 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
8166 check_update_rgn( hchild
, 0 );
8169 #if 0 /* this one doesn't pass under Wine yet */
8170 UpdateWindow( hparent
);
8173 trace("testing ShowWindow(SW_MINIMIZE) on child\n");
8174 ShowWindow( hchild
, SW_MINIMIZE
);
8175 check_update_rgn( hchild
, 0 );
8179 UpdateWindow( hparent
);
8182 trace("testing SetWindowPos(-10000, -10000) on parent\n");
8183 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
8184 check_update_rgn( hparent
, 0 );
8187 log_all_parent_messages
--;
8188 DestroyWindow( hparent
);
8189 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
8191 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
8193 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
8194 100, 100, 200, 200, 0, 0, 0, NULL
);
8195 ok (hparent
!= 0, "Failed to create parent window\n");
8197 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
8198 10, 10, 100, 100, hparent
, 0, 0, NULL
);
8199 ok (hchild
!= 0, "Failed to create child window\n");
8201 ShowWindow( hparent
, SW_SHOW
);
8202 UpdateWindow( hparent
);
8203 UpdateWindow( hchild
);
8207 /* moving child outside of parent boundaries changes update region */
8208 SetRect( &rect
, 0, 0, 40, 40 );
8209 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8210 SetRectRgn( hrgn
, 0, 0, 40, 40 );
8211 check_update_rgn( hchild
, hrgn
);
8212 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
8213 SetRectRgn( hrgn
, 10, 0, 40, 40 );
8214 check_update_rgn( hchild
, hrgn
);
8215 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
8216 SetRectRgn( hrgn
, 10, 10, 40, 40 );
8217 check_update_rgn( hchild
, hrgn
);
8219 /* moving parent off-screen does too */
8220 SetRect( &rect
, 0, 0, 100, 100 );
8221 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
8222 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8223 check_update_rgn( hparent
, hrgn
);
8224 SetRectRgn( hrgn
, 10, 10, 40, 40 );
8225 check_update_rgn( hchild
, hrgn
);
8226 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
8227 GetUpdateRect( hparent
, &rect2
, FALSE
);
8228 if (!EqualRect( &rect2
, &rect
)) /* Win 8 and later don't crop update to screen */
8233 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8234 check_update_rgn( hparent
, hrgn
);
8235 SetRectRgn( hrgn
, rect
.left
+ 10, rect
.top
+ 10, 40, 40 );
8236 check_update_rgn( hchild
, hrgn
);
8238 /* invalidated region is cropped by the parent rects */
8239 SetRect( &rect
, 0, 0, 50, 50 );
8240 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8241 SetRectRgn( hrgn
, rect2
.left
+ 10, rect2
.top
+ 10, 50, 50 );
8242 check_update_rgn( hchild
, hrgn
);
8244 DestroyWindow( hparent
);
8245 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
8248 DeleteObject( hrgn
);
8249 DeleteObject( hrgn2
);
8260 static DWORD WINAPI
thread_proc(void *param
)
8263 struct wnd_event
*wnd_event
= param
;
8265 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
8266 100, 100, 200, 200, 0, 0, 0, NULL
);
8267 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
8269 SetEvent(wnd_event
->start_event
);
8271 while (GetMessageA(&msg
, 0, 0, 0))
8273 TranslateMessage(&msg
);
8274 DispatchMessageA(&msg
);
8277 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
8282 static DWORD CALLBACK
create_grand_child_thread( void *param
)
8284 struct wnd_event
*wnd_event
= param
;
8288 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
8289 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
8290 ok (hchild
!= 0, "Failed to create child window\n");
8293 SetEvent( wnd_event
->start_event
);
8297 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
8298 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
8299 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8304 static DWORD CALLBACK
create_child_thread( void *param
)
8306 struct wnd_event
*wnd_event
= param
;
8307 struct wnd_event child_event
;
8311 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
8312 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
8313 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
8314 SetFocus( child_event
.hwnd
);
8317 child_event
.start_event
= wnd_event
->start_event
;
8318 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
8321 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
8322 if (ret
!= 1) break;
8323 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8325 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
8326 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
8330 static const char manifest_dep
[] =
8331 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
8332 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
8333 " <file name=\"testdep.dll\" />"
8336 static const char manifest_main
[] =
8337 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
8338 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
8340 " <dependentAssembly>"
8341 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
8342 " </dependentAssembly>"
8346 static void create_manifest_file(const char *filename
, const char *manifest
)
8348 WCHAR path
[MAX_PATH
];
8352 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
8353 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
8354 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
8355 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
8359 static HANDLE
test_create(const char *file
)
8361 WCHAR path
[MAX_PATH
];
8365 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
8366 memset(&actctx
, 0, sizeof(ACTCTXW
));
8367 actctx
.cbSize
= sizeof(ACTCTXW
);
8368 actctx
.lpSource
= path
;
8370 handle
= pCreateActCtxW(&actctx
);
8371 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %u\n", GetLastError());
8373 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%d\n", actctx
.cbSize
);
8374 ok(actctx
.dwFlags
== 0, "dwFlags=%d\n", actctx
.dwFlags
);
8375 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
8376 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
8377 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
8378 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
8379 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
8380 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
8381 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
8386 static void test_interthread_messages(void)
8388 HANDLE hThread
, context
, handle
, event
;
8394 int len
, expected_len
;
8395 struct wnd_event wnd_event
;
8398 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
8399 if (!wnd_event
.start_event
)
8401 win_skip("skipping interthread message test under win9x\n");
8405 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
8406 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8408 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8410 CloseHandle(wnd_event
.start_event
);
8412 SetLastError(0xdeadbeef);
8413 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
8414 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
8415 "wrong error code %d\n", GetLastError());
8417 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
8418 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
8420 expected_len
= lstrlenA("window caption text");
8421 memset(buf
, 0, sizeof(buf
));
8422 SetLastError(0xdeadbeef);
8423 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
8424 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
8425 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
8427 msg
.hwnd
= wnd_event
.hwnd
;
8428 msg
.message
= WM_GETTEXT
;
8429 msg
.wParam
= sizeof(buf
);
8430 msg
.lParam
= (LPARAM
)buf
;
8431 memset(buf
, 0, sizeof(buf
));
8432 SetLastError(0xdeadbeef);
8433 len
= DispatchMessageA(&msg
);
8434 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
8435 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len
, GetLastError());
8437 /* the following test causes an exception in user.exe under win9x */
8438 msg
.hwnd
= wnd_event
.hwnd
;
8439 msg
.message
= WM_TIMER
;
8441 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
8442 SetLastError(0xdeadbeef);
8443 len
= DispatchMessageA(&msg
);
8444 ok(!len
&& GetLastError() == 0xdeadbeef,
8445 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len
, GetLastError());
8447 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
8448 ok( ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
8450 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8451 CloseHandle(hThread
);
8453 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
8455 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8456 100, 100, 200, 200, 0, 0, 0, NULL
);
8457 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
8460 log_all_parent_messages
++;
8461 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
8462 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
8463 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
8466 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
8467 if (ret
!= 1) break;
8468 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8470 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
8471 /* now wait for the thread without processing messages; this shouldn't deadlock */
8472 SetEvent( wnd_event
.stop_event
);
8473 ret
= WaitForSingleObject( hThread
, 5000 );
8474 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
8475 CloseHandle( hThread
);
8477 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
8478 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
8479 CloseHandle( wnd_event
.grand_child
);
8481 CloseHandle( wnd_event
.start_event
);
8482 CloseHandle( wnd_event
.stop_event
);
8484 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
8485 log_all_parent_messages
--;
8486 DestroyWindow( wnd_event
.hwnd
);
8488 /* activation context tests */
8489 if (!pActivateActCtx
)
8491 win_skip("Activation contexts are not supported, skipping\n");
8495 create_manifest_file("testdep1.manifest", manifest_dep
);
8496 create_manifest_file("main.manifest", manifest_main
);
8498 context
= test_create("main.manifest");
8499 DeleteFileA("testdep1.manifest");
8500 DeleteFileA("main.manifest");
8502 handle
= (void*)0xdeadbeef;
8503 ret
= pGetCurrentActCtx(&handle
);
8504 ok(ret
, "GetCurrentActCtx failed: %u\n", GetLastError());
8505 ok(handle
== 0, "active context %p\n", handle
);
8507 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
8508 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
8509 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8510 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8511 CloseHandle(wnd_event
.start_event
);
8513 /* context is activated after thread creation, so it doesn't inherit it by default */
8514 ret
= pActivateActCtx(context
, &cookie
);
8515 ok(ret
, "activation failed: %u\n", GetLastError());
8518 ret
= pGetCurrentActCtx(&handle
);
8519 ok(ret
, "GetCurrentActCtx failed: %u\n", GetLastError());
8520 ok(handle
!= 0, "active context %p\n", handle
);
8521 pReleaseActCtx(handle
);
8523 /* destination window will test for active context */
8524 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
8525 ok(ret
, "thread window returned %d\n", ret
);
8527 event
= CreateEventW(NULL
, 0, 0, NULL
);
8528 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
8529 ok(ret
, "thread window returned %d\n", ret
);
8530 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8533 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
8534 ok(ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
8536 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8537 CloseHandle(hThread
);
8539 ret
= pDeactivateActCtx(0, cookie
);
8540 ok(ret
, "DeactivateActCtx failed: %u\n", GetLastError());
8541 pReleaseActCtx(context
);
8545 static const struct message WmVkN
[] = {
8546 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8547 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8548 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
8549 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
8550 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
8551 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8552 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8553 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8556 static const struct message WmShiftVkN
[] = {
8557 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8558 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8559 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8560 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8561 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8562 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
8563 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
8564 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
8565 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8566 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8567 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8568 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8569 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8570 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8573 static const struct message WmCtrlVkN
[] = {
8574 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8575 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8576 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8577 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8578 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8579 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
8580 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
8581 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
8582 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8583 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8584 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8585 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8586 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8587 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8590 static const struct message WmCtrlVkN_2
[] = {
8591 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8592 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8593 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8594 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8595 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8596 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
8597 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8598 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8599 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8600 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8601 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8602 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8605 static const struct message WmAltVkN
[] = {
8606 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8607 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8608 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8609 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8610 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8611 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
8612 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
8613 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
8614 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
8615 { HCBT_SYSCOMMAND
, hook
},
8616 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8617 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8618 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
8619 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
8620 { WM_INITMENU
, sent
|defwinproc
},
8621 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8622 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
8623 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
8624 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8625 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
8626 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8627 { WM_EXITMENULOOP
, sent
|defwinproc
},
8628 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
8629 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
8630 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8631 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8632 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8633 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8634 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8635 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8638 static const struct message WmAltVkN_2
[] = {
8639 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8640 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8641 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8642 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8643 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8644 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
8645 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8646 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8647 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8648 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8649 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8650 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8653 static const struct message WmCtrlAltVkN
[] = {
8654 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8655 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8656 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8657 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8658 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8659 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8660 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8661 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8662 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
8663 { WM_CHAR
, optional
},
8664 { WM_CHAR
, sent
|optional
},
8665 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8666 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8667 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8668 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8669 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8670 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8671 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8672 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8673 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8676 static const struct message WmCtrlShiftVkN
[] = {
8677 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8678 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8679 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8680 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8681 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8682 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8683 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8684 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8685 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
8686 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8687 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8688 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8689 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8690 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8691 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8692 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8693 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8694 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8697 static const struct message WmCtrlAltShiftVkN
[] = {
8698 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8699 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8700 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8701 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8702 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8703 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8704 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
8705 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
8706 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
8707 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8708 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8709 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
8710 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8711 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8712 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8713 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
8714 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
8715 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
8716 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8717 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8718 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8719 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8720 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8721 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8724 static const struct message WmAltPressRelease
[] = {
8725 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8726 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8727 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8728 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8729 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8730 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8731 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
8732 { HCBT_SYSCOMMAND
, hook
},
8733 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8734 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8735 { WM_INITMENU
, sent
|defwinproc
},
8736 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8737 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8738 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8740 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
8742 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8743 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
8744 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8745 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
8746 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8747 { WM_EXITMENULOOP
, sent
|defwinproc
},
8748 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8749 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8750 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8753 static const struct message WmShiftMouseButton
[] = {
8754 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8755 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8756 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8757 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
8758 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
8759 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
8760 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
8761 { WM_LBUTTONUP
, wparam
, MK_SHIFT
, 0 },
8762 { WM_LBUTTONUP
, sent
|wparam
, MK_SHIFT
, 0 },
8763 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8764 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8765 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8768 static const struct message WmF1Seq
[] = {
8769 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
8770 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
8771 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
8772 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
8773 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
8774 { WM_HELP
, sent
|defwinproc
},
8775 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
8776 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
8777 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
8780 static const struct message WmVkAppsSeq
[] = {
8781 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
8782 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
8783 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
8784 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
8785 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
8786 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
8787 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
8788 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
8791 static const struct message WmVkF10Seq
[] = {
8792 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8793 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
8794 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
8795 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8796 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8797 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8798 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
8799 { HCBT_SYSCOMMAND
, hook
},
8800 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8801 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8802 { WM_INITMENU
, sent
|defwinproc
},
8803 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8804 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8805 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8807 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
8809 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8810 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8811 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
8812 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8813 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
8814 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8815 { WM_EXITMENULOOP
, sent
|defwinproc
},
8816 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8817 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8818 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8821 static const struct message WmShiftF10Seq
[] = {
8822 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8823 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8824 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
8825 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8826 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
8827 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
8828 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
8829 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8830 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8831 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8832 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
8833 { HCBT_SYSCOMMAND
, hook
},
8834 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8835 { WM_INITMENU
, sent
|defwinproc
},
8836 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8837 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
8838 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
8839 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8840 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
8841 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8842 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
8843 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
8844 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
8848 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
8852 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
8854 struct recvd_message log_msg
;
8856 /* ignore some unwanted messages */
8857 if (msg
.message
== WM_MOUSEMOVE
||
8858 msg
.message
== WM_TIMER
||
8859 ignore_message( msg
.message
))
8862 log_msg
.hwnd
= msg
.hwnd
;
8863 log_msg
.message
= msg
.message
;
8864 log_msg
.flags
= wparam
|lparam
;
8865 log_msg
.wParam
= msg
.wParam
;
8866 log_msg
.lParam
= msg
.lParam
;
8867 log_msg
.descr
= "accel";
8868 add_message(&log_msg
);
8870 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
8872 TranslateMessage(&msg
);
8873 DispatchMessageA(&msg
);
8878 static void test_accelerators(void)
8884 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8885 100, 100, 200, 200, 0, 0, 0, NULL
);
8894 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
8896 state
= GetKeyState(VK_SHIFT
);
8897 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
8898 state
= GetKeyState(VK_CAPITAL
);
8899 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
8901 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
8902 assert(hAccel
!= 0);
8905 pump_msg_loop(hwnd
, 0);
8908 trace("testing VK_N press/release\n");
8910 keybd_event('N', 0, 0, 0);
8911 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8912 pump_msg_loop(hwnd
, hAccel
);
8913 if (!sequence_cnt
) /* we didn't get any message */
8915 skip( "queuing key events not supported\n" );
8918 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
8920 trace("testing Shift+VK_N press/release\n");
8922 keybd_event(VK_SHIFT
, 0, 0, 0);
8923 keybd_event('N', 0, 0, 0);
8924 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8925 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8926 pump_msg_loop(hwnd
, hAccel
);
8927 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
8929 trace("testing Ctrl+VK_N press/release\n");
8931 keybd_event(VK_CONTROL
, 0, 0, 0);
8932 keybd_event('N', 0, 0, 0);
8933 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8934 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8935 pump_msg_loop(hwnd
, hAccel
);
8936 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
8938 trace("testing Alt+VK_N press/release\n");
8940 keybd_event(VK_MENU
, 0, 0, 0);
8941 keybd_event('N', 0, 0, 0);
8942 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8943 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8944 pump_msg_loop(hwnd
, hAccel
);
8945 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
8947 trace("testing Ctrl+Alt+VK_N press/release 1\n");
8949 keybd_event(VK_CONTROL
, 0, 0, 0);
8950 keybd_event(VK_MENU
, 0, 0, 0);
8951 keybd_event('N', 0, 0, 0);
8952 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8953 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8954 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8955 pump_msg_loop(hwnd
, hAccel
);
8956 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
8958 ret
= DestroyAcceleratorTable(hAccel
);
8959 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
8961 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
8962 assert(hAccel
!= 0);
8964 trace("testing VK_N press/release\n");
8966 keybd_event('N', 0, 0, 0);
8967 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8968 pump_msg_loop(hwnd
, hAccel
);
8969 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
8971 trace("testing Shift+VK_N press/release\n");
8973 keybd_event(VK_SHIFT
, 0, 0, 0);
8974 keybd_event('N', 0, 0, 0);
8975 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8976 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8977 pump_msg_loop(hwnd
, hAccel
);
8978 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
8980 trace("testing Ctrl+VK_N press/release 2\n");
8982 keybd_event(VK_CONTROL
, 0, 0, 0);
8983 keybd_event('N', 0, 0, 0);
8984 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8985 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8986 pump_msg_loop(hwnd
, hAccel
);
8987 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
8989 trace("testing Alt+VK_N press/release 2\n");
8991 keybd_event(VK_MENU
, 0, 0, 0);
8992 keybd_event('N', 0, 0, 0);
8993 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8994 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8995 pump_msg_loop(hwnd
, hAccel
);
8996 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
8998 trace("testing Ctrl+Alt+VK_N press/release 2\n");
9000 keybd_event(VK_CONTROL
, 0, 0, 0);
9001 keybd_event(VK_MENU
, 0, 0, 0);
9002 keybd_event('N', 0, 0, 0);
9003 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9004 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9005 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9006 pump_msg_loop(hwnd
, hAccel
);
9007 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
9009 trace("testing Ctrl+Shift+VK_N press/release\n");
9011 keybd_event(VK_CONTROL
, 0, 0, 0);
9012 keybd_event(VK_SHIFT
, 0, 0, 0);
9013 keybd_event('N', 0, 0, 0);
9014 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9015 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9016 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9017 pump_msg_loop(hwnd
, hAccel
);
9018 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
9020 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
9022 keybd_event(VK_CONTROL
, 0, 0, 0);
9023 keybd_event(VK_MENU
, 0, 0, 0);
9024 keybd_event(VK_SHIFT
, 0, 0, 0);
9025 keybd_event('N', 0, 0, 0);
9026 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9027 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9028 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9029 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
9030 pump_msg_loop(hwnd
, hAccel
);
9031 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
9033 ret
= DestroyAcceleratorTable(hAccel
);
9034 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
9037 trace("testing Alt press/release\n");
9039 keybd_event(VK_MENU
, 0, 0, 0);
9040 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9041 keybd_event(VK_MENU
, 0, 0, 0);
9042 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
9043 pump_msg_loop(hwnd
, 0);
9044 ok_sequence(WmAltPressRelease
, "Alt press/release", FALSE
);
9046 trace("testing VK_F1 press/release\n");
9047 keybd_event(VK_F1
, 0, 0, 0);
9048 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
9049 pump_msg_loop(hwnd
, 0);
9050 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
9052 trace("testing VK_APPS press/release\n");
9053 keybd_event(VK_APPS
, 0, 0, 0);
9054 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
9055 pump_msg_loop(hwnd
, 0);
9056 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
9058 trace("testing VK_F10 press/release\n");
9059 keybd_event(VK_F10
, 0, 0, 0);
9060 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9061 keybd_event(VK_F10
, 0, 0, 0);
9062 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9063 pump_msg_loop(hwnd
, 0);
9064 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", FALSE
);
9066 trace("testing SHIFT+F10 press/release\n");
9067 keybd_event(VK_SHIFT
, 0, 0, 0);
9068 keybd_event(VK_F10
, 0, 0, 0);
9069 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
9070 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9071 keybd_event(VK_ESCAPE
, 0, 0, 0);
9072 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
9073 pump_msg_loop(hwnd
, 0);
9074 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
9076 trace("testing Shift+MouseButton press/release\n");
9077 /* first, move mouse pointer inside of the window client area */
9078 GetClientRect(hwnd
, &rc
);
9079 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
9080 rc
.left
+= (rc
.right
- rc
.left
)/2;
9081 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
9082 SetCursorPos(rc
.left
, rc
.top
);
9083 SetActiveWindow(hwnd
);
9088 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
9091 keybd_event(VK_SHIFT
, 0, 0, 0);
9092 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
9093 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
9094 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
9095 pump_msg_loop(hwnd
, 0);
9096 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
9097 if (i
< sequence_cnt
)
9098 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
9100 skip( "Shift+MouseButton event didn't get to the window\n" );
9104 if (hAccel
) DestroyAcceleratorTable(hAccel
);
9105 DestroyWindow(hwnd
);
9108 /************* window procedures ********************/
9110 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
9111 WPARAM wParam
, LPARAM lParam
)
9113 static LONG defwndproc_counter
= 0;
9114 static LONG beginpaint_counter
= 0;
9116 struct recvd_message msg
;
9118 if (ignore_message( message
)) return 0;
9124 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9125 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
9126 "wrong WS_DISABLED state: %ld != %d\n", wParam
, !(style
& WS_DISABLED
));
9130 case WM_CAPTURECHANGED
:
9131 if (test_DestroyWindow_flag
)
9133 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9134 if (style
& WS_CHILD
)
9135 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
9136 else if (style
& WS_POPUP
)
9137 lParam
= WND_POPUP_ID
;
9139 lParam
= WND_PARENT_ID
;
9147 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
9148 capture
= GetCapture();
9151 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
9152 trace("current capture %p, releasing...\n", capture
);
9159 ok(pGetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
9160 if (test_DestroyWindow_flag
)
9162 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
9163 if (style
& WS_CHILD
)
9164 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
9165 else if (style
& WS_POPUP
)
9166 lParam
= WND_POPUP_ID
;
9168 lParam
= WND_PARENT_ID
;
9172 /* test_accelerators() depends on this */
9178 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo
;
9179 HANDLE handle
, event
= (HANDLE
)lParam
;
9182 handle
= (void*)0xdeadbeef;
9183 ret
= pGetCurrentActCtx(&handle
);
9184 ok(ret
, "failed to get current context, %u\n", GetLastError());
9185 ok(handle
== 0, "got active context %p\n", handle
);
9187 memset(&basicinfo
, 0xff, sizeof(basicinfo
));
9188 ret
= pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
, handle
, 0, ActivationContextBasicInformation
,
9189 &basicinfo
, sizeof(basicinfo
), NULL
);
9190 ok(ret
, "got %d, error %d\n", ret
, GetLastError());
9191 ok(basicinfo
.hActCtx
== NULL
, "got %p\n", basicinfo
.hActCtx
);
9192 ok(basicinfo
.dwFlags
== 0, "got %x\n", basicinfo
.dwFlags
);
9194 if (event
) SetEvent(event
);
9200 case WM_MOUSEACTIVATE
:
9201 case WM_NCMOUSEMOVE
:
9208 msg
.message
= message
;
9209 msg
.flags
= sent
|wparam
|lparam
;
9210 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9211 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
9212 msg
.wParam
= wParam
;
9213 msg
.lParam
= lParam
;
9214 msg
.descr
= "MsgCheckProc";
9217 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
9219 HWND parent
= GetParent(hwnd
);
9221 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
9223 GetClientRect(parent
, &rc
);
9224 trace("parent %p client size = (%d x %d)\n", parent
, rc
.right
, rc
.bottom
);
9225 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
9226 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
9227 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
9228 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
9229 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
9230 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
9232 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %d != %d\n",
9233 minmax
->ptMaxSize
.x
, rc
.right
);
9234 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %d != %d\n",
9235 minmax
->ptMaxSize
.y
, rc
.bottom
);
9238 if (message
== WM_PAINT
)
9241 beginpaint_counter
++;
9242 BeginPaint( hwnd
, &ps
);
9243 beginpaint_counter
--;
9244 EndPaint( hwnd
, &ps
);
9248 if (message
== WM_CONTEXTMENU
)
9250 /* don't create context menu */
9254 defwndproc_counter
++;
9255 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
9256 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9257 defwndproc_counter
--;
9262 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9264 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
9267 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9269 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
9272 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9274 static LONG defwndproc_counter
= 0;
9276 struct recvd_message msg
;
9278 if (ignore_message( message
)) return 0;
9282 case WM_QUERYENDSESSION
:
9284 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
9289 msg
.message
= message
;
9290 msg
.flags
= sent
|wparam
|lparam
;
9291 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9292 msg
.wParam
= wParam
;
9293 msg
.lParam
= lParam
;
9294 msg
.descr
= "popup";
9297 if (message
== WM_CREATE
)
9299 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
9300 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
9303 defwndproc_counter
++;
9304 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9305 defwndproc_counter
--;
9310 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9312 static LONG defwndproc_counter
= 0;
9313 static LONG beginpaint_counter
= 0;
9315 struct recvd_message msg
;
9317 if (ignore_message( message
)) return 0;
9319 if (log_all_parent_messages
||
9320 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
9321 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
9322 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
9323 message
== WM_DRAWITEM
|| message
== WM_MEASUREITEM
|| message
== WM_COMPAREITEM
||
9324 message
== WM_COMMAND
|| message
== WM_IME_SETCONTEXT
)
9333 case WM_NCMOUSEMOVE
:
9339 INT ret
= GetClipBox((HDC
)wParam
, &rc
);
9341 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret
, wine_dbgstr_rect(&rc
));
9347 msg
.message
= message
;
9348 msg
.flags
= sent
|parent
|wparam
|lparam
;
9349 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9350 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
9351 msg
.wParam
= wParam
;
9352 msg
.lParam
= lParam
;
9353 msg
.descr
= "parent";
9357 if (message
== WM_PAINT
)
9360 beginpaint_counter
++;
9361 BeginPaint( hwnd
, &ps
);
9362 beginpaint_counter
--;
9363 EndPaint( hwnd
, &ps
);
9367 defwndproc_counter
++;
9368 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9369 defwndproc_counter
--;
9371 return message
== WM_COMPAREITEM
? -1 : ret
;
9374 static INT_PTR CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
9376 if (message
== WM_CREATE
)
9377 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
9378 else if (message
== WM_CLOSE
)
9380 /* Only the first WM_QUIT will survive the window destruction */
9381 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
9382 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
9383 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
9386 return DefWindowProcA(hwnd
, message
, wp
, lp
);
9389 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9391 static LONG defwndproc_counter
= 0;
9393 struct recvd_message msg
;
9395 if (ignore_message( message
)) return 0;
9399 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
9400 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
9401 if (after_end_dialog
)
9402 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
9404 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
9408 msg
.message
= message
;
9409 msg
.flags
= sent
|wparam
|lparam
;
9410 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9411 msg
.wParam
= wParam
;
9412 msg
.lParam
= lParam
;
9413 msg
.descr
= "dialog";
9416 defwndproc_counter
++;
9417 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
9418 defwndproc_counter
--;
9423 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9425 static LONG defwndproc_counter
= 0;
9427 struct recvd_message msg
;
9429 /* log only specific messages we are interested in */
9432 #if 0 /* probably log these as well */
9440 case WM_GETMINMAXINFO
:
9441 case WM_WINDOWPOSCHANGING
:
9442 case WM_WINDOWPOSCHANGED
:
9445 default: /* ignore */
9446 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
9447 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9451 msg
.message
= message
;
9452 msg
.flags
= sent
|wparam
|lparam
;
9453 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9454 msg
.wParam
= wParam
;
9455 msg
.lParam
= lParam
;
9459 defwndproc_counter
++;
9460 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9461 defwndproc_counter
--;
9466 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
9470 case WM_CREATE
: return 0;
9479 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
9481 TranslateMessage(&msg2
);
9482 DispatchMessageA(&msg2
);
9486 else ok(broken(1), "infinite loop\n");
9488 paint_loop_done
= TRUE
;
9489 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
9492 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
9495 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9497 static LONG defwndproc_counter
= 0;
9499 struct recvd_message msg
;
9502 if (ignore_message( message
)) return 0;
9504 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
9505 message
== WM_HOTKEY
|| message
>= WM_APP
)
9508 msg
.message
= message
;
9509 msg
.flags
= sent
|wparam
|lparam
;
9510 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9511 msg
.wParam
= wParam
;
9512 msg
.lParam
= lParam
;
9513 msg
.descr
= "HotkeyMsgCheckProcA";
9517 defwndproc_counter
++;
9518 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
9519 defwndproc_counter
--;
9521 if (message
== WM_APP
)
9523 queue_status
= GetQueueStatus(QS_HOTKEY
);
9524 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
9525 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
9526 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
9527 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
9529 else if (message
== WM_APP
+1)
9531 queue_status
= GetQueueStatus(QS_HOTKEY
);
9532 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
9538 static BOOL
RegisterWindowClasses(void)
9544 cls
.lpfnWndProc
= MsgCheckProcA
;
9547 cls
.hInstance
= GetModuleHandleA(0);
9549 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
9550 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
9551 cls
.lpszMenuName
= NULL
;
9552 cls
.lpszClassName
= "TestWindowClass";
9553 if(!RegisterClassA(&cls
)) return FALSE
;
9555 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
9556 cls
.lpszClassName
= "HotkeyWindowClass";
9557 if(!RegisterClassA(&cls
)) return FALSE
;
9559 cls
.lpfnWndProc
= ShowWindowProcA
;
9560 cls
.lpszClassName
= "ShowWindowClass";
9561 if(!RegisterClassA(&cls
)) return FALSE
;
9563 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
9564 cls
.lpszClassName
= "TestPopupClass";
9565 if(!RegisterClassA(&cls
)) return FALSE
;
9567 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
9568 cls
.lpszClassName
= "TestParentClass";
9569 if(!RegisterClassA(&cls
)) return FALSE
;
9571 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
9572 cls
.lpszClassName
= "StopQuitClass";
9573 if(!RegisterClassA(&cls
)) return FALSE
;
9575 cls
.lpfnWndProc
= DefWindowProcA
;
9576 cls
.lpszClassName
= "SimpleWindowClass";
9577 if(!RegisterClassA(&cls
)) return FALSE
;
9579 cls
.lpfnWndProc
= PaintLoopProcA
;
9580 cls
.lpszClassName
= "PaintLoopWindowClass";
9581 if(!RegisterClassA(&cls
)) return FALSE
;
9583 cls
.style
= CS_NOCLOSE
;
9584 cls
.lpszClassName
= "NoCloseWindowClass";
9585 if(!RegisterClassA(&cls
)) return FALSE
;
9587 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
9589 cls
.hInstance
= GetModuleHandleA(0);
9590 cls
.hbrBackground
= 0;
9591 cls
.lpfnWndProc
= TestDlgProcA
;
9592 cls
.lpszClassName
= "TestDialogClass";
9593 if(!RegisterClassA(&cls
)) return FALSE
;
9596 clsW
.lpfnWndProc
= MsgCheckProcW
;
9597 clsW
.cbClsExtra
= 0;
9598 clsW
.cbWndExtra
= 0;
9599 clsW
.hInstance
= GetModuleHandleW(0);
9601 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
9602 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
9603 clsW
.lpszMenuName
= NULL
;
9604 clsW
.lpszClassName
= testWindowClassW
;
9605 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
9610 static BOOL
is_our_logged_class(HWND hwnd
)
9614 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
9616 if (!lstrcmpiA(buf
, "TestWindowClass") ||
9617 !lstrcmpiA(buf
, "ShowWindowClass") ||
9618 !lstrcmpiA(buf
, "TestParentClass") ||
9619 !lstrcmpiA(buf
, "TestPopupClass") ||
9620 !lstrcmpiA(buf
, "SimpleWindowClass") ||
9621 !lstrcmpiA(buf
, "TestDialogClass") ||
9622 !lstrcmpiA(buf
, "MDI_frame_class") ||
9623 !lstrcmpiA(buf
, "MDI_client_class") ||
9624 !lstrcmpiA(buf
, "MDI_child_class") ||
9625 !lstrcmpiA(buf
, "my_button_class") ||
9626 !lstrcmpiA(buf
, "my_edit_class") ||
9627 !lstrcmpiA(buf
, "static") ||
9628 !lstrcmpiA(buf
, "ListBox") ||
9629 !lstrcmpiA(buf
, "ComboBox") ||
9630 !lstrcmpiA(buf
, "MyDialogClass") ||
9631 !lstrcmpiA(buf
, "#32770") ||
9632 !lstrcmpiA(buf
, "#32768"))
9638 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
9642 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
9644 if (nCode
== HCBT_CLICKSKIPPED
)
9646 /* ignore this event, XP sends it a lot when switching focus between windows */
9647 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9650 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
9652 struct recvd_message msg
;
9655 msg
.message
= nCode
;
9656 msg
.flags
= hook
|wparam
|lparam
;
9657 msg
.wParam
= wParam
;
9658 msg
.lParam
= lParam
;
9662 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9665 if (nCode
== HCBT_DESTROYWND
)
9667 if (test_DestroyWindow_flag
)
9669 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
9670 if (style
& WS_CHILD
)
9671 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
9672 else if (style
& WS_POPUP
)
9673 lParam
= WND_POPUP_ID
;
9675 lParam
= WND_PARENT_ID
;
9679 /* Log also SetFocus(0) calls */
9680 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
9682 if (is_our_logged_class(hwnd
))
9684 struct recvd_message msg
;
9687 msg
.message
= nCode
;
9688 msg
.flags
= hook
|wparam
|lparam
;
9689 msg
.wParam
= wParam
;
9690 msg
.lParam
= lParam
;
9694 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9697 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
9705 ok(thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
9707 /* ignore mouse cursor events */
9708 if (object_id
== OBJID_CURSOR
) return;
9710 if (!hwnd
|| is_our_logged_class(hwnd
))
9712 struct recvd_message msg
;
9715 msg
.message
= event
;
9716 msg
.flags
= winevent_hook
|wparam
|lparam
;
9717 msg
.wParam
= object_id
;
9718 msg
.lParam
= child_id
;
9724 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
9725 static const WCHAR wszAnsi
[] = {'U',0};
9727 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
9731 case CB_FINDSTRINGEXACT
:
9732 trace("String: %p\n", (LPCWSTR
)lParam
);
9733 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
9735 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
9739 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
9742 static const struct message WmGetTextLengthAfromW
[] = {
9743 { WM_GETTEXTLENGTH
, sent
},
9744 { WM_GETTEXT
, sent
|optional
},
9748 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
9750 /* dummy window proc for WM_GETTEXTLENGTH test */
9751 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
9755 case WM_GETTEXTLENGTH
:
9756 return lstrlenW(dummy_window_text
) + 37; /* some random length */
9758 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
9759 return lstrlenW( (LPWSTR
)lp
);
9761 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
9765 static void test_message_conversion(void)
9767 static const WCHAR wszMsgConversionClass
[] =
9768 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
9772 WNDPROC wndproc
, newproc
;
9776 cls
.lpfnWndProc
= MsgConversionProcW
;
9779 cls
.hInstance
= GetModuleHandleW(NULL
);
9781 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
9782 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
9783 cls
.lpszMenuName
= NULL
;
9784 cls
.lpszClassName
= wszMsgConversionClass
;
9785 /* this call will fail on Win9x, but that doesn't matter as this test is
9786 * meaningless on those platforms */
9787 if(!RegisterClassW(&cls
)) return;
9789 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
9790 100, 100, 200, 200, 0, 0, 0, NULL
);
9791 ok(hwnd
!= NULL
, "Window creation failed\n");
9795 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
9796 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9797 ok(lRes
== 0, "String should have been converted\n");
9798 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9799 ok(lRes
== 1, "String shouldn't have been converted\n");
9803 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
9804 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9805 ok(lRes
== 1, "String shouldn't have been converted\n");
9806 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9807 ok(lRes
== 1, "String shouldn't have been converted\n");
9809 /* Synchronous messages */
9811 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9812 ok(lRes
== 0, "String should have been converted\n");
9813 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9814 ok(lRes
== 1, "String shouldn't have been converted\n");
9816 /* Asynchronous messages */
9819 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9820 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9821 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9823 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9824 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9825 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9827 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9828 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9829 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9831 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9832 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9833 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9835 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9836 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9837 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9839 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9840 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9841 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9843 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
9844 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9845 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9847 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
9848 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9849 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9851 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
9853 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
9854 WS_OVERLAPPEDWINDOW
,
9855 100, 100, 200, 200, 0, 0, 0, NULL
);
9858 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
9859 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
9860 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
9861 "got bad length %ld\n", lRes
);
9864 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
9865 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
9866 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
9867 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
9868 "got bad length %ld\n", lRes
);
9870 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
9871 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
9872 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
9873 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
9874 NULL
, 0, NULL
, NULL
) ||
9875 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
9876 "got bad length %ld\n", lRes
);
9878 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
9879 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
9880 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
9881 NULL
, 0, NULL
, NULL
) ||
9882 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
9883 "got bad length %ld\n", lRes
);
9885 ret
= DestroyWindow(hwnd
);
9886 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
9896 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
9900 #define TIMER_ID 0x19
9901 #define TIMER_COUNT_EXPECTED 100
9902 #define TIMER_COUNT_TOLERANCE 10
9904 static int count
= 0;
9905 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
9910 static DWORD exception
;
9911 static void CALLBACK
callback_exception(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
9914 RaiseException(exception
, 0, 0, NULL
);
9917 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
9919 struct timer_info
*info
= x
;
9922 r
= KillTimer(info
->hWnd
, 0x19);
9923 ok(r
,"KillTimer failed in thread\n");
9924 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
9925 ok(r
,"SetTimer failed in thread\n");
9926 ok(r
==TIMER_ID
,"SetTimer id different\n");
9927 r
= SetEvent(info
->handles
[0]);
9928 ok(r
,"SetEvent failed in thread\n");
9932 static void test_timers(void)
9934 struct timer_info info
;
9939 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
9940 WS_OVERLAPPEDWINDOW
,
9941 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
9944 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
9945 ok(info
.id
, "SetTimer failed\n");
9946 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
9947 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
9948 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
9950 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
9952 WaitForSingleObject(info
.handles
[1], INFINITE
);
9954 CloseHandle(info
.handles
[0]);
9955 CloseHandle(info
.handles
[1]);
9957 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
9959 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
9960 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
9961 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
9962 * ±9 counts (~4 ms) around the expected value.
9965 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
9966 ok(id
!= 0, "did not get id from SetTimer.\n");
9967 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
9968 start
= GetTickCount();
9969 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
9970 DispatchMessageA(&msg
);
9972 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
9973 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
9974 || broken(abs(count
-43) < TIMER_COUNT_TOLERANCE
) /* w2k3, win8 */,
9975 "did not get expected count for minimum timeout (%d != ~%d).\n",
9976 count
, TIMER_COUNT_EXPECTED
);
9977 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
9978 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
9979 if (pSetSystemTimer
)
9984 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
9985 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
9986 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
9987 start
= GetTickCount();
9988 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
9990 if (msg
.message
== WM_SYSTIMER
)
9992 DispatchMessageA(&msg
);
9994 ok(abs(syscount
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
9995 || broken(abs(syscount
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
9996 || broken(syscount
> 4000 && syscount
< 12000) /* win2k3sp0 */,
9997 "did not get expected count for minimum timeout (%d != ~%d).\n",
9998 syscount
, TIMER_COUNT_EXPECTED
);
9999 todo_wine
ok(count
== 0, "did not get expected count for callback timeout (%d != 0).\n",
10001 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
10004 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
10007 static void test_timers_no_wnd(void)
10009 static UINT_PTR ids
[0xffff];
10016 id
= SetTimer(NULL
, 0, 100, callback_count
);
10017 ok(id
!= 0, "did not get id from SetTimer.\n");
10018 id2
= SetTimer(NULL
, id
, 200, callback_count
);
10019 ok(id2
== id
, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2
, id
);
10021 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10022 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
10024 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10025 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
10026 KillTimer(NULL
, id
);
10028 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10029 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
10031 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
10032 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
10033 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
10034 * ±9 counts (~4 ms) around the expected value.
10037 id
= SetTimer(NULL
, 0, 0, callback_count
);
10038 ok(id
!= 0, "did not get id from SetTimer.\n");
10039 start
= GetTickCount();
10040 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, NULL
, 0, 0))
10041 DispatchMessageA(&msg
);
10043 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
10044 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */,
10045 "did not get expected count for minimum timeout (%d != ~%d).\n",
10046 count
, TIMER_COUNT_EXPECTED
);
10047 KillTimer(NULL
, id
);
10048 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
10050 if (pSetCoalescableTimer
)
10053 id
= pSetCoalescableTimer(NULL
, 0, 0, callback_count
, 0);
10054 ok(id
!= 0, "SetCoalescableTimer failed with %u.\n", GetLastError());
10055 start
= GetTickCount();
10056 while (GetTickCount()-start
< 100 && GetMessageA(&msg
, NULL
, 0, 0))
10057 DispatchMessageA(&msg
);
10058 ok(count
> 1, "expected count > 1, got %d.\n", count
);
10059 KillTimer(NULL
, id
);
10062 win_skip("SetCoalescableTimer not available.\n");
10064 /* Check what happens when we're running out of timers */
10065 for (i
=0; i
<sizeof(ids
)/sizeof(ids
[0]); i
++)
10067 SetLastError(0xdeadbeef);
10068 ids
[i
] = SetTimer(NULL
, 0, USER_TIMER_MAXIMUM
, tfunc
);
10069 if (!ids
[i
]) break;
10071 ok(i
!= sizeof(ids
)/sizeof(ids
[0]), "all timers were created successfully\n");
10072 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES
|| broken(GetLastError()==0xdeadbeef),
10073 "GetLastError() = %d\n", GetLastError());
10074 while (i
> 0) KillTimer(NULL
, ids
[--i
]);
10077 static void test_timers_exception(DWORD code
)
10083 id
= SetTimer(NULL
, 0, 1000, callback_exception
);
10084 ok(id
!= 0, "did not get id from SetTimer.\n");
10086 memset(&msg
, 0, sizeof(msg
));
10087 msg
.message
= WM_TIMER
;
10089 msg
.lParam
= (LPARAM
)callback_exception
;
10092 DispatchMessageA(&msg
);
10093 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
10095 KillTimer(NULL
, id
);
10098 static void test_timers_exceptions(void)
10100 test_timers_exception(EXCEPTION_ACCESS_VIOLATION
);
10101 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT
);
10102 test_timers_exception(EXCEPTION_BREAKPOINT
);
10103 test_timers_exception(EXCEPTION_SINGLE_STEP
);
10104 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED
);
10105 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND
);
10106 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO
);
10107 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT
);
10108 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION
);
10109 test_timers_exception(0xE000BEEF); /* customer exception */
10112 /* Various win events with arbitrary parameters */
10113 static const struct message WmWinEventsSeq
[] = {
10114 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
10115 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
10116 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
10117 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
10118 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
10119 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
10120 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
10121 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
10122 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
10123 /* our win event hook ignores OBJID_CURSOR events */
10124 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
10125 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
10126 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
10127 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
10128 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
10129 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
10130 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
10131 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
10132 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
10133 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
10134 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
10135 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
10136 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
10137 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
10140 static const struct message WmWinEventCaretSeq
[] = {
10141 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10142 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10143 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
10144 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
10147 static const struct message WmWinEventCaretSeq_2
[] = {
10148 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10149 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10150 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
10153 static const struct message WmWinEventAlertSeq
[] = {
10154 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
10157 static const struct message WmWinEventAlertSeq_2
[] = {
10158 /* create window in the thread proc */
10159 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
10160 /* our test event */
10161 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
10164 static const struct message WmGlobalHookSeq_1
[] = {
10165 /* create window in the thread proc */
10166 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
10167 /* our test events */
10168 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
10169 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
10172 static const struct message WmGlobalHookSeq_2
[] = {
10173 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
10174 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
10175 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
10176 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
10180 static const struct message WmMouseLLHookSeq
[] = {
10181 { WM_MOUSEMOVE
, hook
},
10182 { WM_LBUTTONUP
, hook
},
10183 { WM_MOUSEMOVE
, hook
},
10187 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
10197 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
10199 if (!lstrcmpiA(buf
, "TestWindowClass") ||
10200 !lstrcmpiA(buf
, "static"))
10202 struct recvd_message msg
;
10205 msg
.message
= event
;
10206 msg
.flags
= winevent_hook
|wparam
|lparam
;
10207 msg
.wParam
= object_id
;
10208 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
10209 msg
.descr
= "WEH_2";
10215 static HHOOK hCBT_global_hook
;
10216 static DWORD cbt_global_hook_thread_id
;
10218 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
10223 if (nCode
== HCBT_SYSCOMMAND
)
10225 struct recvd_message msg
;
10228 msg
.message
= nCode
;
10229 msg
.flags
= hook
|wparam
|lparam
;
10230 msg
.wParam
= wParam
;
10231 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
10232 msg
.descr
= "CBT_2";
10235 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
10237 /* WH_MOUSE_LL hook */
10238 if (nCode
== HC_ACTION
)
10240 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
10242 /* we can't test for real mouse events */
10243 if (mhll
->flags
& LLMHF_INJECTED
)
10245 struct recvd_message msg
;
10247 memset (&msg
, 0, sizeof (msg
));
10248 msg
.message
= wParam
;
10250 msg
.descr
= "CBT_2";
10253 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
10256 /* Log also SetFocus(0) calls */
10257 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
10259 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
10261 if (!lstrcmpiA(buf
, "TestWindowClass") ||
10262 !lstrcmpiA(buf
, "static"))
10264 struct recvd_message msg
;
10267 msg
.message
= nCode
;
10268 msg
.flags
= hook
|wparam
|lparam
;
10269 msg
.wParam
= wParam
;
10270 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
10271 msg
.descr
= "CBT_2";
10275 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
10278 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
10282 HANDLE hevent
= *(HANDLE
*)param
;
10284 assert(pNotifyWinEvent
);
10286 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
10288 trace("created thread window %p\n", hwnd
);
10290 *(HWND
*)param
= hwnd
;
10293 /* this event should be received only by our new hook proc,
10294 * an old one does not expect an event from another thread.
10296 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
10299 while (GetMessageA(&msg
, 0, 0, 0))
10301 TranslateMessage(&msg
);
10302 DispatchMessageA(&msg
);
10307 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
10311 HANDLE hevent
= *(HANDLE
*)param
;
10314 /* these events should be received only by our new hook proc,
10315 * an old one does not expect an event from another thread.
10318 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
10320 trace("created thread window %p\n", hwnd
);
10322 *(HWND
*)param
= hwnd
;
10324 /* Windows doesn't like when a thread plays games with the focus,
10325 that leads to all kinds of misbehaviours and failures to activate
10326 a window. So, better keep next lines commented out.
10330 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
10331 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
10335 while (GetMessageA(&msg
, 0, 0, 0))
10337 TranslateMessage(&msg
);
10338 DispatchMessageA(&msg
);
10343 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
10347 HANDLE hevent
= *(HANDLE
*)param
;
10349 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
10351 trace("created thread window %p\n", hwnd
);
10353 *(HWND
*)param
= hwnd
;
10357 /* Windows doesn't like when a thread plays games with the focus,
10358 * that leads to all kinds of misbehaviours and failures to activate
10359 * a window. So, better don't generate a mouse click message below.
10361 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10362 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
10363 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10366 while (GetMessageA(&msg
, 0, 0, 0))
10368 TranslateMessage(&msg
);
10369 DispatchMessageA(&msg
);
10374 static void test_winevents(void)
10380 HANDLE hthread
, hevent
;
10382 HWINEVENTHOOK hhook
;
10383 const struct message
*events
= WmWinEventsSeq
;
10385 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
10386 WS_OVERLAPPEDWINDOW
,
10387 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
10391 /****** start of global hook test *************/
10392 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
10393 if (!hCBT_global_hook
)
10395 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10396 skip( "cannot set global hook\n" );
10400 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10404 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
10405 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10407 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10409 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
10412 /* this one should be received only by old hook proc */
10413 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
10414 /* this one should be received only by old hook proc */
10415 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
10417 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
10419 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
10420 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
10422 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10423 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10424 CloseHandle(hthread
);
10425 CloseHandle(hevent
);
10426 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10427 /****** end of global hook test *************/
10429 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
10431 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10439 /* this test doesn't pass under Win9x */
10440 /* win2k ignores events with hwnd == 0 */
10441 SetLastError(0xdeadbeef);
10442 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
10443 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
10444 GetLastError() == 0xdeadbeef, /* Win9x */
10445 "unexpected error %d\n", GetLastError());
10446 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
10449 for (i
= 0; i
< sizeof(WmWinEventsSeq
)/sizeof(WmWinEventsSeq
[0]); i
++)
10450 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
10452 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
10454 /****** start of event filtering test *************/
10455 hhook
= pSetWinEventHook(
10456 EVENT_OBJECT_SHOW
, /* 0x8002 */
10457 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
10458 GetModuleHandleA(0), win_event_global_hook_proc
,
10459 GetCurrentProcessId(), 0,
10460 WINEVENT_INCONTEXT
);
10461 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10463 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10467 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
10468 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10470 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10472 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
10475 /* this one should be received only by old hook proc */
10476 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
10477 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
10478 /* this one should be received only by old hook proc */
10479 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
10481 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
10483 ret
= pUnhookWinEvent(hhook
);
10484 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10486 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10487 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10488 CloseHandle(hthread
);
10489 CloseHandle(hevent
);
10490 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10491 /****** end of event filtering test *************/
10493 /****** start of out of context event test *************/
10494 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
10495 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
10496 WINEVENT_OUTOFCONTEXT
);
10497 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10499 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10505 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
10506 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10508 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10510 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
10511 /* process pending winevent messages */
10512 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
10513 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
10516 /* this one should be received only by old hook proc */
10517 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
10518 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
10519 /* this one should be received only by old hook proc */
10520 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
10522 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
10523 /* process pending winevent messages */
10524 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
10525 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
10527 ret
= pUnhookWinEvent(hhook
);
10528 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10530 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10531 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10532 CloseHandle(hthread
);
10533 CloseHandle(hevent
);
10534 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10535 /****** end of out of context event test *************/
10537 /****** start of MOUSE_LL hook test *************/
10538 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
10539 /* WH_MOUSE_LL is not supported on Win9x platforms */
10540 if (!hCBT_global_hook
)
10542 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
10543 goto skip_mouse_ll_hook_test
;
10546 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
10550 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
10551 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
10553 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
10554 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
10556 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
10559 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10560 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
10561 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10563 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
10565 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
10566 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
10568 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10569 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10570 CloseHandle(hthread
);
10571 CloseHandle(hevent
);
10572 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10573 /****** end of MOUSE_LL hook test *************/
10574 skip_mouse_ll_hook_test
:
10576 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10579 static void test_set_hook(void)
10583 HWINEVENTHOOK hwinevent_hook
;
10585 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
10586 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
10587 UnhookWindowsHookEx(hhook
);
10591 /* this test doesn't pass under Win9x: BUG! */
10592 SetLastError(0xdeadbeef);
10593 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
10594 ok(!hhook
, "global hook requires hModule != 0\n");
10595 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %d\n", GetLastError());
10598 SetLastError(0xdeadbeef);
10599 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
10600 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
10601 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
|| /* Win2k */
10602 GetLastError() == 0xdeadbeef, /* Win9x */
10603 "unexpected error %d\n", GetLastError());
10605 SetLastError(0xdeadbeef);
10606 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
10607 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
|| /* Win2k */
10608 GetLastError() == 0xdeadbeef, /* Win9x */
10609 "unexpected error %d\n", GetLastError());
10611 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
10613 /* even process local incontext hooks require hmodule */
10614 SetLastError(0xdeadbeef);
10615 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10616 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
10617 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
10618 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
10619 GetLastError() == 0xdeadbeef, /* Win9x */
10620 "unexpected error %d\n", GetLastError());
10622 /* even thread local incontext hooks require hmodule */
10623 SetLastError(0xdeadbeef);
10624 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10625 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
10626 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
10627 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
10628 GetLastError() == 0xdeadbeef, /* Win9x */
10629 "unexpected error %d\n", GetLastError());
10633 /* these 3 tests don't pass under Win9x */
10634 SetLastError(0xdeadbeef);
10635 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
10636 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10637 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
10638 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
10640 SetLastError(0xdeadbeef);
10641 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
10642 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10643 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
10644 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
10646 SetLastError(0xdeadbeef);
10647 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10648 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
10649 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
10650 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %d\n", GetLastError());
10653 SetLastError(0xdeadbeef);
10654 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
10655 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10656 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10657 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10658 ret
= pUnhookWinEvent(hwinevent_hook
);
10659 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10662 /* This call succeeds under win2k SP4, but fails under Wine.
10663 Does win2k test/use passed process id? */
10664 SetLastError(0xdeadbeef);
10665 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10666 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
10667 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10668 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10669 ret
= pUnhookWinEvent(hwinevent_hook
);
10670 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10673 SetLastError(0xdeadbeef);
10674 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
10675 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
10676 GetLastError() == 0xdeadbeef, /* Win9x */
10677 "unexpected error %d\n", GetLastError());
10680 static HWND hook_hwnd
;
10681 static HHOOK recursive_hook
;
10682 static int hook_depth
, max_hook_depth
;
10684 static LRESULT WINAPI
rec_get_message_hook(int code
, WPARAM w
, LPARAM l
)
10691 if(hook_depth
> max_hook_depth
)
10692 max_hook_depth
= hook_depth
;
10694 b
= PeekMessageW(&msg
, hook_hwnd
, 0, 0, PM_NOREMOVE
);
10695 ok(b
, "PeekMessage failed\n");
10697 res
= CallNextHookEx(recursive_hook
, code
, w
, l
);
10703 static void test_recursive_hook(void)
10708 hook_hwnd
= CreateWindowA("Static", NULL
, WS_POPUP
, 0, 0, 200, 60, NULL
, NULL
, NULL
, NULL
);
10709 ok(hook_hwnd
!= NULL
, "CreateWindow failed\n");
10711 recursive_hook
= SetWindowsHookExW(WH_GETMESSAGE
, rec_get_message_hook
, NULL
, GetCurrentThreadId());
10712 ok(recursive_hook
!= NULL
, "SetWindowsHookEx failed\n");
10714 PostMessageW(hook_hwnd
, WM_USER
, 0, 0);
10715 PostMessageW(hook_hwnd
, WM_USER
+1, 0, 0);
10718 GetMessageW(&msg
, hook_hwnd
, 0, 0);
10719 ok(15 <= max_hook_depth
&& max_hook_depth
< 45, "max_hook_depth = %d\n", max_hook_depth
);
10720 trace("max_hook_depth = %d\n", max_hook_depth
);
10722 b
= UnhookWindowsHookEx(recursive_hook
);
10723 ok(b
, "UnhokWindowsHookEx failed\n");
10725 DestroyWindow(hook_hwnd
);
10728 static const struct message ScrollWindowPaint1
[] = {
10729 { WM_PAINT
, sent
},
10730 { WM_ERASEBKGND
, sent
|beginpaint
},
10731 { WM_GETTEXTLENGTH
, sent
|optional
},
10732 { WM_PAINT
, sent
|optional
},
10733 { WM_NCPAINT
, sent
|beginpaint
|optional
},
10734 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10735 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10736 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10737 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
10738 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
10742 static const struct message ScrollWindowPaint2
[] = {
10743 { WM_PAINT
, sent
},
10747 static void test_scrollwindowex(void)
10750 RECT rect
={0,0,130,130};
10752 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
10753 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
10754 100, 100, 200, 200, 0, 0, 0, NULL
);
10755 ok (hwnd
!= 0, "Failed to create overlapped window\n");
10756 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
10757 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
10758 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
10759 ok (hchild
!= 0, "Failed to create child\n");
10760 UpdateWindow(hwnd
);
10764 /* scroll without the child window */
10765 trace("start scroll\n");
10766 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
10767 SW_ERASE
|SW_INVALIDATE
);
10768 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
10769 trace("end scroll\n");
10772 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
10776 /* Now without the SW_ERASE flag */
10777 trace("start scroll\n");
10778 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
10779 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
10780 trace("end scroll\n");
10783 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
10787 /* now scroll the child window as well */
10788 trace("start scroll\n");
10789 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
10790 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
10791 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
10792 /* windows sometimes a WM_MOVE */
10793 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
10794 trace("end scroll\n");
10797 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
10801 /* now scroll with ScrollWindow() */
10802 trace("start scroll with ScrollWindow\n");
10803 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
10804 trace("end scroll\n");
10807 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
10809 ok(DestroyWindow(hchild
), "failed to destroy window\n");
10810 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10814 static const struct message destroy_window_with_children
[] = {
10815 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
10816 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10817 { 0x0090, sent
|optional
},
10818 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10819 { 0x0090, sent
|optional
},
10820 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
10821 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10822 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10823 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10824 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* parent */
10825 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10826 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
10827 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
10828 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
10829 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
10830 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
10831 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
10832 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10836 static void test_DestroyWindow(void)
10839 HWND parent
, child1
, child2
, child3
, child4
, test
;
10840 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
10842 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
10843 100, 100, 200, 200, 0, 0, 0, NULL
);
10844 assert(parent
!= 0);
10845 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10846 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
10847 assert(child1
!= 0);
10848 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10849 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
10850 assert(child2
!= 0);
10851 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10852 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
10853 assert(child3
!= 0);
10854 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
10855 0, 0, 50, 50, parent
, 0, 0, NULL
);
10856 assert(child4
!= 0);
10858 /* test owner/parent of child2 */
10859 test
= GetParent(child2
);
10860 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10861 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
10863 test
= pGetAncestor(child2
, GA_PARENT
);
10864 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10866 test
= GetWindow(child2
, GW_OWNER
);
10867 ok(!test
, "wrong owner %p\n", test
);
10869 test
= SetParent(child2
, parent
);
10870 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
10872 /* test owner/parent of the parent */
10873 test
= GetParent(parent
);
10874 ok(!test
, "wrong parent %p\n", test
);
10875 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
10877 test
= pGetAncestor(parent
, GA_PARENT
);
10878 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10880 test
= GetWindow(parent
, GW_OWNER
);
10881 ok(!test
, "wrong owner %p\n", test
);
10883 /* test owner/parent of child1 */
10884 test
= GetParent(child1
);
10885 ok(test
== parent
, "wrong parent %p\n", test
);
10886 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
10888 test
= pGetAncestor(child1
, GA_PARENT
);
10889 ok(test
== parent
, "wrong parent %p\n", test
);
10891 test
= GetWindow(child1
, GW_OWNER
);
10892 ok(!test
, "wrong owner %p\n", test
);
10894 /* test owner/parent of child2 */
10895 test
= GetParent(child2
);
10896 ok(test
== parent
, "wrong parent %p\n", test
);
10897 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
10899 test
= pGetAncestor(child2
, GA_PARENT
);
10900 ok(test
== parent
, "wrong parent %p\n", test
);
10902 test
= GetWindow(child2
, GW_OWNER
);
10903 ok(!test
, "wrong owner %p\n", test
);
10905 /* test owner/parent of child3 */
10906 test
= GetParent(child3
);
10907 ok(test
== child1
, "wrong parent %p\n", test
);
10908 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
10910 test
= pGetAncestor(child3
, GA_PARENT
);
10911 ok(test
== child1
, "wrong parent %p\n", test
);
10913 test
= GetWindow(child3
, GW_OWNER
);
10914 ok(!test
, "wrong owner %p\n", test
);
10916 /* test owner/parent of child4 */
10917 test
= GetParent(child4
);
10918 ok(test
== parent
, "wrong parent %p\n", test
);
10919 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
10921 test
= pGetAncestor(child4
, GA_PARENT
);
10922 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10924 test
= GetWindow(child4
, GW_OWNER
);
10925 ok(test
== parent
, "wrong owner %p\n", test
);
10929 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
10930 parent
, child1
, child2
, child3
, child4
);
10932 SetCapture(child4
);
10933 test
= GetCapture();
10934 ok(test
== child4
, "wrong capture window %p\n", test
);
10936 test_DestroyWindow_flag
= TRUE
;
10937 ret
= DestroyWindow(parent
);
10938 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
10939 test_DestroyWindow_flag
= FALSE
;
10940 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
10942 ok(!IsWindow(parent
), "parent still exists\n");
10943 ok(!IsWindow(child1
), "child1 still exists\n");
10944 ok(!IsWindow(child2
), "child2 still exists\n");
10945 ok(!IsWindow(child3
), "child3 still exists\n");
10946 ok(!IsWindow(child4
), "child4 still exists\n");
10948 test
= GetCapture();
10949 ok(!test
, "wrong capture window %p\n", test
);
10953 static const struct message WmDispatchPaint
[] = {
10954 { WM_NCPAINT
, sent
},
10955 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10956 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10957 { WM_ERASEBKGND
, sent
},
10961 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10963 if (message
== WM_PAINT
) return 0;
10964 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
10967 static void test_DispatchMessage(void)
10972 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
10973 100, 100, 200, 200, 0, 0, 0, NULL
);
10974 ShowWindow( hwnd
, SW_SHOW
);
10975 UpdateWindow( hwnd
);
10978 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
10980 SetRect( &rect
, -5, -5, 5, 5 );
10981 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
10983 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
10985 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
10989 DispatchMessageA( &msg
);
10990 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
10991 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
10992 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
10993 if (++count
> 10) break;
10996 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
10998 trace("now without DispatchMessage\n");
11000 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11002 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11004 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11007 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
11009 /* this will send WM_NCCPAINT just like DispatchMessage does */
11010 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
11011 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11012 DeleteObject( hrgn
);
11013 GetClientRect( hwnd
, &rect
);
11014 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
11015 ok( !count
, "Got multiple WM_PAINTs\n" );
11016 if (++count
> 10) break;
11021 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
11023 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
11025 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
11031 hdc
= BeginPaint( hwnd
, NULL
);
11032 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
11033 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
11034 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
11035 ok( !count
, "Got multiple WM_PAINTs\n" );
11036 if (++count
> 10) break;
11039 DestroyWindow(hwnd
);
11043 static const struct message WmUser
[] = {
11048 struct sendmsg_info
11055 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
11057 struct sendmsg_info
*info
= arg
;
11058 SetLastError( 0xdeadbeef );
11059 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
11060 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
11061 broken(GetLastError() == 0), /* win9x */
11062 "unexpected error %d\n", GetLastError());
11066 static void wait_for_thread( HANDLE thread
)
11068 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
11071 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11075 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11077 if (message
== WM_USER
) Sleep(200);
11078 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
11081 static void test_SendMessageTimeout(void)
11084 struct sendmsg_info info
;
11088 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11089 100, 100, 200, 200, 0, 0, 0, NULL
);
11093 info
.timeout
= 1000;
11094 info
.ret
= 0xdeadbeef;
11095 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11096 wait_for_thread( thread
);
11097 CloseHandle( thread
);
11098 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11099 ok_sequence( WmUser
, "WmUser", FALSE
);
11102 info
.ret
= 0xdeadbeef;
11103 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11104 Sleep(100); /* SendMessageTimeout should time out here */
11105 wait_for_thread( thread
);
11106 CloseHandle( thread
);
11107 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
11108 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11110 /* 0 means infinite timeout (but not on win9x) */
11112 info
.ret
= 0xdeadbeef;
11113 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11115 wait_for_thread( thread
);
11116 CloseHandle( thread
);
11117 is_win9x
= !info
.ret
;
11118 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11119 else ok_sequence( WmUser
, "WmUser", FALSE
);
11121 /* timeout is treated as signed despite the prototype (but not on win9x) */
11122 info
.timeout
= 0x7fffffff;
11123 info
.ret
= 0xdeadbeef;
11124 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11126 wait_for_thread( thread
);
11127 CloseHandle( thread
);
11128 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11129 ok_sequence( WmUser
, "WmUser", FALSE
);
11131 info
.timeout
= 0x80000000;
11132 info
.ret
= 0xdeadbeef;
11133 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11135 wait_for_thread( thread
);
11136 CloseHandle( thread
);
11139 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
11140 ok_sequence( WmUser
, "WmUser", FALSE
);
11144 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
11145 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
11148 /* now check for timeout during message processing */
11149 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
11150 info
.timeout
= 100;
11151 info
.ret
= 0xdeadbeef;
11152 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
11153 wait_for_thread( thread
);
11154 CloseHandle( thread
);
11155 /* we should time out but still get the message */
11156 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
11157 ok_sequence( WmUser
, "WmUser", FALSE
);
11159 DestroyWindow( info
.hwnd
);
11163 /****************** edit message test *************************/
11164 #define ID_EDIT 0x1234
11165 static const struct message sl_edit_setfocus
[] =
11167 { HCBT_SETFOCUS
, hook
},
11168 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11169 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11170 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11171 { WM_SETFOCUS
, sent
|wparam
, 0 },
11172 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11173 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
11174 { WM_CTLCOLOREDIT
, sent
|parent
},
11175 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11176 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11177 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11178 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11181 static const struct message sl_edit_invisible
[] =
11183 { HCBT_SETFOCUS
, hook
},
11184 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11185 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11186 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11187 { WM_KILLFOCUS
, sent
|parent
},
11188 { WM_SETFOCUS
, sent
},
11189 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11192 static const struct message ml_edit_setfocus
[] =
11194 { HCBT_SETFOCUS
, hook
},
11195 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11196 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11197 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11198 { WM_SETFOCUS
, sent
|wparam
, 0 },
11199 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11200 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11201 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11202 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11203 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11206 static const struct message sl_edit_killfocus
[] =
11208 { HCBT_SETFOCUS
, hook
},
11209 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11210 { WM_KILLFOCUS
, sent
|wparam
, 0 },
11211 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11212 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11213 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
11214 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
11215 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11218 static const struct message sl_edit_lbutton_dblclk
[] =
11220 { WM_LBUTTONDBLCLK
, sent
},
11221 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
11224 static const struct message sl_edit_lbutton_down
[] =
11226 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
11227 { HCBT_SETFOCUS
, hook
},
11228 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11229 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11230 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11231 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
11232 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11233 { WM_CTLCOLOREDIT
, sent
|parent
},
11234 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11235 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11236 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11237 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11238 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11239 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
11240 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11241 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
11242 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11243 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11244 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11247 static const struct message ml_edit_lbutton_down
[] =
11249 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
11250 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
11251 { HCBT_SETFOCUS
, hook
},
11252 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11253 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11254 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11255 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
11256 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11257 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11258 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11259 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11260 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
11263 static const struct message sl_edit_lbutton_up
[] =
11265 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
11266 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11267 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
11268 { WM_CAPTURECHANGED
, sent
|defwinproc
},
11269 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11272 static const struct message ml_edit_lbutton_up
[] =
11274 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
11275 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
11276 { WM_CAPTURECHANGED
, sent
|defwinproc
},
11280 static WNDPROC old_edit_proc
;
11282 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11284 static LONG defwndproc_counter
= 0;
11286 struct recvd_message msg
;
11288 if (ignore_message( message
)) return 0;
11291 msg
.message
= message
;
11292 msg
.flags
= sent
|wparam
|lparam
;
11293 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11294 msg
.wParam
= wParam
;
11295 msg
.lParam
= lParam
;
11296 msg
.descr
= "edit";
11299 defwndproc_counter
++;
11300 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
11301 defwndproc_counter
--;
11306 static void subclass_edit(void)
11310 if (!GetClassInfoA(0, "edit", &cls
)) assert(0);
11312 old_edit_proc
= cls
.lpfnWndProc
;
11314 cls
.hInstance
= GetModuleHandleA(NULL
);
11315 cls
.lpfnWndProc
= edit_hook_proc
;
11316 cls
.lpszClassName
= "my_edit_class";
11317 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
11318 if (!RegisterClassA(&cls
)) assert(0);
11321 static void test_edit_messages(void)
11327 log_all_parent_messages
++;
11329 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11330 100, 100, 200, 200, 0, 0, 0, NULL
);
11331 ok (parent
!= 0, "Failed to create parent window\n");
11333 /* test single line edit */
11334 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
11335 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
11336 ok(hwnd
!= 0, "Failed to create edit window\n");
11338 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
11339 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08x\n", dlg_code
);
11343 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
11345 ShowWindow(hwnd
, SW_SHOW
);
11346 UpdateWindow(hwnd
);
11351 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
11354 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
11360 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
11361 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
11367 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
11368 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
11370 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
11371 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
11373 DestroyWindow(hwnd
);
11375 /* test multiline edit */
11376 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
11377 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
11378 ok(hwnd
!= 0, "Failed to create edit window\n");
11380 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
11381 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
11382 "wrong dlg_code %08x\n", dlg_code
);
11384 ShowWindow(hwnd
, SW_SHOW
);
11385 UpdateWindow(hwnd
);
11390 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
11393 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
11399 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
11400 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
11406 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
11407 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
11409 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
11410 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
11412 DestroyWindow(hwnd
);
11413 DestroyWindow(parent
);
11415 log_all_parent_messages
--;
11418 /**************************** End of Edit test ******************************/
11420 static const struct message WmKeyDownSkippedSeq
[] =
11422 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
11425 static const struct message WmKeyDownWasDownSkippedSeq
[] =
11427 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
11430 static const struct message WmKeyUpSkippedSeq
[] =
11432 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
11435 static const struct message WmUserKeyUpSkippedSeq
[] =
11438 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
11443 #define EV_SENDMSG 1
11446 struct peekmsg_info
11449 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
11452 static DWORD CALLBACK
send_msg_thread_2(void *param
)
11455 struct peekmsg_info
*info
= param
;
11457 trace("thread: looping\n");
11458 SetEvent(info
->hevent
[EV_ACK
]);
11462 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
11466 case WAIT_OBJECT_0
+ EV_STOP
:
11467 trace("thread: exiting\n");
11470 case WAIT_OBJECT_0
+ EV_SENDMSG
:
11471 trace("thread: sending message\n");
11472 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
11473 ok(ret
, "SendNotifyMessageA failed error %u\n", GetLastError());
11474 SetEvent(info
->hevent
[EV_ACK
]);
11478 trace("unexpected return: %04x\n", ret
);
11486 static void test_PeekMessage(void)
11490 DWORD tid
, qstatus
;
11491 UINT qs_all_input
= QS_ALLINPUT
;
11492 UINT qs_input
= QS_INPUT
;
11494 struct peekmsg_info info
;
11496 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11497 100, 100, 200, 200, 0, 0, 0, NULL
);
11499 ShowWindow(info
.hwnd
, SW_SHOW
);
11500 UpdateWindow(info
.hwnd
);
11501 SetFocus(info
.hwnd
);
11503 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
11504 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
11505 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
11507 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
11508 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
11513 SetLastError(0xdeadbeef);
11514 qstatus
= GetQueueStatus(qs_all_input
);
11515 if (GetLastError() == ERROR_INVALID_FLAGS
)
11517 trace("QS_RAWINPUT not supported on this platform\n");
11518 qs_all_input
&= ~QS_RAWINPUT
;
11519 qs_input
&= ~QS_RAWINPUT
;
11521 if (qstatus
& QS_POSTMESSAGE
)
11523 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
11524 qstatus
= GetQueueStatus(qs_all_input
);
11526 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11528 trace("signalling to send message\n");
11529 SetEvent(info
.hevent
[EV_SENDMSG
]);
11530 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11532 /* pass invalid QS_xxxx flags */
11533 SetLastError(0xdeadbeef);
11534 qstatus
= GetQueueStatus(0xffffffff);
11535 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus
);
11538 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %d\n", GetLastError());
11539 qstatus
= GetQueueStatus(qs_all_input
);
11541 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
11542 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
),
11543 "wrong qstatus %08x\n", qstatus
);
11546 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11548 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11550 ok_sequence(WmUser
, "WmUser", FALSE
);
11552 qstatus
= GetQueueStatus(qs_all_input
);
11553 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11555 keybd_event('N', 0, 0, 0);
11556 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
11557 qstatus
= GetQueueStatus(qs_all_input
);
11558 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
11560 skip( "queuing key events not supported\n" );
11563 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
11564 /* keybd_event seems to trigger a sent message on NT4 */
11565 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
11566 "wrong qstatus %08x\n", qstatus
);
11568 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11569 qstatus
= GetQueueStatus(qs_all_input
);
11570 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
11571 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
11572 "wrong qstatus %08x\n", qstatus
);
11574 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
11575 qstatus
= GetQueueStatus(qs_all_input
);
11576 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
11577 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
11578 "wrong qstatus %08x\n", qstatus
);
11580 trace("signalling to send message\n");
11581 SetEvent(info
.hevent
[EV_SENDMSG
]);
11582 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11584 qstatus
= GetQueueStatus(qs_all_input
);
11585 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11586 "wrong qstatus %08x\n", qstatus
);
11589 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
11590 if (ret
&& msg
.message
== WM_CHAR
)
11592 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11596 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11598 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
11600 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11603 ok_sequence(WmUser
, "WmUser", FALSE
);
11605 qstatus
= GetQueueStatus(qs_all_input
);
11606 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11607 "wrong qstatus %08x\n", qstatus
);
11609 trace("signalling to send message\n");
11610 SetEvent(info
.hevent
[EV_SENDMSG
]);
11611 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11613 qstatus
= GetQueueStatus(qs_all_input
);
11614 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11615 "wrong qstatus %08x\n", qstatus
);
11618 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11620 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11622 ok_sequence(WmUser
, "WmUser", FALSE
);
11624 qstatus
= GetQueueStatus(qs_all_input
);
11625 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11626 "wrong qstatus %08x\n", qstatus
);
11629 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11630 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11631 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11632 ret
, msg
.message
, msg
.wParam
);
11633 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11635 qstatus
= GetQueueStatus(qs_all_input
);
11636 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
11637 "wrong qstatus %08x\n", qstatus
);
11640 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11642 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11644 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11646 qstatus
= GetQueueStatus(qs_all_input
);
11647 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
11648 "wrong qstatus %08x\n", qstatus
);
11651 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
11652 ok(ret
&& msg
.message
== WM_PAINT
,
11653 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
11654 DispatchMessageA(&msg
);
11655 ok_sequence(WmPaint
, "WmPaint", FALSE
);
11657 qstatus
= GetQueueStatus(qs_all_input
);
11658 ok(qstatus
== MAKELONG(0, QS_KEY
),
11659 "wrong qstatus %08x\n", qstatus
);
11662 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
11664 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11666 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11668 qstatus
= GetQueueStatus(qs_all_input
);
11669 ok(qstatus
== MAKELONG(0, QS_KEY
),
11670 "wrong qstatus %08x\n", qstatus
);
11672 trace("signalling to send message\n");
11673 SetEvent(info
.hevent
[EV_SENDMSG
]);
11674 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11676 qstatus
= GetQueueStatus(qs_all_input
);
11677 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
11678 "wrong qstatus %08x\n", qstatus
);
11680 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11682 qstatus
= GetQueueStatus(qs_all_input
);
11683 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11684 "wrong qstatus %08x\n", qstatus
);
11687 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
11688 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11689 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11690 ret
, msg
.message
, msg
.wParam
);
11691 ok_sequence(WmUser
, "WmUser", FALSE
);
11693 qstatus
= GetQueueStatus(qs_all_input
);
11694 ok(qstatus
== MAKELONG(0, QS_KEY
),
11695 "wrong qstatus %08x\n", qstatus
);
11698 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
11700 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11702 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11704 qstatus
= GetQueueStatus(qs_all_input
);
11705 ok(qstatus
== MAKELONG(0, QS_KEY
),
11706 "wrong qstatus %08x\n", qstatus
);
11708 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11710 qstatus
= GetQueueStatus(qs_all_input
);
11711 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
11712 "wrong qstatus %08x\n", qstatus
);
11714 trace("signalling to send message\n");
11715 SetEvent(info
.hevent
[EV_SENDMSG
]);
11716 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11718 qstatus
= GetQueueStatus(qs_all_input
);
11719 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11720 "wrong qstatus %08x\n", qstatus
);
11723 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
11725 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11727 ok_sequence(WmUser
, "WmUser", FALSE
);
11729 qstatus
= GetQueueStatus(qs_all_input
);
11730 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
11731 "wrong qstatus %08x\n", qstatus
);
11734 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
11735 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
11736 else /* workaround for a missing QS_RAWINPUT support */
11737 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
11738 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11739 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11740 ret
, msg
.message
, msg
.wParam
);
11741 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
11743 qstatus
= GetQueueStatus(qs_all_input
);
11744 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
11745 "wrong qstatus %08x\n", qstatus
);
11748 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
11749 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
11750 else /* workaround for a missing QS_RAWINPUT support */
11751 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
11752 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
11753 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n",
11754 ret
, msg
.message
, msg
.wParam
);
11755 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
11757 qstatus
= GetQueueStatus(qs_all_input
);
11758 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11759 "wrong qstatus %08x\n", qstatus
);
11762 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
11764 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11766 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11768 qstatus
= GetQueueStatus(qs_all_input
);
11769 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11770 "wrong qstatus %08x\n", qstatus
);
11773 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11774 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11775 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11776 ret
, msg
.message
, msg
.wParam
);
11777 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11779 qstatus
= GetQueueStatus(qs_all_input
);
11781 "wrong qstatus %08x\n", qstatus
);
11784 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11786 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11788 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11790 qstatus
= GetQueueStatus(qs_all_input
);
11792 "wrong qstatus %08x\n", qstatus
);
11794 /* test whether presence of the quit flag in the queue affects
11797 PostQuitMessage(0x1234abcd);
11799 qstatus
= GetQueueStatus(qs_all_input
);
11800 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
11801 "wrong qstatus %08x\n", qstatus
);
11803 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
11805 qstatus
= GetQueueStatus(qs_all_input
);
11806 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
11807 "wrong qstatus %08x\n", qstatus
);
11810 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11811 ok(ret
&& msg
.message
== WM_USER
,
11812 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
11813 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11815 qstatus
= GetQueueStatus(qs_all_input
);
11816 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11817 "wrong qstatus %08x\n", qstatus
);
11820 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11821 ok(ret
&& msg
.message
== WM_QUIT
,
11822 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
11823 ok(msg
.wParam
== 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg
.wParam
);
11824 ok(msg
.lParam
== 0, "got lParam %08lx instead of 0\n", msg
.lParam
);
11825 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11827 qstatus
= GetQueueStatus(qs_all_input
);
11829 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11830 "wrong qstatus %08x\n", qstatus
);
11834 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11836 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11838 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11840 qstatus
= GetQueueStatus(qs_all_input
);
11842 "wrong qstatus %08x\n", qstatus
);
11844 /* some GetMessage tests */
11846 keybd_event('N', 0, 0, 0);
11847 qstatus
= GetQueueStatus(qs_all_input
);
11848 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11850 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11851 qstatus
= GetQueueStatus(qs_all_input
);
11852 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11856 ret
= GetMessageA( &msg
, 0, 0, 0 );
11857 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11858 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11859 ret
, msg
.message
, msg
.wParam
);
11860 qstatus
= GetQueueStatus(qs_all_input
);
11861 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11866 ret
= GetMessageA( &msg
, 0, 0, 0 );
11867 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11868 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11869 ret
, msg
.message
, msg
.wParam
);
11870 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
11871 qstatus
= GetQueueStatus(qs_all_input
);
11872 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11875 keybd_event('N', 0, 0, 0);
11876 qstatus
= GetQueueStatus(qs_all_input
);
11877 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11879 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11880 qstatus
= GetQueueStatus(qs_all_input
);
11881 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11883 if (qstatus
& (QS_KEY
<< 16))
11885 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
11886 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11887 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11888 ret
, msg
.message
, msg
.wParam
);
11889 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
11890 qstatus
= GetQueueStatus(qs_all_input
);
11891 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
11896 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
11897 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11898 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11899 ret
, msg
.message
, msg
.wParam
);
11900 qstatus
= GetQueueStatus(qs_all_input
);
11901 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11904 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
11905 qstatus
= GetQueueStatus(qs_all_input
);
11906 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11908 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11909 qstatus
= GetQueueStatus(qs_all_input
);
11910 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11912 trace("signalling to send message\n");
11913 SetEvent(info
.hevent
[EV_SENDMSG
]);
11914 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11915 qstatus
= GetQueueStatus(qs_all_input
);
11916 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11917 "wrong qstatus %08x\n", qstatus
);
11919 if (qstatus
& (QS_KEY
<< 16))
11921 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
11922 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
11923 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11924 ret
, msg
.message
, msg
.wParam
);
11925 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
11926 qstatus
= GetQueueStatus(qs_all_input
);
11927 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
11932 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
11933 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11934 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11935 ret
, msg
.message
, msg
.wParam
);
11936 qstatus
= GetQueueStatus(qs_all_input
);
11937 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11940 trace("signalling to exit\n");
11941 SetEvent(info
.hevent
[EV_STOP
]);
11943 WaitForSingleObject(hthread
, INFINITE
);
11945 CloseHandle(hthread
);
11946 CloseHandle(info
.hevent
[0]);
11947 CloseHandle(info
.hevent
[1]);
11948 CloseHandle(info
.hevent
[2]);
11950 DestroyWindow(info
.hwnd
);
11953 static void wait_move_event(HWND hwnd
, int x
, int y
)
11959 time
= GetTickCount();
11960 while (GetTickCount() - time
< 200) {
11961 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
11962 if (ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
) break;
11963 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, GetTickCount() - time
, QS_ALLINPUT
);
11964 else Sleep( GetTickCount() - time
);
11969 static void test_PeekMessage2(void)
11975 DWORD time1
, time2
, time3
;
11976 int x1
, y1
, x2
, y2
, x3
, y3
;
11979 time1
= time2
= time3
= 0;
11980 x1
= y1
= x2
= y2
= x3
= y3
= 0;
11982 /* Initialise window and make sure it is ready for events */
11983 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
11984 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
11986 trace("Window for test_PeekMessage2 %p\n", hwnd
);
11987 ShowWindow(hwnd
, SW_SHOW
);
11988 UpdateWindow(hwnd
);
11990 GetCursorPos(&pos
);
11991 SetCursorPos(100, 100);
11992 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
11995 /* Do initial mousemove, wait until we can see it
11996 and then do our test peek with PM_NOREMOVE. */
11997 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
11998 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
12000 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12003 skip( "queuing mouse events not supported\n" );
12008 trace("1st move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
12009 message
= msg
.message
;
12013 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
12016 /* Allow time to advance a bit, and then simulate the user moving their
12017 * mouse around. After that we peek again with PM_NOREMOVE.
12018 * Although the previous mousemove message was never removed, the
12019 * mousemove we now peek should reflect the recent mouse movements
12020 * because the input queue will merge the move events. */
12022 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
12023 wait_move_event(hwnd
, x1
, y1
);
12025 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12026 ok(ret
, "no message available\n");
12028 trace("2nd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
12029 message
= msg
.message
;
12033 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
12034 ok(time2
> time1
, "message time not advanced: %x %x\n", time1
, time2
);
12035 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
12038 /* Have another go, to drive the point home */
12040 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
12041 wait_move_event(hwnd
, x2
, y2
);
12043 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
12044 ok(ret
, "no message available\n");
12046 trace("3rd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
12047 message
= msg
.message
;
12051 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
12052 ok(time3
> time2
, "message time not advanced: %x %x\n", time2
, time3
);
12053 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
12057 DestroyWindow(hwnd
);
12058 SetCursorPos(pos
.x
, pos
.y
);
12062 static void test_PeekMessage3(void)
12068 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW
,
12069 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
12070 ok(hwnd
!= NULL
, "expected hwnd != NULL\n");
12073 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
12074 * were already seen. */
12076 SetTimer(hwnd
, 1, 0, NULL
);
12077 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
12078 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12079 PostMessageA(hwnd
, WM_USER
, 0, 0);
12080 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
12081 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12082 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12083 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12084 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12085 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12086 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12087 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12089 SetTimer(hwnd
, 1, 0, NULL
);
12090 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
12091 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12092 PostMessageA(hwnd
, WM_USER
, 0, 0);
12093 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12094 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12095 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12096 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12097 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12098 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12100 /* It doesn't matter if a message range is specified or not. */
12102 SetTimer(hwnd
, 1, 0, NULL
);
12103 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12104 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12105 PostMessageA(hwnd
, WM_USER
, 0, 0);
12106 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12107 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12108 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12109 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12110 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12111 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12113 /* But not if the post messages were added before the PeekMessage() call. */
12115 PostMessageA(hwnd
, WM_USER
, 0, 0);
12116 SetTimer(hwnd
, 1, 0, NULL
);
12117 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12118 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12119 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12120 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12121 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12122 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12123 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12124 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12126 /* More complicated test with multiple messages. */
12128 PostMessageA(hwnd
, WM_USER
, 0, 0);
12129 SetTimer(hwnd
, 1, 0, NULL
);
12130 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12131 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12132 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
12133 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12134 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12135 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12136 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12137 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12138 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
12139 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12140 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12142 /* Newer messages are still returned when specifying a message range. */
12144 SetTimer(hwnd
, 1, 0, NULL
);
12145 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12146 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12147 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
12148 PostMessageA(hwnd
, WM_USER
, 0, 0);
12149 ret
= PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
12150 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12151 ret
= PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
+ 1, PM_NOREMOVE
);
12152 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
12153 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12154 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12155 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12156 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
12157 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12158 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12159 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12160 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12162 /* Also works for posted messages, but the situation is a bit different,
12163 * because both messages are in the same queue. */
12165 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
12166 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12167 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12168 PostMessageA(hwnd
, WM_USER
, 0, 0);
12169 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12170 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12171 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12172 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12173 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12174 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12176 PostMessageA(hwnd
, WM_USER
, 0, 0);
12177 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
12178 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
12179 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12180 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12181 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
12182 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12183 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
12184 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
12185 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
12187 DestroyWindow(hwnd
);
12191 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12193 struct recvd_message msg
;
12195 if (ignore_message( message
)) return 0;
12198 msg
.message
= message
;
12199 msg
.flags
= sent
|wparam
|lparam
;
12202 msg
.descr
= "dialog";
12207 case WM_INITDIALOG
:
12208 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
12209 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
12212 case WM_GETDLGCODE
:
12216 EndDialog(hwnd
, 0);
12223 static const struct message WmQuitDialogSeq
[] = {
12224 { HCBT_CREATEWND
, hook
},
12225 { WM_SETFONT
, sent
},
12226 { WM_INITDIALOG
, sent
},
12227 { WM_CHANGEUISTATE
, sent
|optional
},
12228 { HCBT_DESTROYWND
, hook
},
12229 { 0x0090, sent
|optional
}, /* Vista */
12230 { WM_DESTROY
, sent
},
12231 { WM_NCDESTROY
, sent
},
12235 static const struct message WmStopQuitSeq
[] = {
12236 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
12237 { WM_CLOSE
, posted
},
12238 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
12242 static void test_quit_message(void)
12247 /* test using PostQuitMessage */
12249 PostQuitMessage(0xbeef);
12252 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_QS_SENDMESSAGE
);
12253 ok(!ret
, "got %x message\n", msg
.message
);
12255 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
12256 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
12257 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12258 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
12260 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
12261 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
12263 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12264 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
12265 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
12267 /* note: WM_QUIT message received after WM_USER message */
12268 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12269 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
12270 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12271 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
12273 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12274 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
12276 /* now test with PostThreadMessage - different behaviour! */
12277 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
12279 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
12280 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
12281 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12282 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
12284 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
12285 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
12287 /* note: we receive the WM_QUIT message first this time */
12288 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12289 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
12290 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12291 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
12293 ret
= GetMessageA(&msg
, NULL
, 0, 0);
12294 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
12295 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
12299 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
12300 ok(ret
== 1, "expected 1, got %d\n", ret
);
12301 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
12302 memset(&msg
, 0xab, sizeof(msg
));
12303 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
12304 ok(ret
, "PeekMessage failed\n");
12305 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
12306 ok(msg
.wParam
== 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg
.wParam
);
12307 ok(msg
.lParam
== 0, "lParam was 0x%lx instead of 0\n", msg
.lParam
);
12309 /* Check what happens to a WM_QUIT message posted to a window that gets
12312 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
12313 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
12315 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12317 struct recvd_message rmsg
;
12318 rmsg
.hwnd
= msg
.hwnd
;
12319 rmsg
.message
= msg
.message
;
12320 rmsg
.flags
= posted
|wparam
|lparam
;
12321 rmsg
.wParam
= msg
.wParam
;
12322 rmsg
.lParam
= msg
.lParam
;
12323 rmsg
.descr
= "stop/quit";
12324 if (msg
.message
== WM_QUIT
)
12325 /* The hwnd can only be checked here */
12326 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
12327 add_message(&rmsg
);
12328 DispatchMessageA(&msg
);
12330 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
12333 static const struct message WmNotifySeq
[] = {
12334 { WM_NOTIFY
, sent
|wparam
|lparam
, 0x1234, 0xdeadbeef },
12338 static void test_notify_message(void)
12344 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12345 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0, NULL
, NULL
, 0);
12346 ok(hwnd
!= 0, "Failed to create window\n");
12350 ret
= SendNotifyMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12351 ok(ret
== TRUE
, "SendNotifyMessageA failed with error %u\n", GetLastError());
12352 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12354 ret
= SendNotifyMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12355 ok(ret
== TRUE
, "SendNotifyMessageW failed with error %u\n", GetLastError());
12356 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12358 ret
= SendMessageCallbackA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
12359 ok(ret
== TRUE
, "SendMessageCallbackA failed with error %u\n", GetLastError());
12360 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12362 ret
= SendMessageCallbackW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
12363 ok(ret
== TRUE
, "SendMessageCallbackW failed with error %u\n", GetLastError());
12364 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12366 ret
= PostMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12367 ok(ret
== TRUE
, "PostMessageA failed with error %u\n", GetLastError());
12369 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12371 ret
= PostMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
12372 ok(ret
== TRUE
, "PostMessageW failed with error %u\n", GetLastError());
12374 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12376 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
12377 ok(ret
== TRUE
, "PostThreadMessageA failed with error %u\n", GetLastError());
12378 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12381 DispatchMessageA(&msg
);
12383 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12385 ret
= PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
12386 ok(ret
== TRUE
, "PostThreadMessageW failed with error %u\n", GetLastError());
12387 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12390 DispatchMessageA(&msg
);
12392 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
12394 DestroyWindow(hwnd
);
12397 static const struct message WmMouseHoverSeq
[] = {
12398 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
12399 { WM_MOUSEACTIVATE
, sent
|optional
},
12400 { WM_TIMER
, sent
|optional
}, /* XP sends it */
12401 { WM_SYSTIMER
, sent
},
12402 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
12406 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
12409 DWORD start_ticks
, end_ticks
;
12411 start_ticks
= GetTickCount();
12412 /* add some deviation (50%) to cover not expected delays */
12413 start_ticks
+= timeout
/ 2;
12417 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12419 /* Timer proc messages are not dispatched to the window proc,
12420 * and therefore not logged.
12422 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
12424 struct recvd_message s_msg
;
12426 s_msg
.hwnd
= msg
.hwnd
;
12427 s_msg
.message
= msg
.message
;
12428 s_msg
.flags
= sent
|wparam
|lparam
;
12429 s_msg
.wParam
= msg
.wParam
;
12430 s_msg
.lParam
= msg
.lParam
;
12431 s_msg
.descr
= "msg_loop";
12432 add_message(&s_msg
);
12434 DispatchMessageA(&msg
);
12437 end_ticks
= GetTickCount();
12439 /* inject WM_MOUSEMOVE to see how it changes tracking */
12440 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
12442 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12443 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12445 inject_mouse_move
= FALSE
;
12447 } while (start_ticks
+ timeout
>= end_ticks
);
12450 static void test_TrackMouseEvent(void)
12452 TRACKMOUSEEVENT tme
;
12455 RECT rc_parent
, rc_child
;
12456 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
12458 #define track_hover(track_hwnd, track_hover_time) \
12459 tme.cbSize = sizeof(tme); \
12460 tme.dwFlags = TME_HOVER; \
12461 tme.hwndTrack = track_hwnd; \
12462 tme.dwHoverTime = track_hover_time; \
12463 SetLastError(0xdeadbeef); \
12464 ret = pTrackMouseEvent(&tme); \
12465 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError())
12467 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
12468 tme.cbSize = sizeof(tme); \
12469 tme.dwFlags = TME_QUERY; \
12470 tme.hwndTrack = (HWND)0xdeadbeef; \
12471 tme.dwHoverTime = 0xdeadbeef; \
12472 SetLastError(0xdeadbeef); \
12473 ret = pTrackMouseEvent(&tme); \
12474 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\
12475 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \
12476 ok(tme.dwFlags == (expected_track_flags), \
12477 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
12478 ok(tme.hwndTrack == (expected_track_hwnd), \
12479 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
12480 ok(tme.dwHoverTime == (expected_hover_time), \
12481 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time))
12483 #define track_hover_cancel(track_hwnd) \
12484 tme.cbSize = sizeof(tme); \
12485 tme.dwFlags = TME_HOVER | TME_CANCEL; \
12486 tme.hwndTrack = track_hwnd; \
12487 tme.dwHoverTime = 0xdeadbeef; \
12488 SetLastError(0xdeadbeef); \
12489 ret = pTrackMouseEvent(&tme); \
12490 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError())
12492 default_hover_time
= 0xdeadbeef;
12493 SetLastError(0xdeadbeef);
12494 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
12495 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
12496 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError());
12497 if (!ret
) default_hover_time
= 400;
12498 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
12500 SetLastError(0xdeadbeef);
12501 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
12502 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
12503 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError());
12504 if (!ret
) hover_width
= 4;
12505 SetLastError(0xdeadbeef);
12506 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
12507 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
12508 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError());
12509 if (!ret
) hover_height
= 4;
12510 trace("hover rect is %u x %d\n", hover_width
, hover_height
);
12512 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
12513 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12514 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
12518 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
12519 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
12520 50, 50, 200, 200, hwnd
,
12524 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
12529 tme
.dwFlags
= TME_QUERY
;
12530 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12531 tme
.dwHoverTime
= 0xdeadbeef;
12532 SetLastError(0xdeadbeef);
12533 ret
= pTrackMouseEvent(&tme
);
12534 ok(!ret
, "TrackMouseEvent should fail\n");
12535 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
12536 "not expected error %u\n", GetLastError());
12538 tme
.cbSize
= sizeof(tme
);
12539 tme
.dwFlags
= TME_HOVER
;
12540 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12541 tme
.dwHoverTime
= 0xdeadbeef;
12542 SetLastError(0xdeadbeef);
12543 ret
= pTrackMouseEvent(&tme
);
12544 ok(!ret
, "TrackMouseEvent should fail\n");
12545 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
12546 "not expected error %u\n", GetLastError());
12548 tme
.cbSize
= sizeof(tme
);
12549 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
12550 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12551 tme
.dwHoverTime
= 0xdeadbeef;
12552 SetLastError(0xdeadbeef);
12553 ret
= pTrackMouseEvent(&tme
);
12554 ok(!ret
, "TrackMouseEvent should fail\n");
12555 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
12556 "not expected error %u\n", GetLastError());
12558 GetWindowRect(hwnd
, &rc_parent
);
12559 GetWindowRect(hchild
, &rc_child
);
12560 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
12562 /* Process messages so that the system updates its internal current
12563 * window and hittest, otherwise TrackMouseEvent calls don't have any
12569 track_query(0, NULL
, 0);
12570 track_hover(hchild
, 0);
12571 track_query(0, NULL
, 0);
12576 track_hover(hwnd
, 0);
12577 tme
.cbSize
= sizeof(tme
);
12578 tme
.dwFlags
= TME_QUERY
;
12579 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12580 tme
.dwHoverTime
= 0xdeadbeef;
12581 SetLastError(0xdeadbeef);
12582 ret
= pTrackMouseEvent(&tme
);
12583 ok(ret
, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());
12584 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %u\n", tme
.cbSize
);
12587 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
12588 DestroyWindow( hwnd
);
12591 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme
.dwFlags
);
12592 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
12593 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %u, expected %u\n",
12594 tme
.dwHoverTime
, default_hover_time
);
12596 pump_msg_loop_timeout(default_hover_time
, FALSE
);
12597 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12599 track_query(0, NULL
, 0);
12601 track_hover(hwnd
, HOVER_DEFAULT
);
12602 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12604 Sleep(default_hover_time
/ 2);
12605 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12606 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12608 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12610 pump_msg_loop_timeout(default_hover_time
, FALSE
);
12611 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12613 track_query(0, NULL
, 0);
12615 track_hover(hwnd
, HOVER_DEFAULT
);
12616 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12618 pump_msg_loop_timeout(default_hover_time
, TRUE
);
12619 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12621 track_query(0, NULL
, 0);
12623 track_hover(hwnd
, HOVER_DEFAULT
);
12624 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12625 track_hover_cancel(hwnd
);
12627 DestroyWindow(hwnd
);
12631 #undef track_hover_cancel
12635 static const struct message WmSetWindowRgn
[] = {
12636 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12637 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12638 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
12639 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12640 { WM_ERASEBKGND
, sent
|optional
},
12641 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12642 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12646 static const struct message WmSetWindowRgn_no_redraw
[] = {
12647 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
12648 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12649 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
12650 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12654 static const struct message WmSetWindowRgn_clear
[] = {
12655 { WM_WINDOWPOSCHANGING
, sent
/*|wparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ },
12656 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12657 { WM_NCPAINT
, sent
|optional
},
12658 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12659 { WM_ERASEBKGND
, sent
|optional
}, /* FIXME: remove optional once Wine is fixed */
12660 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12661 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
12662 { WM_NCPAINT
, sent
|optional
},
12663 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12664 { WM_ERASEBKGND
, sent
|optional
},
12665 { WM_WINDOWPOSCHANGING
, sent
|optional
},
12666 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
12667 { WM_NCPAINT
, sent
|optional
},
12668 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12669 { WM_ERASEBKGND
, sent
|optional
},
12670 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12671 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
12672 { WM_NCPAINT
, sent
|optional
},
12673 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12674 { WM_ERASEBKGND
, sent
|optional
},
12675 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12676 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12680 static void test_SetWindowRgn(void)
12683 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
12684 100, 100, 200, 200, 0, 0, 0, NULL
);
12685 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
12687 ShowWindow( hwnd
, SW_SHOW
);
12688 UpdateWindow( hwnd
);
12692 trace("testing SetWindowRgn\n");
12693 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
12694 SetWindowRgn( hwnd
, hrgn
, TRUE
);
12695 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
12697 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
12698 SetWindowRgn( hwnd
, hrgn
, FALSE
);
12699 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
12701 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
12702 SetWindowRgn( hwnd
, hrgn
, TRUE
);
12703 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
12705 SetWindowRgn( hwnd
, 0, TRUE
);
12706 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
12708 DestroyWindow( hwnd
);
12711 /*************************** ShowWindow() test ******************************/
12712 static const struct message WmShowNormal
[] = {
12713 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12714 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12715 { HCBT_ACTIVATE
, hook
},
12716 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12717 { HCBT_SETFOCUS
, hook
},
12718 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12721 static const struct message WmShow
[] = {
12722 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12723 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12724 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12725 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12726 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12727 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12730 static const struct message WmShowNoActivate_1
[] = {
12731 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
12732 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12733 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12734 { WM_MOVE
, sent
|defwinproc
|optional
},
12735 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12738 static const struct message WmShowNoActivate_2
[] = {
12739 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
12740 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12741 { HCBT_ACTIVATE
, hook
|optional
},
12742 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12743 { HCBT_SETFOCUS
, hook
|optional
},
12744 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12745 { WM_MOVE
, sent
|defwinproc
},
12746 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12747 { HCBT_SETFOCUS
, hook
|optional
},
12748 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
12749 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12750 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12751 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
12754 static const struct message WmShowNA_1
[] = {
12755 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12756 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
12757 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12760 static const struct message WmShowNA_2
[] = {
12761 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12762 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
12763 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12766 static const struct message WmRestore_1
[] = {
12767 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
12768 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12769 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12770 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12771 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12772 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12773 { WM_MOVE
, sent
|defwinproc
},
12774 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12775 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
12778 static const struct message WmRestore_2
[] = {
12779 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12780 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12781 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12782 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12783 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12784 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12787 static const struct message WmRestore_3
[] = {
12788 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
12789 { WM_GETMINMAXINFO
, sent
},
12790 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12791 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
12792 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12793 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
12794 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12795 { WM_MOVE
, sent
|defwinproc
},
12796 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12797 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
12800 static const struct message WmRestore_4
[] = {
12801 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
12802 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12803 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12804 { WM_MOVE
, sent
|defwinproc
|optional
},
12805 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
12808 static const struct message WmRestore_5
[] = {
12809 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
12810 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12811 { HCBT_ACTIVATE
, hook
|optional
},
12812 { HCBT_SETFOCUS
, hook
|optional
},
12813 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12814 { WM_MOVE
, sent
|defwinproc
|optional
},
12815 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
12818 static const struct message WmHide_1
[] = {
12819 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12820 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
12821 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
12822 { HCBT_ACTIVATE
, hook
|optional
},
12823 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
12826 static const struct message WmHide_2
[] = {
12827 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12828 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
12829 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
12830 { HCBT_ACTIVATE
, hook
|optional
},
12833 static const struct message WmHide_3
[] = {
12834 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12835 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12836 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12837 { HCBT_SETFOCUS
, hook
|optional
},
12838 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12841 static const struct message WmShowMinimized_1
[] = {
12842 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
12843 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12844 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12845 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12846 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12847 { WM_MOVE
, sent
|defwinproc
},
12848 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12851 static const struct message WmMinimize_1
[] = {
12852 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12853 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12854 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12855 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12856 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12857 { WM_MOVE
, sent
|defwinproc
},
12858 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12861 static const struct message WmMinimize_2
[] = {
12862 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12863 { HCBT_SETFOCUS
, hook
|optional
},
12864 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12865 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12866 { WM_MOVE
, sent
|defwinproc
},
12867 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12870 static const struct message WmMinimize_3
[] = {
12871 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12872 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12873 { HCBT_ACTIVATE
, hook
|optional
},
12874 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12875 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12876 { WM_MOVE
, sent
|defwinproc
},
12877 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12880 static const struct message WmShowMinNoActivate
[] = {
12881 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
12882 { WM_WINDOWPOSCHANGING
, sent
},
12883 { WM_WINDOWPOSCHANGED
, sent
},
12884 { WM_MOVE
, sent
|defwinproc
|optional
},
12885 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
12888 static const struct message WmMinMax_1
[] = {
12889 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
12892 static const struct message WmMinMax_2
[] = {
12893 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12894 { WM_GETMINMAXINFO
, sent
|optional
},
12895 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
12896 { HCBT_ACTIVATE
, hook
|optional
},
12897 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12898 { HCBT_SETFOCUS
, hook
|optional
},
12899 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12900 { WM_MOVE
, sent
|defwinproc
|optional
},
12901 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
12902 { HCBT_SETFOCUS
, hook
|optional
},
12905 static const struct message WmMinMax_3
[] = {
12906 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12907 { HCBT_SETFOCUS
, hook
|optional
},
12908 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12909 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12910 { WM_MOVE
, sent
|defwinproc
|optional
},
12911 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
12914 static const struct message WmMinMax_4
[] = {
12915 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
12918 static const struct message WmShowMaximized_1
[] = {
12919 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12920 { WM_GETMINMAXINFO
, sent
},
12921 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12922 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12923 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12924 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12925 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12926 { WM_MOVE
, sent
|defwinproc
},
12927 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12928 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
12931 static const struct message WmShowMaximized_2
[] = {
12932 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12933 { WM_GETMINMAXINFO
, sent
},
12934 { WM_WINDOWPOSCHANGING
, sent
|optional
},
12935 { HCBT_ACTIVATE
, hook
|optional
},
12936 { WM_WINDOWPOSCHANGED
, sent
|optional
},
12937 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
12938 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
12939 { WM_WINDOWPOSCHANGING
, sent
|optional
},
12940 { HCBT_SETFOCUS
, hook
|optional
},
12941 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12942 { WM_MOVE
, sent
|defwinproc
},
12943 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12944 { HCBT_SETFOCUS
, hook
|optional
},
12947 static const struct message WmShowMaximized_3
[] = {
12948 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12949 { WM_GETMINMAXINFO
, sent
|optional
},
12950 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12951 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12952 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12953 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12954 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12955 { WM_MOVE
, sent
|defwinproc
|optional
},
12956 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12960 static void test_ShowWindow(void)
12962 /* ShowWindow commands in random order */
12963 static const struct
12965 INT cmd
; /* ShowWindow command */
12966 LPARAM ret
; /* ShowWindow return value */
12967 DWORD style
; /* window style after the command */
12968 const struct message
*msg
; /* message sequence the command produces */
12969 INT wp_cmd
, wp_flags
; /* window placement after the command */
12970 POINT wp_min
, wp_max
; /* window placement after the command */
12971 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
12974 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
12975 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12976 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12977 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12978 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
12979 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12980 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
12981 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12982 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
12983 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12984 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
12985 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12986 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
12987 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12988 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
12989 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12990 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
12991 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12992 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
12993 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12994 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
12995 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12996 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
12997 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12998 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
12999 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13000 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13001 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13002 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
13003 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13004 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13005 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13006 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
13007 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13008 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13009 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13010 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
13011 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13012 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
13013 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13014 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13015 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13016 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
13017 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
13018 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
13019 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13020 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13021 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13022 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
13023 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13024 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
13025 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13026 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
13027 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13028 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13029 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13030 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
13031 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13032 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
13033 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13034 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13035 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13036 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
13037 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13038 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13039 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13040 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
13041 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13042 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
13043 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13044 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13045 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13046 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
13047 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13048 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13049 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13050 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13051 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13052 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
13053 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13054 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
13055 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13056 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
13057 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13058 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
13059 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13060 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
13061 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13062 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
13063 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13064 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
13065 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13066 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
13067 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13068 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
13069 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13070 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
13071 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13072 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
13073 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13074 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
13075 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13076 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
13077 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13078 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
13079 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
13080 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
13081 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13082 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
13083 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13084 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
13085 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
13086 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
13087 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
13093 WINDOWPLACEMENT wp
;
13094 RECT win_rc
, work_rc
= {0, 0, 0, 0};
13096 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
13097 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
13102 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
13103 ok(style
== 0, "expected style 0, got %08x\n", style
);
13108 if (pGetMonitorInfoA
&& pMonitorFromPoint
)
13114 SetLastError(0xdeadbeef);
13115 hmon
= pMonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
13116 ok(hmon
!= 0, "MonitorFromPoint error %u\n", GetLastError());
13118 mi
.cbSize
= sizeof(mi
);
13119 SetLastError(0xdeadbeef);
13120 ret
= pGetMonitorInfoA(hmon
, &mi
);
13121 ok(ret
, "GetMonitorInfo error %u\n", GetLastError());
13122 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi
.rcMonitor
),
13123 wine_dbgstr_rect(&mi
.rcWork
));
13124 work_rc
= mi
.rcWork
;
13127 GetWindowRect(hwnd
, &win_rc
);
13128 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
13130 wp
.length
= sizeof(wp
);
13131 SetLastError(0xdeadbeaf);
13132 ret
= GetWindowPlacement(hwnd
, &wp
);
13133 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
13134 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
13135 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
13136 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
13137 "expected -1,-1 got %d,%d\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
13138 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
13139 "expected -1,-1 got %d,%d\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
13140 todo_wine_if (work_rc
.left
|| work_rc
.top
) /* FIXME: remove once Wine is fixed */
13141 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n", wine_dbgstr_rect(&win_rc
),
13142 wine_dbgstr_rect(&wp
.rcNormalPosition
));
13144 for (i
= 0; i
< sizeof(sw
)/sizeof(sw
[0]); i
++)
13146 static const char * const sw_cmd_name
[13] =
13148 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
13149 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
13150 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
13151 "SW_NORMALNA" /* 0xCC */
13154 INT idx
; /* index into the above array of names */
13156 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
13158 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
13159 trace("%d: sending %s, current window style %08x\n", i
+1, sw_cmd_name
[idx
], style
);
13160 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
13161 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %lu, got %lu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
13162 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
13163 ok(style
== sw
[i
].style
, "%d: expected style %08x, got %08x\n", i
+1, sw
[i
].style
, style
);
13165 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
13166 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
13168 wp
.length
= sizeof(wp
);
13169 SetLastError(0xdeadbeaf);
13170 ret
= GetWindowPlacement(hwnd
, &wp
);
13171 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
13172 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
13173 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
13175 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
13176 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
13177 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
13179 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
13180 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
13181 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
13185 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
13186 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
13189 todo_wine_if(wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
13190 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
13191 "expected %d,%d got %d,%d\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
13193 if (0) /* FIXME: Wine behaves completely different here */
13194 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n",
13195 wine_dbgstr_rect(&win_rc
), wine_dbgstr_rect(&wp
.rcNormalPosition
));
13197 DestroyWindow(hwnd
);
13201 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13203 struct recvd_message msg
;
13205 if (ignore_message( message
)) return 0;
13208 msg
.message
= message
;
13209 msg
.flags
= sent
|wparam
|lparam
;
13210 msg
.wParam
= wParam
;
13211 msg
.lParam
= lParam
;
13212 msg
.descr
= "dialog";
13215 /* calling DefDlgProc leads to a recursion under XP */
13219 case WM_INITDIALOG
:
13222 case WM_GETDLGCODE
:
13228 static WNDPROC orig_edit_proc
;
13229 static LRESULT WINAPI
dlg_creation_edit_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
13231 struct recvd_message msg
;
13233 if (ignore_message( message
)) return 0;
13236 msg
.message
= message
;
13237 msg
.flags
= sent
|wparam
|lparam
;
13240 msg
.descr
= "edit";
13243 return CallWindowProcW(orig_edit_proc
, hwnd
, message
, wp
, lp
);
13246 static INT_PTR WINAPI
test_dlg_proc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13248 struct recvd_message msg
;
13250 if (ignore_message( message
)) return 0;
13253 msg
.message
= message
;
13254 msg
.flags
= sent
|wparam
|lparam
|parent
;
13255 msg
.wParam
= wParam
;
13256 msg
.lParam
= lParam
;
13257 msg
.descr
= "dialog";
13260 if (message
== WM_INITDIALOG
)
13262 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
13263 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
13269 static INT_PTR WINAPI
test_dlg_proc3(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13271 ok( 0, "should not be called since DefDlgProc is not used\n" );
13275 static LRESULT WINAPI
test_dlg_proc4(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13277 struct recvd_message msg
;
13279 if (!ignore_message( message
))
13282 msg
.message
= message
;
13283 msg
.flags
= sent
|wparam
|lparam
|parent
;
13284 msg
.wParam
= wParam
;
13285 msg
.lParam
= lParam
;
13286 msg
.descr
= "dialog";
13289 if (message
== WM_INITDIALOG
)
13291 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
13292 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
13295 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
13298 static const struct message WmDefDlgSetFocus_1
[] = {
13299 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13300 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
13301 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
13302 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
13303 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
13304 { HCBT_SETFOCUS
, hook
},
13305 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
13306 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13307 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13308 { WM_SETFOCUS
, sent
|wparam
, 0 },
13309 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
13310 { WM_CTLCOLOREDIT
, sent
},
13311 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13312 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13313 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13314 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13315 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
13318 static const struct message WmDefDlgSetFocus_2
[] = {
13319 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13320 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
13321 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
13322 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
13323 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
13324 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13325 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
13326 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
13329 /* Creation of a dialog */
13330 static const struct message WmCreateDialogParamSeq_0
[] = {
13331 { HCBT_CREATEWND
, hook
},
13332 { WM_NCCREATE
, sent
},
13333 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
13334 { WM_CREATE
, sent
},
13335 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13336 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
13338 { WM_SETFONT
, sent
},
13339 { WM_INITDIALOG
, sent
},
13340 { WM_CHANGEUISTATE
, sent
|optional
},
13343 /* Creation of a dialog */
13344 static const struct message WmCreateDialogParamSeq_1
[] = {
13345 { HCBT_CREATEWND
, hook
},
13346 { WM_NCCREATE
, sent
},
13347 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
13348 { WM_CREATE
, sent
},
13349 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13350 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
13352 { WM_SETFONT
, sent
},
13353 { WM_INITDIALOG
, sent
},
13354 { WM_GETDLGCODE
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* FIXME: Wine doesn't send it */
13355 { HCBT_SETFOCUS
, hook
},
13356 { HCBT_ACTIVATE
, hook
},
13357 { WM_QUERYNEWPALETTE
, sent
|optional
},
13358 { WM_PALETTEISCHANGING
, sent
|optional
},
13359 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13360 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13361 { WM_NCACTIVATE
, sent
},
13362 { WM_ACTIVATE
, sent
|wparam
, 1 },
13363 { WM_SETFOCUS
, sent
},
13364 { WM_CHANGEUISTATE
, sent
|optional
},
13367 /* Creation of a dialog */
13368 static const struct message WmCreateDialogParamSeq_2
[] = {
13369 { HCBT_CREATEWND
, hook
},
13370 { WM_NCCREATE
, sent
},
13371 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
13372 { WM_CREATE
, sent
},
13373 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13374 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
13376 { WM_CHANGEUISTATE
, sent
|optional
},
13380 static const struct message WmCreateDialogParamSeq_3
[] = {
13381 { HCBT_CREATEWND
, hook
},
13382 { WM_SETFONT
, sent
|parent
},
13383 { WM_INITDIALOG
, sent
|parent
},
13384 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13385 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
13386 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13387 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13388 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13389 { HCBT_ACTIVATE
, hook
},
13390 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
13391 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13392 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13393 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
13394 { WM_NCACTIVATE
, sent
|parent
},
13395 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
13396 { WM_SETFOCUS
, sent
},
13397 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
13398 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13399 { WM_USER
, sent
|parent
},
13400 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
13404 static const struct message WmCreateDialogParamSeq_4
[] = {
13405 { HCBT_CREATEWND
, hook
},
13406 { WM_NCCREATE
, sent
|parent
},
13407 { WM_NCCALCSIZE
, sent
|parent
|wparam
, 0 },
13408 { WM_CREATE
, sent
|parent
},
13409 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13410 { WM_SIZE
, sent
|parent
|wparam
, SIZE_RESTORED
},
13411 { WM_MOVE
, sent
|parent
},
13412 { WM_SETFONT
, sent
|parent
},
13413 { WM_INITDIALOG
, sent
|parent
},
13414 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13415 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
13416 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13417 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13418 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
13419 { HCBT_ACTIVATE
, hook
},
13420 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
13421 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13422 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13423 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
13424 { WM_NCACTIVATE
, sent
|parent
},
13425 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
13426 { HCBT_SETFOCUS
, hook
},
13427 { WM_SETFOCUS
, sent
|parent
},
13428 { WM_KILLFOCUS
, sent
|parent
},
13429 { WM_SETFOCUS
, sent
},
13430 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
13431 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
13432 { WM_USER
, sent
|parent
},
13433 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
13434 { WM_UPDATEUISTATE
, sent
|parent
|optional
},
13435 { WM_UPDATEUISTATE
, sent
|optional
},
13439 static void test_dialog_messages(void)
13442 HWND hdlg
, hedit1
, hedit2
, hfocus
, parent
, child
, child2
;
13445 #define set_selection(hctl, start, end) \
13446 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
13447 ok(ret == 1, "EM_SETSEL returned %ld\n", ret);
13449 #define check_selection(hctl, start, end) \
13450 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
13451 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
13455 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
13456 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
13457 0, 0, 100, 100, 0, 0, 0, NULL
);
13458 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
13460 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
13461 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
13462 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
13463 ok(hedit1
!= 0, "Failed to create edit control\n");
13464 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
13465 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
13466 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
13467 ok(hedit2
!= 0, "Failed to create edit control\n");
13469 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
13470 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
13472 hfocus
= GetFocus();
13473 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
13476 hfocus
= GetFocus();
13477 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
13479 check_selection(hedit1
, 0, 0);
13480 check_selection(hedit2
, 0, 0);
13482 set_selection(hedit2
, 0, -1);
13483 check_selection(hedit2
, 0, 3);
13486 hfocus
= GetFocus();
13487 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
13490 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
13491 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
13492 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
13494 hfocus
= GetFocus();
13495 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
13497 check_selection(hedit1
, 0, 5);
13498 check_selection(hedit2
, 0, 3);
13501 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
13502 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
13503 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
13505 hfocus
= GetFocus();
13506 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
13508 check_selection(hedit1
, 0, 5);
13509 check_selection(hedit2
, 0, 3);
13511 EndDialog(hdlg
, 0);
13512 DestroyWindow(hedit1
);
13513 DestroyWindow(hedit2
);
13514 DestroyWindow(hdlg
);
13517 #undef set_selection
13518 #undef check_selection
13520 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
13521 cls
.lpszClassName
= "MyDialogClass";
13522 cls
.hInstance
= GetModuleHandleA(NULL
);
13523 /* need a cast since a dlgproc is used as a wndproc */
13524 cls
.lpfnWndProc
= test_dlg_proc
;
13525 if (!RegisterClassA(&cls
)) assert(0);
13529 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
13530 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13531 ok_sequence(WmCreateDialogParamSeq_0
, "CreateDialogParam_0", FALSE
);
13532 hfocus
= GetFocus();
13533 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
13534 EndDialog(hdlg
, 0);
13535 DestroyWindow(hdlg
);
13540 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 1);
13541 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13542 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
13543 hfocus
= GetFocus();
13544 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
13545 EndDialog(hdlg
, 0);
13546 DestroyWindow(hdlg
);
13549 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
13550 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13551 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
13552 EndDialog(hdlg
, 0);
13553 DestroyWindow(hdlg
);
13556 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2
, 0);
13557 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13558 ok_sequence(WmCreateDialogParamSeq_3
, "CreateDialogParam_3", TRUE
);
13559 EndDialog(hdlg
, 0);
13560 DestroyWindow(hdlg
);
13563 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
13564 cls
.lpfnWndProc
= test_dlg_proc4
;
13565 ok( RegisterClassA(&cls
), "failed to register class again\n" );
13566 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3
, 0);
13567 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13568 ok_sequence(WmCreateDialogParamSeq_4
, "CreateDialogParam_4", TRUE
);
13569 EndDialog(hdlg
, 0);
13570 DestroyWindow(hdlg
);
13573 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
13575 parent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13576 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13577 100, 100, 200, 200, 0, 0, 0, NULL
);
13578 ok (parent
!= 0, "Failed to create parent window\n");
13580 /* This child has no parent set. We will later call SetParent on it,
13581 * so that it will have a parent set, but no WS_CHILD style. */
13582 child
= CreateWindowExA(0, "TestWindowClass", "Test child",
13583 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13584 100, 100, 200, 200, 0, 0, 0, NULL
);
13585 ok (child
!= 0, "Failed to create child window\n");
13587 /* This is a regular child window. When used as an owner, the other
13588 * child window will be used. */
13589 child2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2",
13590 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CHILD
,
13591 100, 100, 200, 200, child
, 0, 0, NULL
);
13592 ok (child2
!= 0, "Failed to create child window\n");
13594 SetParent(child
, parent
);
13598 DialogBoxA( 0, "TEST_DIALOG", child2
, TestModalDlgProc2
);
13599 ok_sequence(WmModalDialogSeq_2
, "ModalDialog2", TRUE
);
13601 DestroyWindow(child2
);
13602 DestroyWindow(child
);
13603 DestroyWindow(parent
);
13607 static void test_enddialog_seq(HWND dialog
, HWND owner
)
13609 const struct message seq
[] = {
13610 { WM_ENABLE
, sent
},
13611 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13612 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
13613 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13614 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13615 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */
13616 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13617 { WM_QUERYNEWPALETTE
, sent
|optional
},
13618 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
13619 { WM_GETTEXT
, sent
|optional
|defwinproc
},
13620 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
13621 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
13622 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
13623 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, (WPARAM
)dialog
},
13628 EndDialog(dialog
, 0);
13629 ok_sequence(seq
, "EndDialog", FALSE
);
13632 static void test_enddialog_seq2(HWND dialog
, HWND owner
)
13634 const struct message seq
[] = {
13635 { WM_ENABLE
, parent
|sent
},
13636 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13637 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
13638 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13639 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13640 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13641 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13642 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
13643 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
13644 { WM_SETFOCUS
, sent
|parent
|defwinproc
|wparam
, (WPARAM
)dialog
},
13649 EndDialog(dialog
, 0);
13650 ok_sequence(seq
, "EndDialog2", FALSE
);
13653 static void test_EndDialog(void)
13655 HWND hparent
, hother
, hactive
, hdlg
, hchild
;
13658 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13659 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
13660 100, 100, 200, 200, 0, 0, 0, NULL
);
13661 ok (hparent
!= 0, "Failed to create parent window\n");
13663 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
13664 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13665 200, 100, 200, 200, 0, 0, 0, NULL
);
13666 ok (hother
!= 0, "Failed to create parent window\n");
13668 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
13669 cls
.lpszClassName
= "MyDialogClass";
13670 cls
.hInstance
= GetModuleHandleA(NULL
);
13671 cls
.lpfnWndProc
= test_dlg_proc
;
13672 if (!RegisterClassA(&cls
)) assert(0);
13675 SetForegroundWindow(hother
);
13676 hactive
= GetForegroundWindow();
13677 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
13679 /* create a dialog where the parent is disabled, this parent should be
13680 * enabled and receive focus when dialog exits */
13681 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
13682 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13683 SetForegroundWindow(hdlg
);
13684 hactive
= GetForegroundWindow();
13685 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
13686 EndDialog(hdlg
, 0);
13687 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
13688 hactive
= GetForegroundWindow();
13689 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
13690 DestroyWindow(hdlg
);
13693 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */
13694 EnableWindow(hparent
, FALSE
);
13695 hdlg
= CreateWindowExA(0, "TestDialogClass", NULL
,
13696 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
13697 0, 0, 100, 100, hparent
, 0, 0, NULL
);
13698 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13700 SetForegroundWindow(hother
);
13702 hactive
= GetForegroundWindow();
13703 ok(hactive
== hother
, "Wrong foreground (%p != %p)\n", hactive
, hother
);
13704 hactive
= GetActiveWindow();
13705 ok(hactive
== hother
, "Wrong active window (%p != %p)\n", hactive
, hother
);
13706 EndDialog(hdlg
, 0);
13707 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
13708 hactive
= GetForegroundWindow();
13709 ok(hother
== hactive
, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
13710 DestroyWindow(hdlg
);
13713 DestroyWindow( hparent
);
13715 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13716 WS_POPUP
| WS_VISIBLE
| WS_DISABLED
,
13717 100, 100, 200, 200, 0, 0, 0, NULL
);
13718 ok (hparent
!= 0, "Failed to create parent window\n");
13720 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
13721 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
13722 0, 0, 0, 0, 0, 0, 0, NULL
);
13723 ok (hchild
!= 0, "Failed to create child window\n");
13725 SetParent(hchild
, hparent
);
13728 SetForegroundWindow(hother
);
13729 hactive
= GetForegroundWindow();
13730 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
13732 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
13733 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13735 SetForegroundWindow(hdlg
);
13736 test_enddialog_seq(hdlg
, hchild
);
13738 hactive
= GetForegroundWindow();
13739 ok(hactive
== hchild
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
13741 DestroyWindow(hdlg
);
13743 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */
13744 SetWindowLongW(hchild
, GWL_STYLE
, GetWindowLongW(hchild
, GWL_STYLE
) | WS_CHILD
);
13746 SetForegroundWindow(hother
);
13747 hactive
= GetForegroundWindow();
13748 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
13750 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
13751 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13753 SetForegroundWindow(hdlg
);
13754 test_enddialog_seq2(hdlg
, hparent
);
13756 hactive
= GetForegroundWindow();
13757 ok(hactive
== hparent
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
13758 DestroyWindow(hdlg
);
13759 DestroyWindow(hchild
);
13760 DestroyWindow(hparent
);
13761 DestroyWindow(hother
);
13764 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
13767 static void test_nullCallback(void)
13771 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
13772 100, 100, 200, 200, 0, 0, 0, NULL
);
13773 ok (hwnd
!= 0, "Failed to create overlapped window\n");
13775 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
13777 DestroyWindow(hwnd
);
13780 /* SetActiveWindow( 0 ) hwnd visible */
13781 static const struct message SetActiveWindowSeq0
[] =
13783 { HCBT_ACTIVATE
, hook
|optional
},
13784 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13785 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13786 { WM_ACTIVATE
, sent
|wparam
, 0 },
13787 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13788 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13789 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13790 { WM_KILLFOCUS
, sent
|optional
},
13791 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13792 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13793 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
13794 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13795 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
13796 { HCBT_SETFOCUS
, hook
|optional
},
13797 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
13798 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
13799 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
13800 { WM_IME_SETCONTEXT
, sent
|optional
},
13801 { WM_IME_SETCONTEXT
, sent
|optional
},
13802 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13803 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13804 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
13805 { WM_GETTEXT
, sent
|optional
},
13808 /* SetActiveWindow( hwnd ) hwnd visible */
13809 static const struct message SetActiveWindowSeq1
[] =
13811 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13814 /* SetActiveWindow( popup ) hwnd visible, popup visible */
13815 static const struct message SetActiveWindowSeq2
[] =
13817 { HCBT_ACTIVATE
, hook
},
13818 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13819 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13820 { WM_ACTIVATE
, sent
|wparam
, 0 },
13821 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13822 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13823 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13824 { WM_NCPAINT
, sent
|optional
},
13825 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13826 { WM_ERASEBKGND
, sent
|optional
},
13827 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13828 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13829 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13830 { WM_ACTIVATE
, sent
|wparam
, 1 },
13831 { HCBT_SETFOCUS
, hook
},
13832 { WM_KILLFOCUS
, sent
|defwinproc
},
13833 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
13834 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13835 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13836 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13837 { WM_SETFOCUS
, sent
|defwinproc
},
13838 { WM_GETTEXT
, sent
|optional
},
13842 /* SetActiveWindow( hwnd ) hwnd not visible */
13843 static const struct message SetActiveWindowSeq3
[] =
13845 { HCBT_ACTIVATE
, hook
},
13846 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13847 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13848 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
13849 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13850 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13851 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13852 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13853 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13854 { WM_ACTIVATE
, sent
|wparam
, 1 },
13855 { HCBT_SETFOCUS
, hook
},
13856 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13857 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13858 { WM_SETFOCUS
, sent
|defwinproc
},
13861 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
13862 static const struct message SetActiveWindowSeq4
[] =
13864 { HCBT_ACTIVATE
, hook
},
13865 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13866 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13867 { WM_ACTIVATE
, sent
|wparam
, 0 },
13868 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13869 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
13870 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13871 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13872 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13873 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13874 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13875 { WM_ACTIVATE
, sent
|wparam
, 1 },
13876 { HCBT_SETFOCUS
, hook
},
13877 { WM_KILLFOCUS
, sent
|defwinproc
},
13878 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
13879 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13880 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13881 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13882 { WM_SETFOCUS
, sent
|defwinproc
},
13887 static void test_SetActiveWindow(void)
13889 HWND hwnd
, popup
, ret
;
13891 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
13892 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13893 100, 100, 200, 200, 0, 0, 0, NULL
);
13895 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
13896 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
13897 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
13899 ok(hwnd
!= 0, "Failed to create overlapped window\n");
13900 ok(popup
!= 0, "Failed to create popup window\n");
13901 SetForegroundWindow( popup
);
13904 trace("SetActiveWindow(0)\n");
13905 ret
= SetActiveWindow(0);
13906 ok( ret
== popup
, "Failed to SetActiveWindow(0)\n");
13907 ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
13910 trace("SetActiveWindow(hwnd), hwnd visible\n");
13911 ret
= SetActiveWindow(hwnd
);
13912 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
13915 trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
13916 ret
= SetActiveWindow(popup
);
13917 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
13918 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
13921 ShowWindow(hwnd
, SW_HIDE
);
13922 ShowWindow(popup
, SW_HIDE
);
13925 trace("SetActiveWindow(hwnd), hwnd not visible\n");
13926 ret
= SetActiveWindow(hwnd
);
13927 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
13928 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
13931 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
13932 ret
= SetActiveWindow(popup
);
13933 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
13934 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
13939 DestroyWindow(hwnd
);
13942 static const struct message SetForegroundWindowSeq
[] =
13944 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13945 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13946 { WM_ACTIVATE
, sent
|wparam
, 0 },
13947 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
13948 { WM_KILLFOCUS
, sent
},
13949 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
13950 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
13954 static void test_SetForegroundWindow(void)
13958 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
13959 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13960 100, 100, 200, 200, 0, 0, 0, NULL
);
13961 ok (hwnd
!= 0, "Failed to create overlapped window\n");
13962 SetForegroundWindow( hwnd
);
13965 trace("SetForegroundWindow( 0 )\n");
13966 SetForegroundWindow( 0 );
13967 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
13968 trace("SetForegroundWindow( GetDesktopWindow() )\n");
13969 SetForegroundWindow( GetDesktopWindow() );
13970 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
13971 "foreground top level window", FALSE
);
13974 DestroyWindow(hwnd
);
13977 static DWORD
get_input_codepage( void )
13981 HKL hkl
= GetKeyboardLayout( 0 );
13983 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
,
13984 (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
13985 if (!ret
) cp
= CP_ACP
;
13989 static void test_dbcs_wm_char(void)
13992 WCHAR wch
, bad_wch
;
14000 struct message wmCharSeq
[2];
14002 DWORD cp
= get_input_codepage();
14004 if (!pGetCPInfoExA
)
14006 win_skip("GetCPInfoExA is not available\n");
14010 pGetCPInfoExA( cp
, 0, &cpinfo
);
14011 if (cpinfo
.MaxCharSize
!= 2)
14013 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
14017 dbch
[0] = dbch
[1] = 0;
14019 bad_wch
= cpinfo
.UnicodeDefaultChar
;
14020 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
14021 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
14022 for (k
= 128; k
<= 255; k
++)
14028 if (MultiByteToWideChar( cp
, 0, str
, 2, wstr
, 2 ) == 1 &&
14029 WideCharToMultiByte( cp
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
14030 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
14031 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
14042 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
14045 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
14046 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
14048 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
14049 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
14050 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
14051 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
14052 ok (hwnd
!= 0, "Failed to create overlapped window\n");
14053 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
14056 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
14057 wmCharSeq
[0].message
= WM_CHAR
;
14058 wmCharSeq
[0].flags
= sent
|wparam
;
14059 wmCharSeq
[0].wParam
= wch
;
14061 /* posted message */
14062 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14063 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14064 ok( !ret
, "got message %x\n", msg
.message
);
14065 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14066 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14067 ok( ret
, "no message\n" );
14068 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14069 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
14070 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14071 ok( !ret
, "got message %x\n", msg
.message
);
14073 /* posted thread message */
14074 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
14075 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14076 ok( !ret
, "got message %x\n", msg
.message
);
14077 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14078 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14079 ok( ret
, "no message\n" );
14080 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14081 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
14082 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14083 ok( !ret
, "got message %x\n", msg
.message
);
14087 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14088 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14089 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14090 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14091 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14092 ok( !ret
, "got message %x\n", msg
.message
);
14094 /* sent message with timeout */
14096 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
14097 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14098 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
14099 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14100 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14101 ok( !ret
, "got message %x\n", msg
.message
);
14103 /* sent message with timeout and callback */
14105 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
14106 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14107 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
14108 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14109 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14110 ok( !ret
, "got message %x\n", msg
.message
);
14112 /* sent message with callback */
14114 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14115 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14116 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
14117 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14118 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14119 ok( !ret
, "got message %x\n", msg
.message
);
14121 /* direct window proc call */
14123 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
14124 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14125 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
14126 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14128 /* dispatch message */
14130 msg
.message
= WM_CHAR
;
14131 msg
.wParam
= dbch
[0];
14133 DispatchMessageA( &msg
);
14134 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14135 msg
.wParam
= dbch
[1];
14136 DispatchMessageA( &msg
);
14137 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14139 /* window handle is irrelevant */
14141 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
14142 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14143 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14144 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14145 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14146 ok( !ret
, "got message %x\n", msg
.message
);
14148 /* interleaved post and send */
14150 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
14151 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
14152 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14153 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14154 ok( !ret
, "got message %x\n", msg
.message
);
14155 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14156 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14157 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14158 ok( ret
, "no message\n" );
14159 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14160 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
14161 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14162 ok( !ret
, "got message %x\n", msg
.message
);
14163 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14164 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14165 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14166 ok( !ret
, "got message %x\n", msg
.message
);
14168 /* interleaved sent message and winproc */
14170 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14171 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
14172 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14173 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14174 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14175 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
14176 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14178 /* interleaved winproc and dispatch */
14180 msg
.message
= WM_CHAR
;
14181 msg
.wParam
= dbch
[0];
14183 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
14184 DispatchMessageA( &msg
);
14185 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14186 msg
.wParam
= dbch
[1];
14187 DispatchMessageA( &msg
);
14188 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14189 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
14190 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14192 /* interleaved sends */
14194 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
14195 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
14196 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
14197 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
14198 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14199 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
14200 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14204 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
14205 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
14206 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14207 ok( !ret
, "got message %x\n", msg
.message
);
14209 /* other char messages are not magic */
14210 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
14211 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14212 ok( ret
, "no message\n" );
14213 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
14214 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
14215 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14216 ok( !ret
, "got message %x\n", msg
.message
);
14217 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
14218 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14219 ok( ret
, "no message\n" );
14220 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
14221 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
14222 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14223 ok( !ret
, "got message %x\n", msg
.message
);
14225 /* test retrieving messages */
14227 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
14228 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14229 ok( ret
, "no message\n" );
14230 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14231 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14232 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14233 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14234 ok( ret
, "no message\n" );
14235 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14236 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14237 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14238 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14239 ok( !ret
, "got message %x\n", msg
.message
);
14241 /* message filters */
14242 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
14243 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14244 ok( ret
, "no message\n" );
14245 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14246 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14247 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14248 /* message id is filtered, hwnd is not */
14249 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
14250 ok( !ret
, "no message\n" );
14251 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
14252 ok( ret
, "no message\n" );
14253 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14254 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14255 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14256 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14257 ok( !ret
, "got message %x\n", msg
.message
);
14259 /* mixing GetMessage and PostMessage */
14260 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
14261 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
14262 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14263 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14264 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14265 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
14268 ok( time
- GetTickCount() <= 100, "bad time %x\n", msg
.time
);
14269 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14270 ok( ret
, "no message\n" );
14271 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14272 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14273 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14274 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
14275 ok( msg
.time
== time
, "bad time %x/%x\n", msg
.time
, time
);
14276 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
);
14277 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14278 ok( !ret
, "got message %x\n", msg
.message
);
14280 /* without PM_REMOVE */
14281 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
14282 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14283 ok( ret
, "no message\n" );
14284 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14285 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14286 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14287 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14288 ok( ret
, "no message\n" );
14289 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14290 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14291 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14292 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14293 ok( ret
, "no message\n" );
14294 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14295 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14296 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14297 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14298 ok( ret
, "no message\n" );
14299 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14300 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14301 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
14302 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
14303 ok( !ret
, "got message %x\n", msg
.message
);
14305 DestroyWindow(hwnd
);
14306 DestroyWindow(hwnd2
);
14309 static void test_unicode_wm_char(void)
14313 struct message seq
[2];
14314 HKL hkl_orig
, hkl_greek
;
14316 LCID thread_locale
;
14318 hkl_orig
= GetKeyboardLayout( 0 );
14319 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
14322 skip( "Default codepage %d\n", cp
);
14326 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
14327 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
14329 skip( "Unable to load Greek keyboard layout\n" );
14333 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
14334 100, 100, 200, 200, 0, 0, 0, NULL
);
14337 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
14339 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
14341 if (!ignore_message( msg
.message
)) break;
14344 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14345 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14346 ok( msg
.wParam
== 0x3b1, "bad wparam %lx\n", msg
.wParam
);
14347 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
14349 DispatchMessageW( &msg
);
14351 memset( seq
, 0, sizeof(seq
) );
14352 seq
[0].message
= WM_CHAR
;
14353 seq
[0].flags
= sent
|wparam
;
14354 seq
[0].wParam
= 0x3b1;
14356 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
14360 /* greek alpha -> 'a' in cp1252 */
14361 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
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
== 0x61, "bad wparam %lx\n", msg
.wParam
);
14367 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
14369 DispatchMessageA( &msg
);
14371 seq
[0].wParam
= 0x61;
14372 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
14374 thread_locale
= GetThreadLocale();
14375 ActivateKeyboardLayout( hkl_greek
, 0 );
14376 ok( GetThreadLocale() == thread_locale
, "locale changed from %08x to %08x\n",
14377 thread_locale
, GetThreadLocale() );
14381 /* greek alpha -> 0xe1 in cp1253 */
14382 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
14384 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
14385 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
14386 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
14387 ok( msg
.wParam
== 0xe1, "bad wparam %lx\n", msg
.wParam
);
14388 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
14390 DispatchMessageA( &msg
);
14392 seq
[0].wParam
= 0x3b1;
14393 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
14395 DestroyWindow( hwnd
);
14396 ActivateKeyboardLayout( hkl_orig
, 0 );
14397 UnloadKeyboardLayout( hkl_greek
);
14400 #define ID_LISTBOX 0x000f
14402 static const struct message wm_lb_setcursel_0
[] =
14404 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
14405 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14406 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
14407 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14408 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14411 static const struct message wm_lb_setcursel_1
[] =
14413 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
14414 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14415 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
14416 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14417 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
14418 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
14419 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
14422 static const struct message wm_lb_setcursel_2
[] =
14424 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
14425 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14426 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
14427 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14428 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
14429 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
14430 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
14433 static const struct message wm_lb_click_0
[] =
14435 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
14436 { HCBT_SETFOCUS
, hook
},
14437 { WM_KILLFOCUS
, sent
|parent
},
14438 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
14439 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
14440 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14441 { WM_SETFOCUS
, sent
|defwinproc
},
14443 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
14444 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
14445 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
14446 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
14447 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
14449 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
14450 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14451 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
14452 { WM_CTLCOLORLISTBOX
, sent
|parent
},
14453 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
14454 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
14456 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14457 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
14459 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
14460 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
14461 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
14462 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
14465 static const struct message wm_lb_deletestring
[] =
14467 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
14468 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
14469 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14470 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14473 static const struct message wm_lb_deletestring_reset
[] =
14475 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
14476 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
14477 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
14478 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14479 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
14482 static const struct message wm_lb_addstring
[] =
14484 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
14485 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
14486 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
14487 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
14488 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
14489 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
14492 static const struct message wm_lb_addstring_sort
[] =
14494 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
14495 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
14496 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
14497 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ee },
14498 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
14499 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
14500 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ef },
14501 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ee, 0xf30604ef },
14502 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
14506 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
14508 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
14510 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14512 static LONG defwndproc_counter
= 0;
14514 struct recvd_message msg
;
14516 /* do not log painting messages */
14517 if (message
!= WM_PAINT
&&
14518 message
!= WM_NCPAINT
&&
14519 message
!= WM_SYNCPAINT
&&
14520 message
!= WM_ERASEBKGND
&&
14521 message
!= WM_NCHITTEST
&&
14522 message
!= WM_GETTEXT
&&
14523 !ignore_message( message
))
14526 msg
.message
= message
;
14527 msg
.flags
= sent
|wparam
|lparam
;
14528 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
14530 if (message
== LB_ADDSTRING
)
14531 msg
.lParam
= lp
? hash_Ly((const char *)lp
) : 0;
14534 msg
.descr
= "listbox";
14538 defwndproc_counter
++;
14539 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
14540 defwndproc_counter
--;
14545 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
14546 int caret_index
, int top_index
, int line
)
14550 /* calling an orig proc helps to avoid unnecessary message logging */
14551 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
14552 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %ld\n", count
, ret
);
14553 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
14554 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %ld\n", cur_sel
, ret
);
14555 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
14556 ok_(__FILE__
, line
)(ret
== caret_index
||
14557 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
14558 "expected caret index %d, got %ld\n", caret_index
, ret
);
14559 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
14560 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %ld\n", top_index
, ret
);
14563 static void test_listbox_messages(void)
14565 HWND parent
, listbox
;
14568 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14569 100, 100, 200, 200, 0, 0, 0, NULL
);
14570 /* with LBS_HASSTRINGS */
14571 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
14572 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
14573 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
14574 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
14576 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
14580 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
14581 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14582 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
14583 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14584 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
14585 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14587 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
14588 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
14592 log_all_parent_messages
++;
14594 trace("selecting item 0\n");
14595 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
14596 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14597 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
14598 check_lb_state(listbox
, 3, 0, 0, 0);
14601 trace("selecting item 1\n");
14602 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
14603 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14604 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
14605 check_lb_state(listbox
, 3, 1, 1, 0);
14607 trace("selecting item 2\n");
14608 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
14609 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14610 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
14611 check_lb_state(listbox
, 3, 2, 2, 0);
14613 trace("clicking on item 0\n");
14614 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
14615 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
14616 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
14617 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
14618 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
14619 check_lb_state(listbox
, 3, 0, 0, 0);
14622 trace("deleting item 0\n");
14623 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14624 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14625 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
14626 check_lb_state(listbox
, 2, -1, 0, 0);
14629 trace("deleting item 0\n");
14630 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14631 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14632 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
14633 check_lb_state(listbox
, 1, -1, 0, 0);
14636 trace("deleting item 0\n");
14637 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14638 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14639 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
14640 check_lb_state(listbox
, 0, -1, 0, 0);
14643 trace("deleting item 0\n");
14644 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
14645 ok(ret
== LB_ERR
, "expected LB_ERR, got %ld\n", ret
);
14646 check_lb_state(listbox
, 0, -1, 0, 0);
14649 log_all_parent_messages
--;
14651 DestroyWindow(listbox
);
14653 /* with LBS_SORT and without LBS_HASSTRINGS */
14654 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
14655 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_SORT
| WS_VISIBLE
,
14656 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
14657 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
14659 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
14663 log_all_parent_messages
++;
14665 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
14666 ok(ret
== 0, "expected 0, got %ld\n", ret
);
14667 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
14668 ok(ret
== 1, "expected 1, got %ld\n", ret
);
14669 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
14670 ok(ret
== 2, "expected 2, got %ld\n", ret
);
14672 ok_sequence(wm_lb_addstring_sort
, "LB_ADDSTRING", FALSE
);
14673 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
14675 log_all_parent_messages
--;
14677 DestroyWindow(listbox
);
14678 DestroyWindow(parent
);
14681 /*************************** Menu test ******************************/
14682 static const struct message wm_popup_menu_1
[] =
14684 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14685 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14686 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
14687 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
14688 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
14689 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
14690 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14691 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14692 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
14693 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
14694 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
14695 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
14696 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
14697 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14698 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
14699 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
14700 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14701 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14702 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14703 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
14704 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14705 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14708 static const struct message wm_popup_menu_2
[] =
14710 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14711 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14712 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
14713 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
14714 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
14715 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
14716 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14717 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14718 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
14719 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
14720 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
14721 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
14722 { HCBT_CREATEWND
, hook
},
14723 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
14724 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
14725 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
14726 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14727 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
14728 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
14729 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
14730 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
14731 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
14732 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
14733 { HCBT_DESTROYWND
, hook
},
14734 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14735 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
14736 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14737 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14738 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14739 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
14740 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14741 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14744 static const struct message wm_popup_menu_3
[] =
14746 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14747 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14748 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
14749 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
14750 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
14751 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
14752 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14753 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14754 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
14755 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
14756 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
14757 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
14758 { HCBT_CREATEWND
, hook
},
14759 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
14760 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
14761 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
14762 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14763 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
14764 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
14765 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
14766 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
14767 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
14768 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
14769 { HCBT_DESTROYWND
, hook
},
14770 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14771 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
14772 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14773 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14774 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14775 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
14776 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14777 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14781 static const struct message wm_single_menu_item
[] =
14783 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14784 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14785 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
14786 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
14787 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
14788 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
14789 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14790 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14791 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
14792 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14793 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14794 { WM_MENUCOMMAND
, sent
},
14795 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
14796 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
14797 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
14798 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
14800 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
14801 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
14802 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
14803 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
14804 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
14808 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14810 if (message
== WM_ENTERIDLE
||
14811 message
== WM_INITMENU
||
14812 message
== WM_INITMENUPOPUP
||
14813 message
== WM_MENUSELECT
||
14814 message
== WM_PARENTNOTIFY
||
14815 message
== WM_ENTERMENULOOP
||
14816 message
== WM_EXITMENULOOP
||
14817 message
== WM_UNINITMENUPOPUP
||
14818 message
== WM_KEYDOWN
||
14819 message
== WM_KEYUP
||
14820 message
== WM_CHAR
||
14821 message
== WM_SYSKEYDOWN
||
14822 message
== WM_SYSKEYUP
||
14823 message
== WM_SYSCHAR
||
14824 message
== WM_COMMAND
||
14825 message
== WM_MENUCOMMAND
)
14827 struct recvd_message msg
;
14830 msg
.message
= message
;
14831 msg
.flags
= sent
|wparam
|lparam
;
14834 msg
.descr
= "parent_menu_proc";
14838 return DefWindowProcA(hwnd
, message
, wp
, lp
);
14841 static void set_menu_style(HMENU hmenu
, DWORD style
)
14846 mi
.cbSize
= sizeof(mi
);
14847 mi
.fMask
= MIM_STYLE
;
14848 mi
.dwStyle
= style
;
14849 SetLastError(0xdeadbeef);
14850 ret
= pSetMenuInfo(hmenu
, &mi
);
14851 ok(ret
, "SetMenuInfo error %u\n", GetLastError());
14854 static DWORD
get_menu_style(HMENU hmenu
)
14859 mi
.cbSize
= sizeof(mi
);
14860 mi
.fMask
= MIM_STYLE
;
14862 SetLastError(0xdeadbeef);
14863 ret
= pGetMenuInfo(hmenu
, &mi
);
14864 ok(ret
, "GetMenuInfo error %u\n", GetLastError());
14869 static void test_menu_messages(void)
14873 HMENU hmenu
, hmenu_popup
;
14877 if (!pGetMenuInfo
|| !pSetMenuInfo
)
14879 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n");
14883 cls
.lpfnWndProc
= parent_menu_proc
;
14884 cls
.cbClsExtra
= 0;
14885 cls
.cbWndExtra
= 0;
14886 cls
.hInstance
= GetModuleHandleA(0);
14888 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
14889 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
14890 cls
.lpszMenuName
= NULL
;
14891 cls
.lpszClassName
= "TestMenuClass";
14892 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
14893 if (!RegisterClassA(&cls
)) assert(0);
14895 SetLastError(0xdeadbeef);
14896 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14897 100, 100, 200, 200, 0, 0, 0, NULL
);
14898 ok(hwnd
!= 0, "LoadMenuA error %u\n", GetLastError());
14900 SetLastError(0xdeadbeef);
14901 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
14902 ok(hmenu
!= 0, "LoadMenuA error %u\n", GetLastError());
14904 SetMenu(hwnd
, hmenu
);
14905 SetForegroundWindow( hwnd
);
14908 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
14909 style
= get_menu_style(hmenu
);
14910 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
14912 hmenu_popup
= GetSubMenu(hmenu
, 0);
14913 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14914 style
= get_menu_style(hmenu_popup
);
14915 ok(style
== 0, "expected 0, got %u\n", style
);
14917 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
14918 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14919 style
= get_menu_style(hmenu_popup
);
14920 ok(style
== 0, "expected 0, got %u\n", style
);
14923 trace("testing a popup menu command\n");
14925 keybd_event(VK_MENU
, 0, 0, 0);
14926 keybd_event('E', 0, 0, 0);
14927 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
14928 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
14929 keybd_event(VK_RETURN
, 0, 0, 0);
14930 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
14931 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14933 TranslateMessage(&msg
);
14934 DispatchMessageA(&msg
);
14936 if (!sequence_cnt
) /* we didn't get any message */
14938 skip( "queuing key events not supported\n" );
14941 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
14942 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
14944 win_skip( "menu tracking through VK_MENU not supported\n" );
14947 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
14949 /* Alt+F, Right, Enter */
14950 trace("testing submenu of a popup menu command\n");
14952 keybd_event(VK_MENU
, 0, 0, 0);
14953 keybd_event('F', 0, 0, 0);
14954 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
14955 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
14956 keybd_event(VK_RIGHT
, 0, 0, 0);
14957 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
14958 keybd_event(VK_RETURN
, 0, 0, 0);
14959 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
14960 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14962 TranslateMessage(&msg
);
14963 DispatchMessageA(&msg
);
14965 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
14967 trace("testing single menu item command\n");
14969 keybd_event(VK_MENU
, 0, 0, 0);
14970 keybd_event('Q', 0, 0, 0);
14971 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
14972 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
14973 keybd_event(VK_ESCAPE
, 0, 0, 0);
14974 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
14975 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14977 TranslateMessage(&msg
);
14978 DispatchMessageA(&msg
);
14980 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
14982 set_menu_style(hmenu
, 0);
14983 style
= get_menu_style(hmenu
);
14984 ok(style
== 0, "expected 0, got %u\n", style
);
14986 hmenu_popup
= GetSubMenu(hmenu
, 0);
14987 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14988 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
14989 style
= get_menu_style(hmenu_popup
);
14990 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
14992 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
14993 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14994 style
= get_menu_style(hmenu_popup
);
14995 ok(style
== 0, "expected 0, got %u\n", style
);
14997 /* Alt+F, Right, Enter */
14998 trace("testing submenu of a popup menu command\n");
15000 keybd_event(VK_MENU
, 0, 0, 0);
15001 keybd_event('F', 0, 0, 0);
15002 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
15003 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
15004 keybd_event(VK_RIGHT
, 0, 0, 0);
15005 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
15006 keybd_event(VK_RETURN
, 0, 0, 0);
15007 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
15008 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
15010 TranslateMessage(&msg
);
15011 DispatchMessageA(&msg
);
15013 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
15016 DestroyWindow(hwnd
);
15017 DestroyMenu(hmenu
);
15021 static void test_paintingloop(void)
15025 paint_loop_done
= FALSE
;
15026 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
15027 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
15028 100, 100, 100, 100, 0, 0, 0, NULL
);
15029 ok(hwnd
!= 0, "PaintLoop window error %u\n", GetLastError());
15030 ShowWindow(hwnd
,SW_NORMAL
);
15033 while (!paint_loop_done
)
15036 if (PeekMessageA(&msg
, 0, 0, 0, 1))
15038 TranslateMessage(&msg
);
15039 DispatchMessageA(&msg
);
15042 DestroyWindow(hwnd
);
15045 static const struct message NCRBUTTONDOWNSeq
[] =
15047 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
15048 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15049 { WM_CAPTURECHANGED
, sent
},
15050 { WM_CONTEXTMENU
, sent
, /*hwnd*/0, -1 },
15054 static const struct message NCXBUTTONUPSeq1
[] =
15056 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_BACKWARD
) },
15060 static const struct message NCXBUTTONUPSeq2
[] =
15062 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_FORWARD
) },
15066 struct rbuttonup_thread_data
15069 HANDLE wndproc_finished
;
15072 static DWORD CALLBACK
post_rbuttonup_msg( void *arg
)
15074 struct rbuttonup_thread_data
*data
= arg
;
15077 ret
= WaitForSingleObject( data
->wndproc_finished
, 500 );
15078 todo_wine
ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %x\n", ret
);
15079 if( ret
== WAIT_OBJECT_0
) return 0;
15081 PostMessageA( data
->hwnd
, WM_RBUTTONUP
, 0, 0 );
15085 static void test_defwinproc(void)
15089 BOOL gotwmquit
= FALSE
;
15094 struct rbuttonup_thread_data data
;
15098 hwnd
= CreateWindowExA(0, "TestWindowClass", "test_defwndproc",
15099 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0,0,500,100,0,0,0, NULL
);
15104 GetWindowTextA(hwnd
, buffA
, sizeof(buffA
)/sizeof(*buffA
));
15105 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
15107 /* Zero high word of the lParam */
15108 res
= DefWindowProcA(hwnd
, WM_SETTEXT
, 0, 0x1234);
15109 ok(res
== 0, "WM_SETTEXT was expected to fail, %ld\n", res
);
15111 GetWindowTextA(hwnd
, buffA
, sizeof(buffA
)/sizeof(*buffA
));
15112 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
15114 res
= DefWindowProcW(hwnd
, WM_SETTEXT
, 0, 0x1234);
15115 ok(res
== 0, "WM_SETTEXT was expected to fail, %ld\n", res
);
15117 GetWindowTextA(hwnd
, buffA
, sizeof(buffA
)/sizeof(*buffA
));
15118 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
15120 GetCursorPos(&pos
);
15121 GetWindowRect(hwnd
, &rect
);
15122 x
= (rect
.left
+rect
.right
) / 2;
15123 y
= rect
.top
+ GetSystemMetrics(SM_CYFRAME
) + 1;
15124 SetCursorPos(x
, y
);
15126 res
= DefWindowProcA( hwnd
, WM_NCHITTEST
, 0, MAKELPARAM(x
, y
));
15127 ok(res
== HTCAPTION
, "WM_NCHITTEST returned %ld\n", res
);
15129 mouse_event( MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0 );
15130 mouse_event( MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0 );
15134 mouse_event( MOUSEEVENTF_RIGHTUP
, 0, 0, 0, 0 );
15135 /* workaround for missing support for clicking on window frame */
15137 data
.wndproc_finished
= CreateEventA( NULL
, FALSE
, FALSE
, NULL
);
15138 thread
= CreateThread( NULL
, 0, post_rbuttonup_msg
, (void*)&data
, 0, NULL
);
15140 DefWindowProcA( hwnd
, WM_NCRBUTTONDOWN
, HTCAPTION
, MAKELPARAM(x
, y
));
15141 ok_sequence(NCRBUTTONDOWNSeq
, "WM_NCRBUTTONDOWN on caption", FALSE
);
15143 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, 0, MAKELPARAM(x
, y
));
15144 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15145 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP without button", FALSE
);
15147 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON1
), MAKELPARAM(x
, y
));
15148 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15149 ok_sequence(NCXBUTTONUPSeq1
, "WM_NCXBUTTONUP with XBUTTON1", FALSE
);
15151 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON2
), MAKELPARAM(x
, y
));
15152 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15153 ok_sequence(NCXBUTTONUPSeq2
, "WM_NCXBUTTONUP with XBUTTON2", FALSE
);
15155 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, 3), MAKELPARAM(x
, y
));
15156 ok(!res
, "WM_NCXBUTTONUP returned %ld\n", res
);
15157 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP with invalid button", FALSE
);
15159 SetEvent( data
.wndproc_finished
);
15160 WaitForSingleObject( thread
, 1000 );
15161 CloseHandle( data
.wndproc_finished
);
15162 CloseHandle( thread
);
15164 SetCursorPos(pos
.x
, pos
.y
);
15166 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
15167 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
15168 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
15169 DispatchMessageA( &msg
);
15171 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
15172 DestroyWindow( hwnd
);
15175 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
15176 static void clear_clipboard_(int line
, HWND hWnd
)
15179 succ
= OpenClipboard(hWnd
);
15180 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%u\n", GetLastError());
15181 succ
= EmptyClipboard();
15182 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%u\n", GetLastError());
15183 succ
= CloseClipboard();
15184 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%u\n", GetLastError());
15187 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
15188 static void expect_HWND_(int line
, HWND expected
, HWND got
)
15190 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
15193 static WNDPROC pOldViewerProc
;
15195 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15197 static BOOL recursion_guard
;
15199 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
15201 recursion_guard
= TRUE
;
15202 clear_clipboard(hWnd
);
15203 recursion_guard
= FALSE
;
15205 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
15208 static void test_clipboard_viewers(void)
15210 static struct message wm_change_cb_chain
[] =
15212 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
15215 static const struct message wm_clipboard_destroyed
[] =
15217 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15220 static struct message wm_clipboard_changed
[] =
15222 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15225 static struct message wm_clipboard_changed_and_owned
[] =
15227 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15228 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
15232 HINSTANCE hInst
= GetModuleHandleA(NULL
);
15233 HWND hWnd1
, hWnd2
, hWnd3
;
15237 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
15238 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
15239 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
15240 GetDesktopWindow(), NULL
, hInst
, NULL
);
15241 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
15242 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
15243 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
15244 GetDesktopWindow(), NULL
, hInst
, NULL
);
15245 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
15246 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
15247 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
15248 GetDesktopWindow(), NULL
, hInst
, NULL
);
15249 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
15250 assert(hWnd1
&& hWnd2
&& hWnd3
);
15252 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */
15255 /* Test getting the clipboard viewer and setting the viewer to NULL. */
15256 hOrigViewer
= GetClipboardViewer();
15257 hRet
= SetClipboardViewer(NULL
);
15258 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
15259 expect_HWND(hOrigViewer
, hRet
);
15260 expect_HWND(NULL
, GetClipboardViewer());
15262 /* Test registering hWnd1 as a viewer. */
15263 hRet
= SetClipboardViewer(hWnd1
);
15264 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
15265 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
15266 expect_HWND(NULL
, hRet
);
15267 expect_HWND(hWnd1
, GetClipboardViewer());
15269 /* Test that changing the clipboard actually refreshes the registered viewer. */
15270 clear_clipboard(hWnd1
);
15271 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
15272 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
15274 /* Again, but with different owner. */
15275 clear_clipboard(hWnd2
);
15276 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
15277 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
15279 /* Test re-registering same window. */
15280 hRet
= SetClipboardViewer(hWnd1
);
15281 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
15282 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
15283 expect_HWND(hWnd1
, hRet
);
15284 expect_HWND(hWnd1
, GetClipboardViewer());
15286 /* Test ChangeClipboardChain. */
15287 ChangeClipboardChain(hWnd2
, hWnd3
);
15288 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
15289 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
15290 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
15291 expect_HWND(hWnd1
, GetClipboardViewer());
15293 ChangeClipboardChain(hWnd2
, NULL
);
15294 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
15295 wm_change_cb_chain
[0].lParam
= 0;
15296 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
15297 expect_HWND(hWnd1
, GetClipboardViewer());
15299 ChangeClipboardChain(NULL
, hWnd2
);
15300 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", FALSE
);
15301 expect_HWND(hWnd1
, GetClipboardViewer());
15303 /* Actually change clipboard viewer with ChangeClipboardChain. */
15304 ChangeClipboardChain(hWnd1
, hWnd2
);
15305 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
15306 expect_HWND(hWnd2
, GetClipboardViewer());
15308 /* Test that no refresh messages are sent when viewer has unregistered. */
15309 clear_clipboard(hWnd2
);
15310 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
15312 /* Register hWnd1 again. */
15313 ChangeClipboardChain(hWnd2
, hWnd1
);
15314 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
15315 expect_HWND(hWnd1
, GetClipboardViewer());
15317 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
15318 * changes the clipboard. When this happens, the system shouldn't send
15319 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
15321 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
15322 clear_clipboard(hWnd2
);
15323 /* The clipboard owner is changed in recursive_viewer_proc: */
15324 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
15325 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
15327 /* Test unregistering. */
15328 ChangeClipboardChain(hWnd1
, NULL
);
15329 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
15330 expect_HWND(NULL
, GetClipboardViewer());
15332 clear_clipboard(hWnd1
);
15333 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
15335 DestroyWindow(hWnd1
);
15336 DestroyWindow(hWnd2
);
15337 DestroyWindow(hWnd3
);
15338 SetClipboardViewer(hOrigViewer
);
15341 static void test_PostMessage(void)
15343 static const struct
15349 { HWND_TOP
/* 0 */, TRUE
},
15350 { HWND_BROADCAST
, TRUE
},
15351 { HWND_BOTTOM
, TRUE
},
15352 { HWND_TOPMOST
, TRUE
},
15353 { HWND_NOTOPMOST
, FALSE
},
15354 { HWND_MESSAGE
, FALSE
},
15355 { (HWND
)0xdeadbeef, FALSE
}
15361 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
15363 SetLastError(0xdeadbeef);
15364 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
15365 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
15367 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
15374 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
15375 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
15377 for (i
= 0; i
< sizeof(data
)/sizeof(data
[0]); i
++)
15379 memset(&msg
, 0xab, sizeof(msg
));
15380 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
15381 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
15385 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
15386 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
15387 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
15388 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
15390 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
15391 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
15392 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
15393 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
15397 DestroyWindow(hwnd
);
15401 static LPARAM g_broadcast_lparam
;
15402 static LRESULT WINAPI
broadcast_test_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15404 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
15406 if (wParam
== 0xbaadbeef)
15407 g_broadcast_lparam
= wParam
;
15409 g_broadcast_lparam
= 0;
15411 return CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
15414 static void test_broadcast(void)
15416 static const UINT messages
[] =
15422 0xc000, /* lowest possible atom returned by RegisterWindowMessage */
15429 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0, 0, 0, 0, 0, 0, 0, NULL
);
15430 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
15432 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_proc
);
15433 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
15435 for (i
= 0; i
< sizeof(messages
)/sizeof(messages
[0]); i
++)
15441 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
15444 /* post, broadcast */
15445 ret
= PostMessageA(HWND_BROADCAST
, messages
[i
], 0, 0);
15446 ok(ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
15448 memset(&msg
, 0xab, sizeof(msg
));
15449 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
15450 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15452 ok(ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
15453 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
15457 ok(!ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
15460 /* post, topmost */
15461 ret
= PostMessageA(HWND_TOPMOST
, messages
[i
], 0, 0);
15462 ok(ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
15464 memset(&msg
, 0xab, sizeof(msg
));
15465 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
15466 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15468 ok(ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
15469 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
15473 ok(!ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
15476 /* send, broadcast */
15477 g_broadcast_lparam
= 0xdead;
15478 ret
= SendMessageTimeoutA(HWND_BROADCAST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
15479 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
15480 win_skip("broadcasting test %d, timeout\n", i
);
15483 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15485 ok(g_broadcast_lparam
== 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15486 g_broadcast_lparam
, GetLastError());
15490 ok(g_broadcast_lparam
== 0xdead, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15491 g_broadcast_lparam
, GetLastError());
15495 /* send, topmost */
15496 g_broadcast_lparam
= 0xdead;
15497 ret
= SendMessageTimeoutA(HWND_TOPMOST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
15498 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
15499 win_skip("broadcasting test %d, timeout\n", i
);
15502 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
15504 ok(g_broadcast_lparam
== 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15505 g_broadcast_lparam
, GetLastError());
15509 ok(g_broadcast_lparam
== 0xdead, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
15510 g_broadcast_lparam
, GetLastError());
15515 DestroyWindow(hwnd
);
15518 static const struct
15522 } wait_idle_expect
[] =
15524 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15525 { WAIT_TIMEOUT
, 0, FALSE
},
15526 { WAIT_TIMEOUT
, 0, FALSE
},
15527 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15528 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15529 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
15530 { WAIT_TIMEOUT
, 0, FALSE
},
15531 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
15534 /* 10 */ { 0, 0, FALSE
},
15536 { 0, WAIT_TIMEOUT
, FALSE
},
15539 /* 15 */ { 0, 0, FALSE
},
15540 { WAIT_TIMEOUT
, 0, FALSE
},
15541 { WAIT_TIMEOUT
, 0, FALSE
},
15542 { WAIT_TIMEOUT
, 0, FALSE
},
15543 { WAIT_TIMEOUT
, 0, FALSE
},
15544 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
15547 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
15551 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15553 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
15557 static void do_wait_idle_child( int arg
)
15564 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
15565 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
15567 memset( &cls
, 0, sizeof(cls
) );
15568 cls
.lpfnWndProc
= DefWindowProcA
;
15569 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
15570 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
15571 cls
.lpszClassName
= "TestClass";
15572 RegisterClassA( &cls
);
15574 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
15576 ok( start_event
!= 0, "failed to create start event, error %u\n", GetLastError() );
15577 ok( end_event
!= 0, "failed to create end event, error %u\n", GetLastError() );
15582 SetEvent( start_event
);
15585 SetEvent( start_event
);
15587 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
15590 SetEvent( start_event
);
15592 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15593 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
15594 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
15597 SetEvent( start_event
);
15599 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
15602 SetEvent( start_event
);
15604 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15605 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
15608 SetEvent( start_event
);
15610 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15611 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
15614 SetEvent( start_event
);
15616 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15617 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
15619 GetMessageA( &msg
, 0, 0, 0 );
15620 DispatchMessageA( &msg
);
15624 SetEvent( start_event
);
15626 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15627 SetTimer( hwnd
, 3, 1, NULL
);
15629 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
15632 SetEvent( start_event
);
15634 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15635 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
15638 SetEvent( start_event
);
15640 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15641 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
15642 for (;;) GetMessageA( &msg
, 0, 0, 0 );
15645 SetEvent( start_event
);
15647 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15648 SetTimer( hwnd
, 3, 1, NULL
);
15650 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
15653 SetEvent( start_event
);
15655 return; /* exiting the process makes WaitForInputIdle return success too */
15657 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15659 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
15660 SetEvent( start_event
);
15663 SetEvent( start_event
);
15664 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
15666 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
15667 WaitForSingleObject( thread
, 10000 );
15668 CloseHandle( thread
);
15671 SetEvent( start_event
);
15673 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
15676 SetEvent( start_event
);
15678 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
15681 SetEvent( start_event
);
15683 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
15686 SetEvent( start_event
);
15688 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
15691 SetEvent( start_event
);
15693 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
15696 SetEvent( start_event
);
15698 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
15701 SetEvent( start_event
);
15703 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
15706 WaitForSingleObject( end_event
, 2000 );
15707 CloseHandle( start_event
);
15708 CloseHandle( end_event
);
15709 if (hwnd
) DestroyWindow( hwnd
);
15712 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
15714 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
15715 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
15718 static DWORD CALLBACK
wait_idle_thread( void *arg
)
15724 memset( &cls
, 0, sizeof(cls
) );
15725 cls
.lpfnWndProc
= wait_idle_proc
;
15726 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
15727 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
15728 cls
.lpszClassName
= "TestClass";
15729 RegisterClassA( &cls
);
15731 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15732 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
15733 DestroyWindow(hwnd
);
15737 static void test_WaitForInputIdle( char *argv0
)
15739 char path
[MAX_PATH
];
15740 PROCESS_INFORMATION pi
;
15741 STARTUPINFOA startup
;
15743 HANDLE start_event
, end_event
, thread
;
15746 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
15747 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
15748 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
15750 if (console_app
) /* build the test with -mwindows for better coverage */
15751 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
15753 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
15754 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
15755 ok(start_event
!= 0, "failed to create start event, error %u\n", GetLastError());
15756 ok(end_event
!= 0, "failed to create end event, error %u\n", GetLastError());
15758 memset( &startup
, 0, sizeof(startup
) );
15759 startup
.cb
= sizeof(startup
);
15760 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
15761 startup
.wShowWindow
= SW_SHOWNORMAL
;
15763 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
15765 for (i
= 0; i
< sizeof(wait_idle_expect
)/sizeof(wait_idle_expect
[0]); i
++)
15767 ResetEvent( start_event
);
15768 ResetEvent( end_event
);
15769 #ifndef __REACTOS__
15770 sprintf( path
, "%s msg %u", argv0
, i
);
15772 sprintf( path
, "%s msg_queue %u", argv0
, i
);
15774 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
15775 ok( ret
, "CreateProcess '%s' failed err %u.\n", path
, GetLastError() );
15778 ret
= WaitForSingleObject( start_event
, 5000 );
15779 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
15780 if (ret
== WAIT_OBJECT_0
)
15782 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
15783 if (ret
== WAIT_FAILED
)
15785 ret
== wait_idle_expect
[i
].exp
||
15786 broken(ret
== wait_idle_expect
[i
].broken
),
15787 "%u: WaitForInputIdle error %08x expected %08x\n",
15788 i
, ret
, wait_idle_expect
[i
].exp
);
15789 else todo_wine_if (wait_idle_expect
[i
].todo
)
15790 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
15791 "%u: WaitForInputIdle error %08x expected %08x\n",
15792 i
, ret
, wait_idle_expect
[i
].exp
);
15793 SetEvent( end_event
);
15794 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
15796 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
15797 winetest_wait_child_process( pi
.hProcess
);
15798 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
15799 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
15800 CloseHandle( pi
.hProcess
);
15801 CloseHandle( pi
.hThread
);
15804 CloseHandle( start_event
);
15805 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
15806 WaitForSingleObject( thread
, 10000 );
15807 CloseHandle( thread
);
15810 static const struct message WmSetParentSeq_1
[] = {
15811 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15812 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15813 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
15814 { WM_CHILDACTIVATE
, sent
},
15815 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
15816 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
15817 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15818 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15822 static const struct message WmSetParentSeq_2
[] = {
15823 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15824 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15825 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15826 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15827 { HCBT_SETFOCUS
, hook
|optional
},
15828 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
15829 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
15830 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
15831 { WM_KILLFOCUS
, sent
|wparam
, 0 },
15832 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15833 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
15834 { HCBT_ACTIVATE
, hook
|optional
},
15835 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15836 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15837 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
15838 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
15839 { HCBT_SETFOCUS
, hook
|optional
},
15840 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15841 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
15842 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
15843 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
15844 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15845 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15846 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15847 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15848 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15853 static void test_SetParent(void)
15855 HWND parent1
, parent2
, child
, popup
;
15858 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
15859 100, 100, 200, 200, 0, 0, 0, NULL
);
15860 ok(parent1
!= 0, "Failed to create parent1 window\n");
15862 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
15863 400, 100, 200, 200, 0, 0, 0, NULL
);
15864 ok(parent2
!= 0, "Failed to create parent2 window\n");
15866 /* WS_CHILD window */
15867 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
15868 10, 10, 150, 150, parent1
, 0, 0, NULL
);
15869 ok(child
!= 0, "Failed to create child window\n");
15871 GetWindowRect(parent1
, &rc
);
15872 trace("parent1 %s\n", wine_dbgstr_rect(&rc
));
15873 GetWindowRect(child
, &rc_old
);
15874 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
15875 trace("child %s\n", wine_dbgstr_rect(&rc_old
));
15879 SetParent(child
, parent2
);
15881 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", TRUE
);
15883 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
15884 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
15886 GetWindowRect(parent2
, &rc
);
15887 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
15888 GetWindowRect(child
, &rc
);
15889 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
15890 trace("child %s\n", wine_dbgstr_rect(&rc
));
15892 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
15893 wine_dbgstr_rect(&rc
));
15895 /* WS_POPUP window */
15896 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
15897 20, 20, 100, 100, 0, 0, 0, NULL
);
15898 ok(popup
!= 0, "Failed to create popup window\n");
15900 GetWindowRect(popup
, &rc_old
);
15901 trace("popup %s\n", wine_dbgstr_rect(&rc_old
));
15905 SetParent(popup
, child
);
15907 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
15909 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
15910 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
15912 GetWindowRect(child
, &rc
);
15913 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
15914 GetWindowRect(popup
, &rc
);
15915 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
15916 trace("popup %s\n", wine_dbgstr_rect(&rc
));
15918 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
15919 wine_dbgstr_rect(&rc
));
15921 DestroyWindow(popup
);
15922 DestroyWindow(child
);
15923 DestroyWindow(parent1
);
15924 DestroyWindow(parent2
);
15929 static const struct message WmKeyReleaseOnly
[] = {
15930 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
15931 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
15934 static const struct message WmKeyPressNormal
[] = {
15935 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
15936 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
15939 static const struct message WmKeyPressRepeat
[] = {
15940 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
15941 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
15944 static const struct message WmKeyReleaseNormal
[] = {
15945 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
15946 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
15950 static void test_keyflags(void)
15954 BYTE keyboard_state
[256];
15957 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15958 100, 100, 200, 200, 0, 0, 0, NULL
);
15963 /* keyup without a keydown */
15964 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
15965 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15966 DispatchMessageA(&msg
);
15967 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
15969 key_state
= GetAsyncKeyState(0x41);
15970 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15972 key_state
= GetKeyState(0x41);
15973 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15976 keybd_event(0x41, 0, 0, 0);
15977 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15978 DispatchMessageA(&msg
);
15979 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
15981 key_state
= GetAsyncKeyState(0x41);
15982 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15984 key_state
= GetKeyState(0x41);
15985 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15987 /* keydown repeat */
15988 keybd_event(0x41, 0, 0, 0);
15989 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15990 DispatchMessageA(&msg
);
15991 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
15993 key_state
= GetAsyncKeyState(0x41);
15994 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15996 key_state
= GetKeyState(0x41);
15997 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16000 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
16001 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16002 DispatchMessageA(&msg
);
16003 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
16005 key_state
= GetAsyncKeyState(0x41);
16006 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16008 key_state
= GetKeyState(0x41);
16009 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16011 /* set the key state in this thread */
16012 GetKeyboardState(keyboard_state
);
16013 keyboard_state
[0x41] = 0x80;
16014 SetKeyboardState(keyboard_state
);
16016 key_state
= GetAsyncKeyState(0x41);
16017 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16020 keybd_event(0x41, 0, 0, 0);
16021 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16022 DispatchMessageA(&msg
);
16023 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
16025 key_state
= GetAsyncKeyState(0x41);
16026 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16028 key_state
= GetKeyState(0x41);
16029 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16031 /* clear the key state in this thread */
16032 GetKeyboardState(keyboard_state
);
16033 keyboard_state
[0x41] = 0;
16034 SetKeyboardState(keyboard_state
);
16036 key_state
= GetAsyncKeyState(0x41);
16037 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16040 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
16041 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
16042 DispatchMessageA(&msg
);
16043 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
16045 key_state
= GetAsyncKeyState(0x41);
16046 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16048 key_state
= GetKeyState(0x41);
16049 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
16051 DestroyWindow(test_window
);
16055 static const struct message WmHotkeyPressLWIN
[] = {
16056 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
16057 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
16058 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
16061 static const struct message WmHotkeyPress
[] = {
16062 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16063 { WM_HOTKEY
, sent
|wparam
, 5 },
16066 static const struct message WmHotkeyRelease
[] = {
16067 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16068 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
16069 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
16072 static const struct message WmHotkeyReleaseLWIN
[] = {
16073 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
16074 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
16075 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
16078 static const struct message WmHotkeyCombined
[] = {
16079 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
16080 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16081 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16082 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
16083 { WM_APP
, sent
, 0, 0 },
16084 { WM_HOTKEY
, sent
|wparam
, 5 },
16085 { WM_APP
+1, sent
, 0, 0 },
16086 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
16087 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
16088 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
16089 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
16090 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
16091 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
16094 static const struct message WmHotkeyPrevious
[] = {
16095 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
16096 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16097 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16098 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
16099 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
16100 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
16101 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
16102 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
16103 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
16104 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
16105 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
16106 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
16109 static const struct message WmHotkeyNew
[] = {
16110 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
16111 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
16112 { WM_HOTKEY
, sent
|wparam
, 5 },
16113 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
16114 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
16118 static int hotkey_letter
;
16120 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
16122 struct recvd_message msg
;
16124 if (nCode
== HC_ACTION
)
16126 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
16129 msg
.message
= wParam
;
16130 msg
.flags
= kbd_hook
|wparam
|lparam
;
16131 msg
.wParam
= kdbhookstruct
->vkCode
;
16132 msg
.lParam
= kdbhookstruct
->flags
;
16133 msg
.descr
= "KeyboardHookProc";
16136 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
)
16138 ok(kdbhookstruct
->vkCode
== VK_LWIN
|| kdbhookstruct
->vkCode
== hotkey_letter
,
16139 "unexpected keycode %x\n", kdbhookstruct
->vkCode
);
16143 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
16146 static void test_hotkey(void)
16148 HWND test_window
, taskbar_window
;
16151 DWORD queue_status
;
16154 SetLastError(0xdeadbeef);
16155 ret
= UnregisterHotKey(NULL
, 0);
16156 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16157 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16158 "unexpected error %d\n", GetLastError());
16162 skip("hotkeys not supported\n");
16166 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16167 100, 100, 200, 200, 0, 0, 0, NULL
);
16171 SetLastError(0xdeadbeef);
16172 ret
= UnregisterHotKey(test_window
, 0);
16173 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16174 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16175 "unexpected error %d\n", GetLastError());
16177 /* Search for a Windows Key + letter combination that hasn't been registered */
16178 for (hotkey_letter
= 0x41; hotkey_letter
<= 0x51; hotkey_letter
++)
16180 SetLastError(0xdeadbeef);
16181 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
16189 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16190 "unexpected error %d\n", GetLastError());
16194 if (hotkey_letter
== 0x52)
16196 ok(0, "Couldn't find any free Windows Key + letter combination\n");
16200 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
16201 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
16203 /* Same key combination, different id */
16204 SetLastError(0xdeadbeef);
16205 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
16206 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16207 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16208 "unexpected error %d\n", GetLastError());
16210 /* Same key combination, different window */
16211 SetLastError(0xdeadbeef);
16212 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
16213 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16214 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16215 "unexpected error %d\n", GetLastError());
16217 /* Register the same hotkey twice */
16218 SetLastError(0xdeadbeef);
16219 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
16220 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16221 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16222 "unexpected error %d\n", GetLastError());
16224 /* Window on another thread */
16225 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
16226 if (!taskbar_window
)
16228 skip("no taskbar?\n");
16232 SetLastError(0xdeadbeef);
16233 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
16234 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16235 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
16236 "unexpected error %d\n", GetLastError());
16239 /* Inject the appropriate key sequence */
16240 keybd_event(VK_LWIN
, 0, 0, 0);
16241 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16242 DispatchMessageA(&msg
);
16243 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
16245 keybd_event(hotkey_letter
, 0, 0, 0);
16246 queue_status
= GetQueueStatus(QS_HOTKEY
);
16247 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
16248 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16250 if (msg
.message
== WM_HOTKEY
)
16252 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
16253 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16255 DispatchMessageA(&msg
);
16257 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
16259 queue_status
= GetQueueStatus(QS_HOTKEY
);
16260 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
16262 key_state
= GetAsyncKeyState(hotkey_letter
);
16263 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
16265 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16266 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16267 DispatchMessageA(&msg
);
16268 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
16270 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16271 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16272 DispatchMessageA(&msg
);
16273 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
16275 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
16276 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
16277 queue_status
= GetQueueStatus(QS_HOTKEY
);
16278 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
16279 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
16280 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
16281 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16282 DispatchMessageA(&msg
);
16285 /* Send and process all messages at once */
16286 PostMessageA(test_window
, WM_APP
, 0, 0);
16287 keybd_event(VK_LWIN
, 0, 0, 0);
16288 keybd_event(hotkey_letter
, 0, 0, 0);
16289 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16290 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16292 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16294 if (msg
.message
== WM_HOTKEY
)
16296 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
16297 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16299 DispatchMessageA(&msg
);
16301 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
16303 /* Register same hwnd/id with different key combination */
16304 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
16305 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16307 /* Previous key combination does not work */
16308 keybd_event(VK_LWIN
, 0, 0, 0);
16309 keybd_event(hotkey_letter
, 0, 0, 0);
16310 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16311 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16313 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16314 DispatchMessageA(&msg
);
16315 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
16317 /* New key combination works */
16318 keybd_event(hotkey_letter
, 0, 0, 0);
16319 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16321 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16323 if (msg
.message
== WM_HOTKEY
)
16325 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
16326 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16328 DispatchMessageA(&msg
);
16330 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
16332 /* Unregister hotkey properly */
16333 ret
= UnregisterHotKey(test_window
, 5);
16334 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16336 /* Unregister hotkey again */
16337 SetLastError(0xdeadbeef);
16338 ret
= UnregisterHotKey(test_window
, 5);
16339 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
16340 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
16341 "unexpected error %d\n", GetLastError());
16343 /* Register thread hotkey */
16344 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
16345 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16347 /* Inject the appropriate key sequence */
16348 keybd_event(VK_LWIN
, 0, 0, 0);
16349 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16351 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16352 DispatchMessageA(&msg
);
16354 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
16356 keybd_event(hotkey_letter
, 0, 0, 0);
16357 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16359 if (msg
.message
== WM_HOTKEY
)
16361 struct recvd_message message
;
16362 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
16363 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
16364 message
.message
= msg
.message
;
16365 message
.flags
= sent
|wparam
|lparam
;
16366 message
.wParam
= msg
.wParam
;
16367 message
.lParam
= msg
.lParam
;
16368 message
.descr
= "test_hotkey thread message";
16369 add_message(&message
);
16372 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16373 DispatchMessageA(&msg
);
16375 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
16377 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
16378 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16380 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16381 DispatchMessageA(&msg
);
16383 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
16385 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
16386 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
16388 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
16389 DispatchMessageA(&msg
);
16391 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
16393 /* Unregister thread hotkey */
16394 ret
= UnregisterHotKey(NULL
, 5);
16395 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
16397 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
16401 UnregisterHotKey(NULL
, 5);
16402 UnregisterHotKey(test_window
, 5);
16403 DestroyWindow(test_window
);
16408 static const struct message WmSetFocus_1
[] = {
16409 { HCBT_SETFOCUS
, hook
}, /* child */
16410 { HCBT_ACTIVATE
, hook
}, /* parent */
16411 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
16412 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
16413 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
16414 { WM_NCACTIVATE
, sent
|parent
},
16415 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
16416 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
16417 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
16418 { HCBT_SETFOCUS
, hook
}, /* parent */
16419 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
16420 { WM_KILLFOCUS
, sent
|parent
},
16421 { WM_SETFOCUS
, sent
},
16424 static const struct message WmSetFocus_2
[] = {
16425 { HCBT_SETFOCUS
, hook
}, /* parent */
16426 { WM_KILLFOCUS
, sent
},
16427 { WM_SETFOCUS
, sent
|parent
},
16430 static const struct message WmSetFocus_3
[] = {
16431 { HCBT_SETFOCUS
, hook
}, /* child */
16435 static void test_SetFocus(void)
16437 HWND parent
, old_parent
, child
, old_focus
, old_active
;
16439 struct wnd_event wnd_event
;
16443 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
16444 ok(wnd_event
.start_event
!= 0, "CreateEvent error %d\n", GetLastError());
16445 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
16446 ok(hthread
!= 0, "CreateThread error %d\n", GetLastError());
16447 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
16448 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
16449 CloseHandle(wnd_event
.start_event
);
16451 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
16452 0, 0, 0, 0, 0, 0, 0, NULL
);
16453 ok(parent
!= 0, "failed to create parent window\n");
16454 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
16455 0, 0, 0, 0, parent
, 0, 0, NULL
);
16456 ok(child
!= 0, "failed to create child window\n");
16458 trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
16461 SetActiveWindow(0);
16466 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
16467 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
16469 log_all_parent_messages
++;
16471 old_focus
= SetFocus(child
);
16472 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16473 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
16474 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
16475 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16476 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
16478 old_focus
= SetFocus(parent
);
16479 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16480 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
16481 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
16482 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16483 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16485 SetLastError(0xdeadbeef);
16486 old_focus
= SetFocus((HWND
)0xdeadbeef);
16487 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
16488 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
16489 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16490 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
16491 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16492 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16493 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16495 SetLastError(0xdeadbeef);
16496 old_focus
= SetFocus(GetDesktopWindow());
16497 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
16498 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
16499 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16500 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
16501 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16502 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16503 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16505 SetLastError(0xdeadbeef);
16506 old_focus
= SetFocus(wnd_event
.hwnd
);
16507 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
16508 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
16509 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16510 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
16511 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16512 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16513 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16515 SetLastError(0xdeadbeef);
16516 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
16517 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
16518 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
16519 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16520 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
16521 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
16522 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16523 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16525 SetLastError(0xdeadbeef);
16526 old_active
= SetActiveWindow(GetDesktopWindow());
16528 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
16529 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16530 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
16531 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
16532 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16533 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16535 SetLastError(0xdeadbeef);
16536 old_active
= SetActiveWindow(wnd_event
.hwnd
);
16538 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
16539 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16540 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
16541 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
16542 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16543 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16545 SetLastError(0xdeadbeef);
16546 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
16547 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
16549 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16550 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16555 old_focus
= SetFocus(wnd_event
.hwnd
);
16556 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16557 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
16558 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
16559 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
16561 old_focus
= SetFocus(parent
);
16562 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16563 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
16564 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16565 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16570 old_active
= SetActiveWindow(wnd_event
.hwnd
);
16571 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16572 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
16573 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
16574 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
16576 SetLastError(0xdeadbeef);
16577 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
16578 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
16580 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
16581 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
16583 old_parent
= SetParent(child
, GetDesktopWindow());
16584 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
16586 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
16587 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
16589 old_focus
= SetFocus(parent
);
16590 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16591 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
16592 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16593 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16598 SetLastError(0xdeadbeef);
16599 old_focus
= SetFocus(child
);
16601 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
16602 broken(GetLastError() == 0) /* XP */ ||
16603 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
16604 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16605 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
16606 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
16607 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16608 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16610 SetLastError(0xdeadbeef);
16611 old_active
= SetActiveWindow(child
);
16612 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
16613 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
16614 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
16615 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
16616 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
16617 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
16619 log_all_parent_messages
--;
16621 DestroyWindow(child
);
16622 DestroyWindow(parent
);
16624 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
16625 ok(ret
, "PostMessage(WM_QUIT) error %d\n", GetLastError());
16626 ret
= WaitForSingleObject(hthread
, INFINITE
);
16627 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
16628 CloseHandle(hthread
);
16631 static const struct message WmSetLayeredStyle
[] = {
16632 { WM_STYLECHANGING
, sent
},
16633 { WM_STYLECHANGED
, sent
},
16634 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16638 static const struct message WmSetLayeredStyle2
[] = {
16639 { WM_STYLECHANGING
, sent
},
16640 { WM_STYLECHANGED
, sent
},
16641 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16642 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
16643 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
16644 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
16645 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
16649 struct layered_window_info
16658 static DWORD CALLBACK
update_layered_proc( void *param
)
16660 struct layered_window_info
*info
= param
;
16661 POINT src
= { 0, 0 };
16663 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
16664 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16665 ok( info
->ret
, "failed\n");
16666 SetEvent( info
->event
);
16670 static void test_layered_window(void)
16681 struct layered_window_info info
;
16683 if (!pUpdateLayeredWindow
)
16685 win_skip( "UpdateLayeredWindow not supported\n" );
16689 hdc
= CreateCompatibleDC( 0 );
16690 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
16691 SelectObject( hdc
, bmp
);
16693 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
16694 100, 100, 300, 300, 0, 0, 0, NULL
);
16695 ok( hwnd
!= 0, "failed to create window\n" );
16696 ShowWindow( hwnd
, SW_SHOWNORMAL
);
16697 UpdateWindow( hwnd
);
16701 GetWindowRect( hwnd
, &rect
);
16702 GetClientRect( hwnd
, &client
);
16703 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
16704 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
16707 pos
.x
= pos
.y
= 300;
16708 size
.cx
= size
.cy
= 250;
16709 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16710 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16711 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
16712 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
16713 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
16715 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16716 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16717 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16718 GetWindowRect( hwnd
, &rect
);
16719 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
16720 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16721 GetClientRect( hwnd
, &rect
);
16722 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
16723 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16727 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16728 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16729 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16730 GetWindowRect( hwnd
, &rect
);
16731 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
16732 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16733 GetClientRect( hwnd
, &rect
);
16734 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
16735 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16737 SetWindowLongA( hwnd
, GWL_STYLE
,
16738 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
16739 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
16743 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16744 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16745 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16746 GetWindowRect( hwnd
, &rect
);
16747 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
16748 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16749 GetClientRect( hwnd
, &rect
);
16750 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
16751 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
16752 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16755 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16756 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16757 ok( GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == ERROR_MR_MID_NOT_FOUND
) ||
16758 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win7 */, "wrong error %u\n", GetLastError() );
16761 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16762 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16763 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
16765 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
16766 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
16767 GetWindowRect( hwnd
, &rect
);
16768 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
16769 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16770 GetClientRect( hwnd
, &rect
);
16771 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
16772 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
16773 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16775 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
16778 info
.size
.cx
= 250;
16779 info
.size
.cy
= 300;
16780 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
16782 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
16783 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
16784 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
16785 WaitForSingleObject( thread
, 1000 );
16786 CloseHandle( thread
);
16787 GetWindowRect( hwnd
, &rect
);
16788 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
16789 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16790 GetClientRect( hwnd
, &rect
);
16791 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
16792 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
16793 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16795 DestroyWindow( hwnd
);
16797 DeleteObject( bmp
);
16800 static HMENU hpopupmenu
;
16802 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16804 if (ignore_message( message
)) return 0;
16808 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
16812 case WM_INITMENUPOPUP
:
16813 case WM_UNINITMENUPOPUP
:
16814 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %lx\n", hpopupmenu
, wParam
);
16816 case WM_CAPTURECHANGED
:
16817 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %lx\n", lParam
);
16821 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
16824 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16826 if (ignore_message( message
)) return 0;
16829 case WM_ENTERMENULOOP
:
16830 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
16834 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
16837 static void test_TrackPopupMenu(void)
16843 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
16846 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
16848 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
16850 hpopupmenu
= CreatePopupMenu();
16851 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
16853 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
16854 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
16858 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16859 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
16860 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
16862 /* Test popup closing with an ESC-press */
16864 PostMessageW(hwnd
, WM_KEYDOWN
, VK_ESCAPE
, 0);
16865 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16866 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
16867 PostQuitMessage(0);
16869 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
16871 TranslateMessage(&msg
);
16872 DispatchMessageA(&msg
);
16874 ok_sequence(WmTrackPopupMenuEsc
, "TrackPopupMenuEsc", FALSE
); /* Shouldn't get any message */
16876 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
16880 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16881 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
16882 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
16884 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
16890 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16891 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
16892 ok(ret
== 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError());
16894 DestroyMenu(hpopupmenu
);
16895 DestroyWindow(hwnd
);
16898 static void test_TrackPopupMenuEmpty(void)
16903 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
16906 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
16908 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
16910 hpopupmenu
= CreatePopupMenu();
16911 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
16915 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16916 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
16917 ok(ret
== 0, "TrackPopupMenu succeeded\n");
16919 DestroyMenu(hpopupmenu
);
16920 DestroyWindow(hwnd
);
16923 static const struct message send_message_1
[] = {
16924 { WM_USER
+2, sent
|wparam
|lparam
, 0, 0 },
16925 { WM_USER
, sent
|wparam
|lparam
, 0, 0 },
16928 static const struct message send_message_2
[] = {
16929 { WM_USER
+4, sent
|wparam
|lparam
, 0, 0 },
16932 static const struct message send_message_3
[] = {
16933 { WM_USER
+3, sent
|wparam
|lparam
, 0, 0 },
16936 static const struct message send_message_4
[] = {
16937 { WM_USER
+1, sent
|wparam
|lparam
, 0, 0 },
16941 static DWORD WINAPI
SendMessage_thread_1(void *param
)
16943 struct wnd_event
*wnd_event
= param
;
16945 trace("thread: starting\n");
16946 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
16948 trace("thread: call PostMessage\n");
16949 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
16951 trace("thread: call PostMessage\n");
16952 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
16954 trace("thread: call SendMessage\n");
16955 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
16957 trace("thread: call SendMessage\n");
16958 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
16963 static DWORD WINAPI
SendMessage_thread_2(void *param
)
16965 struct wnd_event
*wnd_event
= param
;
16967 trace("thread: starting\n");
16968 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
16970 trace("thread: call PostMessage\n");
16971 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
16973 trace("thread: call PostMessage\n");
16974 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
16976 /* this leads to sending an internal message under Wine */
16977 trace("thread: call SetParent\n");
16978 SetParent(wnd_event
->hwnd
, wnd_event
->hwnd
);
16980 trace("thread: call SendMessage\n");
16981 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
16983 trace("thread: call SendMessage\n");
16984 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
16989 static void test_SendMessage_other_thread(int thread_n
)
16991 DWORD qs_all_input
= QS_ALLINPUT
& ~QS_RAWINPUT
;
16993 struct wnd_event wnd_event
;
16997 wnd_event
.start_event
= CreateEventA(NULL
, 0, 0, NULL
);
16999 wnd_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
17000 100, 100, 200, 200, 0, 0, 0, NULL
);
17001 ok(wnd_event
.hwnd
!= 0, "CreateWindowEx failed\n");
17003 hthread
= CreateThread(NULL
, 0, thread_n
== 1 ? SendMessage_thread_1
: SendMessage_thread_2
, &wnd_event
, 0, &tid
);
17004 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
17005 CloseHandle(hthread
);
17010 ret
= GetQueueStatus(QS_SENDMESSAGE
);
17011 ok(ret
== 0, "wrong status %08x\n", ret
);
17013 SetEvent(wnd_event
.start_event
);
17015 /* wait for other thread's SendMessage */
17018 ret
= GetQueueStatus(QS_SENDMESSAGE
);
17019 if (ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
)) break;
17023 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17024 ok(ret
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08x\n", ret
);
17026 trace("main: call GetMessage\n");
17027 GetMessageA(&msg
, 0, 0, 0);
17028 ok(msg
.message
== WM_USER
, "expected WM_USER, got %04x\n", msg
.message
);
17029 DispatchMessageA(&msg
);
17030 ok_sequence(send_message_1
, "SendMessage from other thread 1", thread_n
== 2);
17032 /* intentionally yield */
17033 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
17035 trace("main: call SendMessage\n");
17036 SendMessageA(wnd_event
.hwnd
, WM_USER
+4, 0, 0);
17037 ok_sequence(send_message_2
, "SendMessage from other thread 2", FALSE
);
17039 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17040 ok(ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08x\n", ret
);
17042 trace("main: call PeekMessage\n");
17043 ok(PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should not fail\n");
17044 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
17045 ok_sequence(send_message_3
, "SendMessage from other thread 3", thread_n
== 2);
17047 trace("main: call PeekMessage\n");
17048 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should not fail\n");
17049 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
17050 DispatchMessageA(&msg
);
17051 ok_sequence(send_message_4
, "SendMessage from other thread 4", FALSE
);
17053 /* intentionally yield */
17054 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
17056 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17057 /* FIXME: remove once Wine is fixed */
17058 todo_wine_if (thread_n
== 2)
17059 ok(ret
== 0, "wrong status %08x\n", ret
);
17061 trace("main: call PeekMessage\n");
17062 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should fail\n");
17063 ok_sequence(WmEmptySeq
, "SendMessage from other thread 5", thread_n
== 2);
17065 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
17066 ok(ret
== 0, "wrong status %08x\n", ret
);
17068 trace("main: call DestroyWindow\n");
17069 DestroyWindow(msg
.hwnd
);
17075 static LRESULT CALLBACK
insendmessage_wnd_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
17077 DWORD flags
= InSendMessageEx( NULL
);
17083 ok( flags
== ISMEX_SEND
, "wrong flags %x\n", flags
);
17084 ok( InSendMessage(), "InSendMessage returned false\n" );
17085 ret
= ReplyMessage( msg
);
17086 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
17087 flags
= InSendMessageEx( NULL
);
17088 ok( flags
== (ISMEX_SEND
| ISMEX_REPLIED
), "wrong flags %x\n", flags
);
17089 ok( InSendMessage(), "InSendMessage returned false\n" );
17092 ok( flags
== ISMEX_NOTIFY
, "wrong flags %x\n", flags
);
17093 ok( InSendMessage(), "InSendMessage returned false\n" );
17094 ret
= ReplyMessage( msg
);
17095 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
17096 flags
= InSendMessageEx( NULL
);
17097 ok( flags
== ISMEX_NOTIFY
, "wrong flags %x\n", flags
);
17098 ok( InSendMessage(), "InSendMessage returned false\n" );
17101 ok( flags
== ISMEX_CALLBACK
, "wrong flags %x\n", flags
);
17102 ok( InSendMessage(), "InSendMessage returned false\n" );
17103 ret
= ReplyMessage( msg
);
17104 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
17105 flags
= InSendMessageEx( NULL
);
17106 ok( flags
== (ISMEX_CALLBACK
| ISMEX_REPLIED
) || flags
== ISMEX_SEND
, "wrong flags %x\n", flags
);
17107 ok( InSendMessage(), "InSendMessage returned false\n" );
17110 ok( flags
== ISMEX_NOSEND
, "wrong flags %x\n", flags
);
17111 ok( !InSendMessage(), "InSendMessage returned true\n" );
17112 ret
= ReplyMessage( msg
);
17113 ok( !ret
, "ReplyMessage succeeded\n" );
17117 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
17120 static void CALLBACK
msg_callback( HWND hwnd
, UINT msg
, ULONG_PTR arg
, LRESULT result
)
17122 ok( msg
== WM_USER
+ 2, "wrong msg %x\n", msg
);
17123 ok( result
== WM_USER
+ 2, "wrong result %lx\n", result
);
17126 static DWORD WINAPI
send_message_thread( void *arg
)
17130 SendMessageA( win
, WM_USER
, 0, 0 );
17131 SendNotifyMessageA( win
, WM_USER
+ 1, 0, 0 );
17132 SendMessageCallbackA( win
, WM_USER
+ 2, 0, 0, msg_callback
, 0 );
17133 PostMessageA( win
, WM_USER
+ 3, 0, 0 );
17134 PostMessageA( win
, WM_QUIT
, 0, 0 );
17138 static void test_InSendMessage(void)
17146 memset(&cls
, 0, sizeof(cls
));
17147 cls
.lpfnWndProc
= insendmessage_wnd_proc
;
17148 cls
.hInstance
= GetModuleHandleA(NULL
);
17149 cls
.lpszClassName
= "InSendMessage_test";
17150 RegisterClassA(&cls
);
17152 win
= CreateWindowA( "InSendMessage_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
17153 ok( win
!= NULL
, "CreateWindow failed: %d\n", GetLastError() );
17155 thread
= CreateThread( NULL
, 0, send_message_thread
, win
, 0, &tid
);
17156 ok( thread
!= NULL
, "CreateThread failed: %d\n", GetLastError() );
17158 while (GetMessageA(&msg
, NULL
, 0, 0)) DispatchMessageA( &msg
);
17160 ok( WaitForSingleObject( thread
, 30000 ) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
17161 CloseHandle( thread
);
17163 DestroyWindow( win
);
17164 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL
) );
17167 static const struct message DoubleSetCaptureSeq
[] =
17169 { WM_CAPTURECHANGED
, sent
},
17173 static void test_DoubleSetCapture(void)
17177 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture",
17178 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
17179 100, 100, 200, 200, 0, 0, 0, NULL
);
17180 ok (hwnd
!= 0, "Failed to create overlapped window\n");
17182 ShowWindow( hwnd
, SW_SHOW
);
17183 UpdateWindow( hwnd
);
17187 SetCapture( hwnd
);
17188 SetCapture( hwnd
);
17189 ok_sequence(DoubleSetCaptureSeq
, "SetCapture( hwnd ) twice", FALSE
);
17191 DestroyWindow(hwnd
);
17194 static void init_funcs(void)
17196 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
17198 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
17201 X(DeactivateActCtx
);
17202 X(GetCurrentActCtx
);
17208 #ifndef __REACTOS__
17213 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
17214 HMODULE hModuleImm32
;
17215 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
17220 argc
= winetest_get_mainargs( &test_argv
);
17224 /* Child process. */
17225 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
17226 do_wait_idle_child( arg
);
17230 InitializeCriticalSection( &sequence_cs
);
17233 hModuleImm32
= LoadLibraryA("imm32.dll");
17234 if (hModuleImm32
) {
17235 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
17236 if (pImmDisableIME
)
17239 pImmDisableIME
= NULL
;
17240 FreeLibrary(hModuleImm32
);
17242 if (!RegisterWindowClasses()) assert(0);
17244 if (pSetWinEventHook
)
17246 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
17247 GetModuleHandleA(0), win_event_proc
,
17248 0, GetCurrentThreadId(),
17249 WINEVENT_INCONTEXT
);
17250 if (pIsWinEventHookInstalled
&& hEvent_hook
)
17253 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
17254 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
17257 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
17259 cbt_hook_thread_id
= GetCurrentThreadId();
17260 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
17261 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
17265 /* Fix message sequences before removing 4 lines below */
17266 if (pUnhookWinEvent
&& hEvent_hook
)
17268 ret
= pUnhookWinEvent(hEvent_hook
);
17269 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17270 pUnhookWinEvent
= 0;
17274 test_SendMessage_other_thread(1);
17275 test_SendMessage_other_thread(2);
17276 test_InSendMessage();
17279 test_PostMessage();
17282 test_PeekMessage();
17283 test_PeekMessage2();
17284 test_PeekMessage3();
17285 test_WaitForInputIdle( test_argv
[0] );
17286 test_scrollwindowex();
17288 test_setwindowpos();
17290 invisible_parent_tests();
17291 test_mdi_messages();
17292 test_button_messages();
17293 test_autoradio_BM_CLICK();
17294 test_autoradio_kbd_move();
17295 test_static_messages();
17296 test_listbox_messages();
17297 test_combobox_messages();
17298 test_wmime_keydown_message();
17299 test_paint_messages();
17300 test_interthread_messages();
17301 test_message_conversion();
17302 test_accelerators();
17304 test_timers_no_wnd();
17305 test_timers_exceptions();
17309 test_recursive_hook();
17311 test_DestroyWindow();
17312 test_DispatchMessage();
17313 test_SendMessageTimeout();
17314 test_edit_messages();
17315 test_quit_message();
17316 test_notify_message();
17317 test_SetActiveWindow();
17319 if (!pTrackMouseEvent
)
17320 win_skip("TrackMouseEvent is not available\n");
17322 test_TrackMouseEvent();
17324 test_SetWindowRgn();
17326 test_dialog_messages();
17328 test_nullCallback();
17329 test_dbcs_wm_char();
17330 test_unicode_wm_char();
17331 test_menu_messages();
17332 test_paintingloop();
17334 test_clipboard_viewers();
17337 test_layered_window();
17338 test_TrackPopupMenu();
17339 test_TrackPopupMenuEmpty();
17340 test_DoubleSetCapture();
17341 /* keep it the last test, under Windows it tends to break the tests
17342 * which rely on active/foreground windows being correct.
17344 test_SetForegroundWindow();
17346 UnhookWindowsHookEx(hCBT_hook
);
17347 if (pUnhookWinEvent
&& hEvent_hook
)
17349 ret
= pUnhookWinEvent(hEvent_hook
);
17350 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17351 SetLastError(0xdeadbeef);
17352 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
17353 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
17354 GetLastError() == 0xdeadbeef, /* Win9x */
17355 "unexpected error %d\n", GetLastError());
17357 DeleteCriticalSection( &sequence_cs
);
17359 #endif /* __REACTOS__ */
17361 static void init_tests()
17363 HMODULE hModuleImm32
;
17364 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
17368 InitializeCriticalSection( &sequence_cs
);
17371 hModuleImm32
= LoadLibraryA("imm32.dll");
17372 if (hModuleImm32
) {
17373 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
17374 if (pImmDisableIME
)
17377 pImmDisableIME
= NULL
;
17378 FreeLibrary(hModuleImm32
);
17380 if (!RegisterWindowClasses()) assert(0);
17382 cbt_hook_thread_id
= GetCurrentThreadId();
17383 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
17384 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
17387 static void cleanup_tests()
17390 UnhookWindowsHookEx(hCBT_hook
);
17391 if (pUnhookWinEvent
&& hEvent_hook
)
17393 ret
= pUnhookWinEvent(hEvent_hook
);
17394 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17395 SetLastError(0xdeadbeef);
17396 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
17397 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
17398 GetLastError() == 0xdeadbeef, /* Win9x */
17399 "unexpected error %d\n", GetLastError());
17401 DeleteCriticalSection( &sequence_cs
);
17405 START_TEST(msg_queue
)
17409 argc
= winetest_get_mainargs( &test_argv
);
17413 /* Child process. */
17414 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
17415 do_wait_idle_child( arg
);
17420 test_SendMessage_other_thread(1);
17421 test_SendMessage_other_thread(2);
17422 test_InSendMessage();
17423 test_PostMessage();
17425 test_PeekMessage();
17426 test_PeekMessage2();
17427 test_PeekMessage3();
17428 test_interthread_messages();
17429 test_DispatchMessage();
17430 test_SendMessageTimeout();
17431 test_quit_message();
17432 test_notify_message();
17433 test_WaitForInputIdle( test_argv
[0] );
17434 test_DestroyWindow();
17438 START_TEST(msg_messages
)
17441 test_message_conversion();
17443 test_wmime_keydown_message();
17444 test_nullCallback();
17445 test_dbcs_wm_char();
17446 test_unicode_wm_char();
17451 START_TEST(msg_focus
)
17457 /* HACK: For some reason the tests fail on Windows if run consecutively.
17458 * Putting these in between helps, and is essentially what happens in the
17459 * "normal" msg test. */
17460 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
17463 test_SetActiveWindow();
17466 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
17469 test_DoubleSetCapture();
17471 /* keep it the last test, under Windows it tends to break the tests
17472 * which rely on active/foreground windows being correct.
17474 test_SetForegroundWindow();
17478 START_TEST(msg_winpos
)
17483 test_setwindowpos();
17485 test_SetWindowRgn();
17486 invisible_parent_tests();
17490 START_TEST(msg_paint
)
17493 test_scrollwindowex();
17494 test_paint_messages();
17496 if (!winetest_interactive
&&
17497 !strcmp(winetest_platform
, "windows"))
17499 skip("ROSTESTS-185: Skipping user32_winetest:msg_paint test_paintingloop because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
17503 test_paintingloop();
17507 START_TEST(msg_input
)
17510 test_accelerators();
17511 if (!pTrackMouseEvent
)
17512 win_skip("TrackMouseEvent is not available\n");
17514 test_TrackMouseEvent();
17521 START_TEST(msg_timer
)
17525 test_timers_no_wnd();
17526 test_timers_exceptions();
17530 typedef BOOL (WINAPI
*IS_WINEVENT_HOOK_INSTALLED
)(DWORD
);
17532 START_TEST(msg_hook
)
17534 // HMODULE user32 = GetModuleHandleA("user32.dll");
17535 // IS_WINEVENT_HOOK_INSTALLED pIsWinEventHookInstalled = (IS_WINEVENT_HOOK_INSTALLED)GetProcAddress(user32, "IsWinEventHookInstalled");
17536 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
17540 if (pSetWinEventHook
)
17542 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
17543 GetModuleHandleA(0), win_event_proc
,
17544 0, GetCurrentThreadId(),
17545 WINEVENT_INCONTEXT
);
17546 if (pIsWinEventHookInstalled
&& hEvent_hook
)
17549 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
17550 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
17553 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
17557 /* Fix message sequences before removing 4 lines below */
17558 if (pUnhookWinEvent
&& hEvent_hook
)
17561 ret
= pUnhookWinEvent(hEvent_hook
);
17562 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
17563 pUnhookWinEvent
= 0;
17569 test_recursive_hook();
17574 START_TEST(msg_menu
)
17578 test_menu_messages();
17579 test_TrackPopupMenu();
17580 test_TrackPopupMenuEmpty();
17584 START_TEST(msg_mdi
)
17587 test_mdi_messages();
17591 START_TEST(msg_controls
)
17594 test_button_messages();
17595 test_autoradio_BM_CLICK();
17596 test_autoradio_kbd_move();
17597 test_static_messages();
17598 test_listbox_messages();
17599 test_combobox_messages();
17600 test_edit_messages();
17604 START_TEST(msg_layered_window
)
17607 test_layered_window();
17611 START_TEST(msg_dialog
)
17614 test_dialog_messages();
17619 START_TEST(msg_clipboard
)
17622 test_clipboard_viewers();