2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004, 2005 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 */
36 #include "wine/test.h"
38 #define MDI_FIRST_CHILD_ID 2004
40 /* undocumented SWP flags - from SDK 3.1 */
41 #define SWP_NOCLIENTSIZE 0x0800
42 #define SWP_NOCLIENTMOVE 0x1000
43 #define SWP_STATECHANGED 0x8000
45 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
48 #define WM_KEYF1 0x004d
52 #define WM_SYSTIMER 0x0118
55 #define WND_PARENT_ID 1
56 #define WND_POPUP_ID 2
57 #define WND_CHILD_ID 3
59 #ifndef WM_LBTRACKPOINT
60 #define WM_LBTRACKPOINT 0x0131
65 #elif defined __x86_64__
71 static BOOL (WINAPI
*pActivateActCtx
)(HANDLE
,ULONG_PTR
*);
72 static HANDLE (WINAPI
*pCreateActCtxW
)(PCACTCTXW
);
73 static BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
,ULONG_PTR
);
74 static BOOL (WINAPI
*pGetCurrentActCtx
)(HANDLE
*);
75 static void (WINAPI
*pReleaseActCtx
)(HANDLE
);
77 /* encoded DRAWITEMSTRUCT into an LPARAM */
84 UINT type
: 4; /* ODT_* flags */
85 UINT ctl_id
: 4; /* Control ID */
86 UINT item_id
: 4; /* Menu item ID */
87 UINT action
: 4; /* ODA_* flags */
88 UINT state
: 16; /* ODS_* flags */
94 static BOOL test_DestroyWindow_flag
;
95 static HWINEVENTHOOK hEvent_hook
;
96 static HHOOK hKBD_hook
;
97 static HHOOK hCBT_hook
;
98 static DWORD cbt_hook_thread_id
;
100 static const WCHAR testWindowClassW
[] =
101 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
104 FIXME: add tests for these
105 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
106 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
107 WS_THICKFRAME: thick border
108 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
109 WS_BORDER (default for overlapped windows): single black border
110 none (default for child (and popup?) windows): no border
128 UINT message
; /* the WM_* code */
129 msg_flags_t flags
; /* message props */
130 WPARAM wParam
; /* expected value of wParam */
131 LPARAM lParam
; /* expected value of lParam */
132 WPARAM wp_mask
; /* mask for wParam checks */
133 LPARAM lp_mask
; /* mask for lParam checks */
136 struct recvd_message
{
137 UINT message
; /* the WM_* code */
138 msg_flags_t flags
; /* message props */
139 HWND hwnd
; /* window that received the message */
140 WPARAM wParam
; /* expected value of wParam */
141 LPARAM lParam
; /* expected value of lParam */
142 int line
; /* source line where logged */
143 const char *descr
; /* description for trace output */
144 char output
[512]; /* trace output */
147 /* Empty message sequence */
148 static const struct message WmEmptySeq
[] =
152 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
153 static const struct message WmCreateOverlappedSeq
[] = {
154 { HCBT_CREATEWND
, hook
},
155 { WM_GETMINMAXINFO
, sent
},
156 { WM_NCCREATE
, sent
},
157 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
158 { 0x0093, sent
|defwinproc
|optional
},
159 { 0x0094, sent
|defwinproc
|optional
},
160 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
162 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
165 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
166 * for a not visible overlapped window.
168 static const struct message WmSWP_ShowOverlappedSeq
[] = {
169 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
170 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
171 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
172 { WM_GETTEXT
, sent
|defwinproc
|optional
},
173 { WM_ERASEBKGND
, sent
|optional
},
174 { HCBT_ACTIVATE
, hook
},
175 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
176 { WM_NOTIFYFORMAT
, sent
|optional
},
177 { WM_QUERYUISTATE
, sent
|optional
},
178 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
179 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
180 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
181 { WM_NCACTIVATE
, sent
},
182 { WM_GETTEXT
, sent
|defwinproc
|optional
},
183 { WM_ACTIVATE
, sent
|wparam
, 1 },
184 { HCBT_SETFOCUS
, hook
},
185 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
186 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
187 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
188 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
189 { WM_GETTEXT
, sent
|optional
},
190 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
191 { WM_GETTEXT
, sent
|defwinproc
|optional
},
192 { WM_ERASEBKGND
, sent
|optional
},
193 /* Win9x adds SWP_NOZORDER below */
194 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
195 { WM_GETTEXT
, sent
|optional
},
196 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
197 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
198 { WM_ERASEBKGND
, sent
|optional
},
199 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
200 { WM_SYNCPAINT
, sent
|optional
},
201 { WM_GETTITLEBARINFOEX
, sent
|optional
},
202 { WM_PAINT
, sent
|optional
},
203 { WM_NCPAINT
, sent
|beginpaint
|optional
},
204 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
205 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
208 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
209 * for a visible overlapped window.
211 static const struct message WmSWP_HideOverlappedSeq
[] = {
212 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
213 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
214 { HCBT_ACTIVATE
, hook
|optional
},
215 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
216 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
217 { WM_NCACTIVATE
, sent
|optional
},
218 { WM_ACTIVATE
, sent
|optional
},
219 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
223 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
224 * for a visible overlapped window.
226 static const struct message WmSWP_ResizeSeq
[] = {
227 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
228 { WM_GETMINMAXINFO
, sent
|defwinproc
},
229 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
230 { WM_NCPAINT
, sent
|optional
},
231 { WM_GETTEXT
, sent
|defwinproc
|optional
},
232 { WM_ERASEBKGND
, sent
|optional
},
233 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
234 { WM_SIZE
, sent
|defwinproc
|optional
},
235 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
236 { WM_NCPAINT
, sent
|optional
},
237 { WM_GETTEXT
, sent
|defwinproc
|optional
},
238 { WM_ERASEBKGND
, sent
|optional
},
239 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
240 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
244 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
245 * for a visible popup window.
247 static const struct message WmSWP_ResizePopupSeq
[] = {
248 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
249 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* Win9x */
250 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
251 { WM_NCPAINT
, sent
|optional
},
252 { WM_GETTEXT
, sent
|defwinproc
|optional
},
253 { WM_ERASEBKGND
, sent
|optional
},
254 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
255 { WM_SIZE
, sent
|defwinproc
|wparam
|optional
, SIZE_RESTORED
},
256 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
257 { WM_NCPAINT
, sent
|optional
},
258 { WM_GETTEXT
, sent
|defwinproc
|optional
},
259 { WM_ERASEBKGND
, sent
|optional
},
260 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
264 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
265 * for a visible overlapped window.
267 static const struct message WmSWP_MoveSeq
[] = {
268 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
},
269 { WM_NCPAINT
, sent
|optional
},
270 { WM_GETTEXT
, sent
|defwinproc
|optional
},
271 { WM_ERASEBKGND
, sent
|optional
},
272 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
273 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
274 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
277 /* Resize with SetWindowPos(SWP_NOZORDER)
278 * for a visible overlapped window
279 * SWP_NOZORDER is stripped by the logging code
281 static const struct message WmSWP_ResizeNoZOrder
[] = {
282 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
},
283 { WM_GETMINMAXINFO
, sent
|defwinproc
},
284 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
285 { WM_NCPAINT
, sent
|optional
},
286 { WM_GETTEXT
, sent
|defwinproc
|optional
},
287 { WM_ERASEBKGND
, sent
|optional
},
288 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
, 0,
289 SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
290 { WM_MOVE
, sent
|defwinproc
|optional
},
291 { WM_SIZE
, sent
|defwinproc
|optional
},
292 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
293 { WM_NCPAINT
, sent
|optional
}, /* Win9x doesn't send it */
294 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
295 { WM_ERASEBKGND
, sent
|optional
}, /* Win9x doesn't send it */
296 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
297 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
301 /* Switch visible mdi children */
302 static const struct message WmSwitchChild
[] = {
303 /* Switch MDI child */
304 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
305 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 1st MDI child */
306 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
307 { WM_CHILDACTIVATE
, sent
},/* in the 1st MDI child */
308 /* Deactivate 2nd MDI child */
309 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
310 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
311 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
312 /* Preparing for maximize and maximize the 1st MDI child */
313 { WM_GETMINMAXINFO
, sent
|defwinproc
}, /* in the 1st MDI child */
314 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
}, /* in the 1st MDI child */
315 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
316 { WM_CHILDACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
317 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 1st MDI child */
318 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
}, /* in the 1st MDI child */
319 /* Lock redraw 2nd MDI child */
320 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
321 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
322 /* Restore 2nd MDI child */
323 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},/* in the 2nd MDI child */
324 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
325 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
326 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 2nd MDI child */
327 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
}, /* in the 2nd MDI child */
328 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
329 /* Redraw 2nd MDI child */
330 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
331 /* Redraw MDI frame */
332 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},/* in MDI frame */
333 { WM_NCCALCSIZE
, sent
|wparam
, 1 },/* in MDI frame */
334 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in MDI frame */
335 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in MDI frame */
336 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
337 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
338 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
339 { HCBT_SETFOCUS
, hook
},
340 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
341 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },/* in the 1st MDI child */
342 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
343 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
344 { WM_SETFOCUS
, sent
},/* in the MDI client */
345 { HCBT_SETFOCUS
, hook
},
346 { WM_KILLFOCUS
, sent
},/* in the MDI client */
347 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
348 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 }, /* in the 1st MDI child */
349 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
350 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
351 { WM_MDIACTIVATE
, sent
|defwinproc
},/* in the 1st MDI child */
352 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 1st MDI child */
356 /* Switch visible not maximized mdi children */
357 static const struct message WmSwitchNotMaximizedChild
[] = {
358 /* Switch not maximized MDI child */
359 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
360 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 2nd MDI child */
361 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
362 { WM_CHILDACTIVATE
, sent
},/* in the 2nd MDI child */
363 /* Deactivate 1st MDI child */
364 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
365 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
366 /* Activate 2nd MDI child */
367 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
}, /* in the 2nd MDI child */
368 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 2nd MDI child */
369 { HCBT_SETFOCUS
, hook
}, /* in the 1st MDI child */
370 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
371 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
372 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
373 { WM_SETFOCUS
, sent
, 0 }, /* in the MDI client */
374 { HCBT_SETFOCUS
, hook
},
375 { WM_KILLFOCUS
, sent
}, /* in the MDI client */
376 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
377 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
378 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
379 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
380 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 2nd MDI child */
385 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
386 SWP_NOZORDER|SWP_FRAMECHANGED)
387 * for a visible overlapped window with WS_CLIPCHILDREN style set.
389 static const struct message WmSWP_FrameChanged_clip
[] = {
390 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
391 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
392 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
393 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
394 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
395 { WM_NCPAINT
, sent
}, /* wparam != 1 */
396 { WM_ERASEBKGND
, sent
},
397 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
398 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
402 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
403 SWP_NOZORDER|SWP_FRAMECHANGED)
404 * for a visible overlapped window.
406 static const struct message WmSWP_FrameChangedDeferErase
[] = {
407 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
408 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
409 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
410 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
411 { WM_PAINT
, sent
|parent
|optional
},
412 { WM_NCPAINT
, sent
|beginpaint
|parent
|optional
}, /* wparam != 1 */
413 { WM_GETTEXT
, sent
|beginpaint
|parent
|defwinproc
|optional
},
415 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
416 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
420 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
421 SWP_NOZORDER|SWP_FRAMECHANGED)
422 * for a visible overlapped window without WS_CLIPCHILDREN style set.
424 static const struct message WmSWP_FrameChanged_noclip
[] = {
425 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
426 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
427 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
428 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
429 { WM_ERASEBKGND
, sent
|parent
|optional
},
430 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
431 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
433 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
434 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
438 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
439 static const struct message WmShowOverlappedSeq
[] = {
440 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
441 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
442 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
443 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
444 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
445 { WM_GETTEXT
, sent
|defwinproc
|optional
},
446 { WM_ERASEBKGND
, sent
|optional
},
447 { HCBT_ACTIVATE
, hook
|optional
},
448 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
449 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
450 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
451 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
452 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
453 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
454 { WM_GETTEXT
, sent
|defwinproc
|optional
},
455 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
456 { HCBT_SETFOCUS
, hook
|optional
},
457 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
458 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
459 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
460 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
461 { WM_GETTEXT
, sent
|optional
},
462 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
463 { WM_GETTEXT
, sent
|defwinproc
|optional
},
464 { WM_ERASEBKGND
, sent
|optional
},
465 /* Win9x adds SWP_NOZORDER below */
466 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
467 { WM_NCCALCSIZE
, sent
|optional
},
468 { WM_GETTEXT
, sent
|optional
},
469 { WM_NCPAINT
, sent
|optional
},
470 { WM_ERASEBKGND
, sent
|optional
},
471 { WM_SYNCPAINT
, sent
|optional
},
472 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
473 * messages. Does that mean that CreateWindow doesn't set initial
474 * window dimensions for overlapped windows?
479 { WM_PAINT
, sent
|optional
},
480 { WM_NCPAINT
, sent
|beginpaint
|optional
},
483 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
484 static const struct message WmShowMaxOverlappedSeq
[] = {
485 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
486 { WM_GETMINMAXINFO
, sent
},
487 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
488 { WM_GETMINMAXINFO
, sent
|defwinproc
},
489 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
490 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
491 { HCBT_ACTIVATE
, hook
|optional
},
492 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
493 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
494 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
495 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
496 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
497 { WM_GETTEXT
, sent
|defwinproc
|optional
},
498 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
499 { HCBT_SETFOCUS
, hook
|optional
},
500 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
501 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
502 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
503 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
504 { WM_GETTEXT
, sent
|optional
},
505 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
506 { WM_GETTEXT
, sent
|defwinproc
|optional
},
507 { WM_ERASEBKGND
, sent
|optional
},
508 /* Win9x adds SWP_NOZORDER below */
509 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
510 { WM_MOVE
, sent
|defwinproc
},
511 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
512 { WM_GETTEXT
, sent
|optional
},
513 { WM_NCCALCSIZE
, sent
|optional
},
514 { WM_NCPAINT
, sent
|optional
},
515 { WM_ERASEBKGND
, sent
|optional
},
516 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
517 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
518 { WM_SYNCPAINT
, sent
|optional
},
519 { WM_GETTITLEBARINFOEX
, sent
|optional
},
520 { WM_PAINT
, sent
|optional
},
521 { WM_NCPAINT
, sent
|beginpaint
|optional
},
522 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
525 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
526 static const struct message WmShowRestoreMaxOverlappedSeq
[] = {
527 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
528 { WM_GETTEXT
, sent
|optional
},
529 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
530 { WM_GETMINMAXINFO
, sent
|defwinproc
},
531 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
532 { WM_NCPAINT
, sent
|optional
},
533 { WM_GETTEXT
, sent
|defwinproc
|optional
},
534 { WM_ERASEBKGND
, sent
|optional
},
535 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
536 { WM_MOVE
, sent
|defwinproc
|optional
},
537 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
538 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
539 { WM_NCPAINT
, sent
|optional
},
540 { WM_ERASEBKGND
, sent
|optional
},
541 { WM_PAINT
, sent
|optional
},
542 { WM_GETTITLEBARINFOEX
, sent
|optional
},
543 { WM_NCPAINT
, sent
|beginpaint
|optional
},
544 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
547 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
548 static const struct message WmShowRestoreMinOverlappedSeq
[] = {
549 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
550 { WM_QUERYOPEN
, sent
|optional
},
551 { WM_GETTEXT
, sent
|optional
},
552 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
553 { WM_WINDOWPOSCHANGING
, sent
|optional
}, /* SWP_NOSIZE|SWP_NOMOVE */
554 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
555 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
556 { WM_MOVE
, sent
|optional
},
557 { WM_SIZE
, sent
|wparam
|optional
, SIZE_RESTORED
},
558 { WM_GETTEXT
, sent
|optional
},
559 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
|SWP_NOCOPYBITS
},
560 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
},
561 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
562 { HCBT_ACTIVATE
, hook
|optional
},
563 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
564 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
565 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
566 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
567 { WM_GETTEXT
, sent
|defwinproc
|optional
},
568 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
569 { HCBT_SETFOCUS
, hook
|optional
},
570 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
571 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
572 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
573 { WM_GETTEXT
, sent
|optional
},
574 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
575 { WM_GETTEXT
, sent
|defwinproc
|optional
},
576 { WM_ERASEBKGND
, sent
},
577 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_STATECHANGED
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
},
578 { WM_MOVE
, sent
|defwinproc
},
579 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
580 { HCBT_SETFOCUS
, hook
|optional
},
581 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
582 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
583 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
584 { WM_ERASEBKGND
, sent
|optional
},
585 { HCBT_SETFOCUS
, hook
|optional
},
586 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
587 { WM_ACTIVATE
, sent
|wparam
, 1 },
588 { WM_GETTEXT
, sent
|optional
},
589 { WM_PAINT
, sent
|optional
},
590 { WM_GETTITLEBARINFOEX
, sent
|optional
},
591 { WM_NCPAINT
, sent
|beginpaint
|optional
},
592 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
595 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
596 static const struct message WmShowMinOverlappedSeq
[] = {
597 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
598 { HCBT_SETFOCUS
, hook
|optional
},
599 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
600 { WM_KILLFOCUS
, sent
|optional
},
601 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
602 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
603 { WM_GETTEXT
, sent
|optional
},
604 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCOPYBITS
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
605 { WM_GETMINMAXINFO
, sent
|defwinproc
},
606 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
607 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
608 { WM_NCPAINT
, sent
|optional
},
609 { WM_GETTEXT
, sent
|defwinproc
|optional
},
610 { WM_WINDOWPOSCHANGED
, sent
},
611 { WM_MOVE
, sent
|defwinproc
},
612 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
613 { WM_NCCALCSIZE
, sent
|optional
},
614 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
615 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
616 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
617 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
618 { WM_GETTEXT
, sent
|defwinproc
|optional
},
619 { WM_ACTIVATE
, sent
|optional
},
620 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
622 /* Vista sometimes restores the window right away... */
623 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
624 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
625 { HCBT_MINMAX
, hook
|optional
|lparam
, 0, SW_RESTORE
},
626 { WM_QUERYOPEN
, sent
|optional
},
627 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
628 { WM_GETMINMAXINFO
, sent
|optional
|defwinproc
},
629 { WM_NCCALCSIZE
, sent
|optional
|wparam
, TRUE
},
630 { HCBT_ACTIVATE
, hook
|optional
},
631 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 1 },
632 { WM_NCACTIVATE
, sent
|optional
},
633 { WM_GETTEXT
, sent
|optional
},
634 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
635 { HCBT_SETFOCUS
, hook
|optional
},
636 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
637 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
638 { WM_SETFOCUS
, sent
|optional
},
639 { WM_NCPAINT
, sent
|optional
},
640 { WM_GETTEXT
, sent
|defwinproc
|optional
},
641 { WM_ERASEBKGND
, sent
|optional
},
642 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
643 { WM_MOVE
, sent
|defwinproc
|optional
},
644 { WM_SIZE
, sent
|defwinproc
|optional
|wparam
, SIZE_RESTORED
},
645 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
646 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
647 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
649 { WM_PAINT
, sent
|optional
},
650 { WM_NCPAINT
, sent
|beginpaint
|optional
},
651 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
654 /* ShowWindow(SW_HIDE) for a visible overlapped window */
655 static const struct message WmHideOverlappedSeq
[] = {
656 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
657 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
658 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
659 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
660 { WM_SIZE
, sent
|optional
}, /* XP doesn't send it */
661 { WM_MOVE
, sent
|optional
}, /* XP doesn't send it */
662 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
663 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
664 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
665 { HCBT_SETFOCUS
, hook
|optional
},
666 { WM_KILLFOCUS
, sent
|wparam
|optional
, 0 },
667 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
668 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
671 /* DestroyWindow for a visible overlapped window */
672 static const struct message WmDestroyOverlappedSeq
[] = {
673 { HCBT_DESTROYWND
, hook
},
674 { 0x0090, sent
|optional
},
675 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
676 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
677 { 0x0090, sent
|optional
},
678 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
679 { WM_NCACTIVATE
, sent
|optional
|wparam
, 0 },
680 { WM_ACTIVATE
, sent
|optional
},
681 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 0 },
682 { WM_KILLFOCUS
, sent
|optional
|wparam
, 0 },
683 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
684 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
685 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
686 { WM_DESTROY
, sent
},
687 { WM_NCDESTROY
, sent
},
690 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
691 static const struct message WmCreateMaxPopupSeq
[] = {
692 { HCBT_CREATEWND
, hook
},
693 { WM_NCCREATE
, sent
},
694 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
696 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
697 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
699 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
700 { WM_GETMINMAXINFO
, sent
},
701 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
702 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
703 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
704 { WM_MOVE
, sent
|defwinproc
},
705 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
706 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
707 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
708 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
709 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
710 { HCBT_ACTIVATE
, hook
},
711 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
712 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
713 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
714 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
715 { WM_ERASEBKGND
, sent
|optional
},
716 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_NOMOVE
|SWP_NOSIZE
},
717 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
718 { WM_NCACTIVATE
, sent
},
719 { WM_ACTIVATE
, sent
|wparam
, 1 },
720 { HCBT_SETFOCUS
, hook
},
721 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
722 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
723 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
724 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
725 { WM_GETTEXT
, sent
|optional
},
726 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
727 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
728 { WM_ERASEBKGND
, sent
|optional
},
729 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
730 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
731 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
734 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
735 static const struct message WmCreateInvisibleMaxPopupSeq
[] = {
736 { HCBT_CREATEWND
, hook
},
737 { WM_NCCREATE
, sent
},
738 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
740 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
741 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
743 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
744 { WM_GETMINMAXINFO
, sent
},
745 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
746 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
747 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
748 { WM_MOVE
, sent
|defwinproc
},
749 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
750 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
753 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
754 static const struct message WmShowMaxPopupResizedSeq
[] = {
755 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
756 { WM_GETMINMAXINFO
, sent
},
757 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
758 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
759 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
760 { HCBT_ACTIVATE
, hook
},
761 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
762 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
763 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
764 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
765 { WM_ERASEBKGND
, sent
|optional
},
766 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
767 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
768 { WM_NCACTIVATE
, sent
},
769 { WM_ACTIVATE
, sent
|wparam
, 1 },
770 { HCBT_SETFOCUS
, hook
},
771 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
772 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
773 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
774 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
775 { WM_GETTEXT
, sent
|optional
},
776 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
777 { WM_ERASEBKGND
, sent
|optional
},
778 { WM_WINDOWPOSCHANGED
, sent
},
779 /* WinNT4.0 sends WM_MOVE */
780 { WM_MOVE
, sent
|defwinproc
|optional
},
781 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
782 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
785 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
786 static const struct message WmShowMaxPopupSeq
[] = {
787 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
788 { WM_GETMINMAXINFO
, sent
},
789 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
790 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
791 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
792 { HCBT_ACTIVATE
, hook
},
793 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
794 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
795 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
796 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
797 { WM_NCACTIVATE
, sent
},
798 { WM_ACTIVATE
, sent
|wparam
, 1 },
799 { HCBT_SETFOCUS
, hook
},
800 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
801 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
802 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
803 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
804 { WM_GETTEXT
, sent
|optional
},
805 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
806 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
807 { WM_ERASEBKGND
, sent
|optional
},
808 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
809 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
810 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
},
811 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
814 /* CreateWindow(WS_VISIBLE) for popup window */
815 static const struct message WmCreatePopupSeq
[] = {
816 { HCBT_CREATEWND
, hook
},
817 { WM_NCCREATE
, sent
},
818 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
820 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
821 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
823 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
824 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
825 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
826 { HCBT_ACTIVATE
, hook
},
827 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
828 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
829 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
830 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
831 { WM_ERASEBKGND
, sent
|optional
},
832 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
833 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
834 { WM_NCACTIVATE
, sent
},
835 { WM_ACTIVATE
, sent
|wparam
, 1 },
836 { HCBT_SETFOCUS
, hook
},
837 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
838 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
839 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
840 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
841 { WM_GETTEXT
, sent
|optional
},
842 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
843 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
844 { WM_ERASEBKGND
, sent
|optional
},
845 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
848 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
849 static const struct message WmShowVisMaxPopupSeq
[] = {
850 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
851 { WM_GETMINMAXINFO
, sent
},
852 { WM_GETTEXT
, sent
|optional
},
853 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
854 { WM_GETTEXT
, sent
|optional
},
855 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
856 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
857 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
858 { WM_ERASEBKGND
, sent
|optional
},
859 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
860 { WM_MOVE
, sent
|defwinproc
},
861 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
862 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
865 /* CreateWindow (for a child popup window, not initially visible) */
866 static const struct message WmCreateChildPopupSeq
[] = {
867 { HCBT_CREATEWND
, hook
},
868 { WM_NCCREATE
, sent
},
869 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
871 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
872 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
876 /* CreateWindow (for a popup window, not initially visible,
877 * which sets WS_VISIBLE in WM_CREATE handler)
879 static const struct message WmCreateInvisiblePopupSeq
[] = {
880 { HCBT_CREATEWND
, hook
},
881 { WM_NCCREATE
, sent
},
882 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
884 { WM_STYLECHANGING
, sent
},
885 { WM_STYLECHANGED
, sent
},
886 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
887 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
891 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
892 * for a popup window with WS_VISIBLE style set
894 static const struct message WmShowVisiblePopupSeq_2
[] = {
895 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
898 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
899 * for a popup window with WS_VISIBLE style set
901 static const struct message WmShowVisiblePopupSeq_3
[] = {
902 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
903 { HCBT_ACTIVATE
, hook
},
904 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
905 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
906 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
907 { WM_NCACTIVATE
, sent
},
908 { WM_ACTIVATE
, sent
|wparam
, 1 },
909 { HCBT_SETFOCUS
, hook
},
910 { WM_KILLFOCUS
, sent
|parent
},
911 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
912 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
913 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
914 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
915 { WM_SETFOCUS
, sent
|defwinproc
},
916 { WM_GETTEXT
, sent
|optional
},
917 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_SHOWWINDOW
},
920 /* CreateWindow (for child window, not initially visible) */
921 static const struct message WmCreateChildSeq
[] = {
922 { HCBT_CREATEWND
, hook
},
923 { WM_NCCREATE
, sent
},
924 /* child is inserted into parent's child list after WM_NCCREATE returns */
925 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
927 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
928 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
930 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
933 /* CreateWindow (for maximized child window, not initially visible) */
934 static const struct message WmCreateMaximizedChildSeq
[] = {
935 { HCBT_CREATEWND
, hook
},
936 { WM_NCCREATE
, sent
},
937 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
939 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
940 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
942 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
943 { WM_GETMINMAXINFO
, sent
},
944 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
945 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
946 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
947 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
948 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
949 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
952 /* CreateWindow (for a child window, initially visible) */
953 static const struct message WmCreateVisibleChildSeq
[] = {
954 { HCBT_CREATEWND
, hook
},
955 { WM_NCCREATE
, sent
},
956 /* child is inserted into parent's child list after WM_NCCREATE returns */
957 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
958 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
960 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
961 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
963 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
964 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
965 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
966 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
967 { WM_ERASEBKGND
, sent
|parent
|optional
},
968 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
969 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
970 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
973 /* ShowWindow(SW_SHOW) for a not visible child window */
974 static const struct message WmShowChildSeq
[] = {
975 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
976 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
977 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
978 { WM_ERASEBKGND
, sent
|parent
|optional
},
979 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
982 /* ShowWindow(SW_HIDE) for a visible child window */
983 static const struct message WmHideChildSeq
[] = {
984 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
985 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
986 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
987 { WM_ERASEBKGND
, sent
|parent
|optional
},
988 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
991 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
992 static const struct message WmHideChildSeq2
[] = {
993 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
994 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
995 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
996 { WM_ERASEBKGND
, sent
|parent
|optional
},
997 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1000 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1001 * for a not visible child window
1003 static const struct message WmShowChildSeq_2
[] = {
1004 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1005 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1006 { WM_CHILDACTIVATE
, sent
},
1007 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1010 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1011 * for a not visible child window
1013 static const struct message WmShowChildSeq_3
[] = {
1014 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1015 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1016 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1019 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1020 * for a visible child window with a caption
1022 static const struct message WmShowChildSeq_4
[] = {
1023 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1024 { WM_CHILDACTIVATE
, sent
},
1027 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1028 static const struct message WmShowChildInvisibleParentSeq_1
[] = {
1029 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1030 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1031 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1032 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1033 { WM_CHILDACTIVATE
, sent
|optional
},
1034 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1035 { WM_MOVE
, sent
|defwinproc
},
1036 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1037 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1038 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1039 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1040 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1041 { WM_GETTEXT
, sent
|optional
},
1044 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1045 static const struct message WmShowChildInvisibleParentSeq_1r
[] = {
1046 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1049 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1050 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
1051 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1052 { WM_GETMINMAXINFO
, sent
},
1053 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
1054 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1055 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1056 { WM_CHILDACTIVATE
, sent
},
1057 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1058 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1059 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1062 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1063 static const struct message WmShowChildInvisibleParentSeq_2r
[] = {
1064 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1067 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1068 static const struct message WmShowChildInvisibleParentSeq_3
[] = {
1069 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1070 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1071 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1072 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1073 { WM_CHILDACTIVATE
, sent
},
1074 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1075 { WM_MOVE
, sent
|defwinproc
},
1076 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1077 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1078 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1079 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1080 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1081 { WM_GETTEXT
, sent
|optional
},
1084 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1085 static const struct message WmShowChildInvisibleParentSeq_3r
[] = {
1086 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1089 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1090 static const struct message WmShowChildInvisibleParentSeq_4
[] = {
1091 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1092 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1093 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1094 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1095 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1096 { WM_MOVE
, sent
|defwinproc
},
1097 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1098 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1099 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1100 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1101 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1102 { WM_GETTEXT
, sent
|optional
},
1105 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1106 static const struct message WmShowChildInvisibleParentSeq_4r
[] = {
1107 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1110 /* ShowWindow(SW_SHOW) for child with invisible parent */
1111 static const struct message WmShowChildInvisibleParentSeq_5
[] = {
1112 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1115 /* ShowWindow(SW_HIDE) for child with invisible parent */
1116 static const struct message WmHideChildInvisibleParentSeq
[] = {
1117 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1120 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1121 static const struct message WmShowChildInvisibleParentSeq_6
[] = {
1122 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1123 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1124 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1127 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1128 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
1129 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1130 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1131 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1134 /* DestroyWindow for a visible child window */
1135 static const struct message WmDestroyChildSeq
[] = {
1136 { HCBT_DESTROYWND
, hook
},
1137 { 0x0090, sent
|optional
},
1138 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1139 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1140 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1141 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1142 { WM_ERASEBKGND
, sent
|parent
|optional
},
1143 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1144 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
1145 { WM_KILLFOCUS
, sent
},
1146 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1147 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
1148 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1149 { WM_SETFOCUS
, sent
|parent
},
1150 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1151 { WM_DESTROY
, sent
},
1152 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
1153 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
1154 { WM_NCDESTROY
, sent
},
1157 /* visible child window destroyed by thread exit */
1158 static const struct message WmExitThreadSeq
[] = {
1159 { WM_NCDESTROY
, sent
}, /* actually in grandchild */
1160 { WM_PAINT
, sent
|parent
},
1161 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
1164 /* DestroyWindow for a visible child window with invisible parent */
1165 static const struct message WmDestroyInvisibleChildSeq
[] = {
1166 { HCBT_DESTROYWND
, hook
},
1167 { 0x0090, sent
|optional
},
1168 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1169 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1170 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1171 { WM_DESTROY
, sent
},
1172 { WM_NCDESTROY
, sent
},
1175 /* Moving the mouse in nonclient area */
1176 static const struct message WmMouseMoveInNonClientAreaSeq
[] = { /* FIXME: add */
1177 { WM_NCHITTEST
, sent
},
1178 { WM_SETCURSOR
, sent
},
1179 { WM_NCMOUSEMOVE
, posted
},
1182 /* Moving the mouse in client area */
1183 static const struct message WmMouseMoveInClientAreaSeq
[] = { /* FIXME: add */
1184 { WM_NCHITTEST
, sent
},
1185 { WM_SETCURSOR
, sent
},
1186 { WM_MOUSEMOVE
, posted
},
1189 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
1190 static const struct message WmDragTitleBarSeq
[] = { /* FIXME: add */
1191 { WM_NCLBUTTONDOWN
, sent
|wparam
, HTCAPTION
},
1192 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_MOVE
+2 },
1193 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1194 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
1195 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
1196 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
1197 { WM_MOVE
, sent
|defwinproc
},
1198 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
1201 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
1202 static const struct message WmDragThickBordersBarSeq
[] = { /* FIXME: add */
1203 { WM_NCLBUTTONDOWN
, sent
|wparam
, 0xd },
1204 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, 0xf004 },
1205 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1206 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
1207 { WM_SIZING
, sent
|defwinproc
|wparam
, 4}, /* one for each mouse movement */
1208 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
1209 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1210 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1211 { WM_NCPAINT
, sent
|defwinproc
|wparam
, 1 },
1212 { WM_GETTEXT
, sent
|defwinproc
},
1213 { WM_ERASEBKGND
, sent
|defwinproc
},
1214 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
1215 { WM_MOVE
, sent
|defwinproc
},
1216 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1217 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
1220 /* Resizing child window with MoveWindow (32) */
1221 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1222 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1223 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1224 { WM_ERASEBKGND
, sent
|parent
|optional
},
1225 { WM_ERASEBKGND
, sent
|optional
},
1226 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1227 { WM_MOVE
, sent
|defwinproc
},
1228 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1229 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1232 /* Clicking on inactive button */
1233 static const struct message WmClickInactiveButtonSeq
[] = { /* FIXME: add */
1234 { WM_NCHITTEST
, sent
},
1235 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_LBUTTONDOWN
},
1236 { WM_MOUSEACTIVATE
, sent
},
1237 { WM_MOUSEACTIVATE
, sent
|parent
|defwinproc
},
1238 { WM_SETCURSOR
, sent
},
1239 { WM_SETCURSOR
, sent
|parent
|defwinproc
},
1240 { WM_LBUTTONDOWN
, posted
},
1241 { WM_KILLFOCUS
, posted
|parent
},
1242 { WM_SETFOCUS
, posted
},
1243 { WM_CTLCOLORBTN
, posted
|parent
},
1244 { BM_SETSTATE
, posted
},
1245 { WM_CTLCOLORBTN
, posted
|parent
},
1246 { WM_LBUTTONUP
, posted
},
1247 { BM_SETSTATE
, posted
},
1248 { WM_CTLCOLORBTN
, posted
|parent
},
1249 { WM_COMMAND
, posted
|parent
},
1252 /* Reparenting a button (16/32) */
1253 /* The last child (button) reparented gets topmost for its new parent. */
1254 static const struct message WmReparentButtonSeq
[] = { /* FIXME: add */
1255 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1256 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1257 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1258 { WM_ERASEBKGND
, sent
|parent
},
1259 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1260 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
1261 { WM_CHILDACTIVATE
, sent
},
1262 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
},
1263 { WM_MOVE
, sent
|defwinproc
},
1264 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1267 /* Creation of a custom dialog (32) */
1268 static const struct message WmCreateCustomDialogSeq
[] = {
1269 { HCBT_CREATEWND
, hook
},
1270 { WM_GETMINMAXINFO
, sent
},
1271 { WM_NCCREATE
, sent
},
1272 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1273 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1274 { WM_CREATE
, sent
},
1275 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1276 { WM_NOTIFYFORMAT
, sent
|optional
},
1277 { WM_QUERYUISTATE
, sent
|optional
},
1278 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1279 { WM_GETMINMAXINFO
, sent
|optional
},
1280 { WM_NCCALCSIZE
, sent
|optional
},
1281 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1282 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1283 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1284 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1285 { HCBT_ACTIVATE
, hook
},
1286 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1289 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1291 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1293 { WM_NCACTIVATE
, sent
},
1294 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1295 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1296 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1297 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1298 { WM_ACTIVATE
, sent
|wparam
, 1 },
1299 { WM_GETTEXT
, sent
|optional
},
1300 { WM_KILLFOCUS
, sent
|parent
},
1301 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1302 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1303 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1304 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1305 { WM_SETFOCUS
, sent
},
1306 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1307 { WM_NCPAINT
, sent
|wparam
, 1 },
1308 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1309 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1310 { WM_ERASEBKGND
, sent
},
1311 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1312 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1313 { WM_GETTEXT
, sent
|optional
},
1314 { WM_GETTEXT
, sent
|optional
},
1315 { WM_NCCALCSIZE
, sent
|optional
},
1316 { WM_NCPAINT
, sent
|optional
},
1317 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1318 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1319 { WM_ERASEBKGND
, sent
|optional
},
1320 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1321 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1322 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1326 /* Calling EndDialog for a custom dialog (32) */
1327 static const struct message WmEndCustomDialogSeq
[] = {
1328 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1329 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1330 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1331 { WM_GETTEXT
, sent
|optional
},
1332 { HCBT_ACTIVATE
, hook
},
1333 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1334 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1335 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1336 { WM_ACTIVATE
, sent
|wparam
, 0 },
1337 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1338 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1339 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1340 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1341 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1342 { HCBT_SETFOCUS
, hook
},
1343 { WM_KILLFOCUS
, sent
},
1344 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1345 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1346 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1347 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1348 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1351 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1352 static const struct message WmShowCustomDialogSeq
[] = {
1353 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1354 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1355 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1356 { HCBT_ACTIVATE
, hook
},
1357 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1359 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1361 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1362 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1363 { WM_NCACTIVATE
, sent
},
1364 { WM_ACTIVATE
, sent
|wparam
, 1 },
1365 { WM_GETTEXT
, sent
|optional
},
1367 { WM_KILLFOCUS
, sent
|parent
},
1368 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1369 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1370 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1371 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1372 { WM_SETFOCUS
, sent
},
1373 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1374 { WM_NCPAINT
, sent
|wparam
, 1 },
1375 { WM_ERASEBKGND
, sent
},
1376 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1377 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1380 /* Creation and destruction of a modal dialog (32) */
1381 static const struct message WmModalDialogSeq
[] = {
1382 { WM_CANCELMODE
, sent
|parent
},
1383 { HCBT_SETFOCUS
, hook
},
1384 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1385 { WM_KILLFOCUS
, sent
|parent
},
1386 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1387 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1388 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1389 { HCBT_CREATEWND
, hook
},
1390 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1391 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1392 { WM_SETFONT
, sent
},
1393 { WM_INITDIALOG
, sent
},
1394 { WM_CHANGEUISTATE
, sent
|optional
},
1395 { WM_UPDATEUISTATE
, sent
|optional
},
1396 { WM_SHOWWINDOW
, sent
},
1397 { HCBT_ACTIVATE
, hook
},
1398 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1399 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1400 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1401 { WM_NCACTIVATE
, sent
},
1402 { WM_GETTEXT
, sent
|optional
},
1403 { WM_ACTIVATE
, sent
|wparam
, 1 },
1404 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1405 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1406 { WM_NCPAINT
, sent
|optional
},
1407 { WM_GETTEXT
, sent
|optional
},
1408 { WM_ERASEBKGND
, sent
|optional
},
1409 { WM_CTLCOLORDLG
, sent
|optional
},
1410 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1411 { WM_GETTEXT
, sent
|optional
},
1412 { WM_NCCALCSIZE
, sent
|optional
},
1413 { WM_NCPAINT
, sent
|optional
},
1414 { WM_GETTEXT
, sent
|optional
},
1415 { WM_ERASEBKGND
, sent
|optional
},
1416 { WM_CTLCOLORDLG
, sent
|optional
},
1417 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1418 { WM_PAINT
, sent
|optional
},
1419 { WM_CTLCOLORBTN
, sent
|optional
},
1420 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1421 { WM_ENTERIDLE
, sent
|parent
|optional
},
1422 { WM_ENTERIDLE
, sent
|parent
|optional
},
1423 { WM_ENTERIDLE
, sent
|parent
|optional
},
1424 { WM_ENTERIDLE
, sent
|parent
|optional
},
1425 { WM_ENTERIDLE
, sent
|parent
|optional
},
1426 { WM_ENTERIDLE
, sent
|parent
|optional
},
1427 { WM_ENTERIDLE
, sent
|parent
|optional
},
1428 { WM_ENTERIDLE
, sent
|parent
|optional
},
1429 { WM_ENTERIDLE
, sent
|parent
|optional
},
1430 { WM_ENTERIDLE
, sent
|parent
|optional
},
1431 { WM_ENTERIDLE
, sent
|parent
|optional
},
1432 { WM_ENTERIDLE
, sent
|parent
|optional
},
1433 { WM_ENTERIDLE
, sent
|parent
|optional
},
1434 { WM_ENTERIDLE
, sent
|parent
|optional
},
1435 { WM_ENTERIDLE
, sent
|parent
|optional
},
1436 { WM_ENTERIDLE
, sent
|parent
|optional
},
1437 { WM_ENTERIDLE
, sent
|parent
|optional
},
1438 { WM_ENTERIDLE
, sent
|parent
|optional
},
1439 { WM_ENTERIDLE
, sent
|parent
|optional
},
1440 { WM_ENTERIDLE
, sent
|parent
|optional
},
1442 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1443 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1444 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1445 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1446 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1447 { WM_GETTEXT
, sent
|optional
},
1448 { HCBT_ACTIVATE
, hook
},
1449 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1450 { WM_GETTEXT
, sent
|optional
},
1451 { WM_ACTIVATE
, sent
|wparam
, 0 },
1452 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1453 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1454 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1455 { HCBT_SETFOCUS
, hook
},
1456 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1457 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1458 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1459 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1460 { HCBT_DESTROYWND
, hook
},
1461 { 0x0090, sent
|optional
},
1462 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1463 { WM_DESTROY
, sent
},
1464 { WM_NCDESTROY
, sent
},
1467 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
1468 static const struct message WmCreateModalDialogResizeSeq
[] = { /* FIXME: add */
1469 /* (inside dialog proc, handling WM_INITDIALOG) */
1470 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
1471 { WM_NCCALCSIZE
, sent
},
1472 { WM_NCACTIVATE
, sent
|parent
|wparam
, 0 },
1473 { WM_GETTEXT
, sent
|defwinproc
},
1474 { WM_ACTIVATE
, sent
|parent
|wparam
, 0 },
1475 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
1476 { WM_WINDOWPOSCHANGING
, sent
|parent
},
1477 { WM_NCACTIVATE
, sent
|wparam
, 1 },
1478 { WM_ACTIVATE
, sent
|wparam
, 1 },
1479 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
1480 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1481 /* (setting focus) */
1482 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1483 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
1484 { WM_NCPAINT
, sent
},
1485 { WM_GETTEXT
, sent
|defwinproc
},
1486 { WM_ERASEBKGND
, sent
},
1487 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1488 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
1490 /* (bunch of WM_CTLCOLOR* for each control) */
1491 { WM_PAINT
, sent
|parent
},
1492 { WM_ENTERIDLE
, sent
|parent
|wparam
, 0 },
1493 { WM_SETCURSOR
, sent
|parent
},
1496 /* SetMenu for NonVisible windows with size change*/
1497 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1498 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1499 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1500 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1501 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1502 { WM_MOVE
, sent
|defwinproc
},
1503 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1504 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1505 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1506 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1507 { WM_GETTEXT
, sent
|optional
},
1508 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1511 /* SetMenu for NonVisible windows with no size change */
1512 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1513 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1514 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1515 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1516 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1519 /* SetMenu for Visible windows with size change */
1520 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1521 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1522 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1523 { 0x0093, sent
|defwinproc
|optional
},
1524 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1525 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1526 { 0x0093, sent
|defwinproc
|optional
},
1527 { 0x0093, sent
|defwinproc
|optional
},
1528 { 0x0091, sent
|defwinproc
|optional
},
1529 { 0x0092, sent
|defwinproc
|optional
},
1530 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1531 { WM_ERASEBKGND
, sent
|optional
},
1532 { WM_ACTIVATE
, sent
|optional
},
1533 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1534 { WM_MOVE
, sent
|defwinproc
},
1535 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1536 { 0x0093, sent
|optional
},
1537 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1538 { 0x0093, sent
|defwinproc
|optional
},
1539 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1540 { 0x0093, sent
|defwinproc
|optional
},
1541 { 0x0093, sent
|defwinproc
|optional
},
1542 { 0x0091, sent
|defwinproc
|optional
},
1543 { 0x0092, sent
|defwinproc
|optional
},
1544 { WM_ERASEBKGND
, sent
|optional
},
1545 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1546 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1549 /* SetMenu for Visible windows with no size change */
1550 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1551 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1552 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1553 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1554 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1555 { WM_ERASEBKGND
, sent
|optional
},
1556 { WM_ACTIVATE
, sent
|optional
},
1557 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1558 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1561 /* DrawMenuBar for a visible window */
1562 static const struct message WmDrawMenuBarSeq
[] =
1564 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1565 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1566 { 0x0093, sent
|defwinproc
|optional
},
1567 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1568 { 0x0093, sent
|defwinproc
|optional
},
1569 { 0x0093, sent
|defwinproc
|optional
},
1570 { 0x0091, sent
|defwinproc
|optional
},
1571 { 0x0092, sent
|defwinproc
|optional
},
1572 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1573 { WM_ERASEBKGND
, sent
|optional
},
1574 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1575 { 0x0093, sent
|optional
},
1576 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1580 static const struct message WmSetRedrawFalseSeq
[] =
1582 { WM_SETREDRAW
, sent
|wparam
, 0 },
1586 static const struct message WmSetRedrawTrueSeq
[] =
1588 { WM_SETREDRAW
, sent
|wparam
, 1 },
1592 static const struct message WmEnableWindowSeq_1
[] =
1594 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1595 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1596 { HCBT_SETFOCUS
, hook
|optional
},
1597 { WM_KILLFOCUS
, sent
|optional
},
1598 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
1602 static const struct message WmEnableWindowSeq_2
[] =
1604 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1605 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
1609 static const struct message WmGetScrollRangeSeq
[] =
1611 { SBM_GETRANGE
, sent
},
1614 static const struct message WmGetScrollInfoSeq
[] =
1616 { SBM_GETSCROLLINFO
, sent
},
1619 static const struct message WmSetScrollRangeSeq
[] =
1621 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1622 sends SBM_SETSCROLLINFO.
1624 { SBM_SETSCROLLINFO
, sent
},
1627 /* SetScrollRange for a window without a non-client area */
1628 static const struct message WmSetScrollRangeHSeq_empty
[] =
1630 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 0 },
1633 static const struct message WmSetScrollRangeVSeq_empty
[] =
1635 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 0 },
1638 static const struct message WmSetScrollRangeHVSeq
[] =
1640 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1641 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1642 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1643 { WM_ERASEBKGND
, sent
|optional
},
1644 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1645 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1646 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1649 /* SetScrollRange for a window with a non-client area */
1650 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
1652 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1653 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1654 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1655 { WM_NCPAINT
, sent
|optional
},
1656 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1657 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1658 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1659 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1660 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1661 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1662 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1663 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1664 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1665 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1666 { WM_ERASEBKGND
, sent
|optional
},
1667 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
1668 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
1669 { WM_SIZE
, sent
|defwinproc
|optional
},
1670 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1671 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1672 { WM_GETTEXT
, sent
|optional
},
1673 { WM_GETTEXT
, sent
|optional
},
1674 { WM_GETTEXT
, sent
|optional
},
1675 { WM_GETTEXT
, sent
|optional
},
1678 /* test if we receive the right sequence of messages */
1679 /* after calling ShowWindow( SW_SHOWNA) */
1680 static const struct message WmSHOWNAChildInvisParInvis
[] = {
1681 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1684 static const struct message WmSHOWNAChildVisParInvis
[] = {
1685 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1688 static const struct message WmSHOWNAChildVisParVis
[] = {
1689 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1690 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1693 static const struct message WmSHOWNAChildInvisParVis
[] = {
1694 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1695 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1696 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1697 { WM_ERASEBKGND
, sent
|optional
},
1698 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
1701 static const struct message WmSHOWNATopVisible
[] = {
1702 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1703 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1704 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1705 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1706 { WM_ERASEBKGND
, sent
|optional
},
1707 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1710 static const struct message WmSHOWNATopInvisible
[] = {
1711 { WM_NOTIFYFORMAT
, sent
|optional
},
1712 { WM_QUERYUISTATE
, sent
|optional
},
1713 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1714 { WM_GETMINMAXINFO
, sent
|optional
},
1715 { WM_NCCALCSIZE
, sent
|optional
},
1716 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1717 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1718 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1719 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1720 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1721 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1722 { WM_ERASEBKGND
, sent
|optional
},
1723 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1724 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1725 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1726 { WM_ERASEBKGND
, sent
|optional
},
1727 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1728 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1733 static const struct message WmTrackPopupMenu
[] = {
1734 { HCBT_CREATEWND
, hook
},
1735 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1736 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1737 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1738 { 0x0093, sent
|optional
},
1739 { 0x0094, sent
|optional
},
1740 { 0x0094, sent
|optional
},
1741 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1742 { WM_CAPTURECHANGED
, sent
},
1743 { HCBT_DESTROYWND
, hook
},
1744 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1745 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1746 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1750 static const struct message WmTrackPopupMenuCapture
[] = {
1751 { HCBT_CREATEWND
, hook
},
1752 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1753 { WM_CAPTURECHANGED
, sent
},
1754 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1755 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1756 { 0x0093, sent
|optional
},
1757 { 0x0094, sent
|optional
},
1758 { 0x0094, sent
|optional
},
1759 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1760 { WM_CAPTURECHANGED
, sent
},
1761 { HCBT_DESTROYWND
, hook
},
1762 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1763 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1764 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1768 static const struct message WmTrackPopupMenuEmpty
[] = {
1769 { HCBT_CREATEWND
, hook
},
1770 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1771 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1772 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1773 { 0x0093, sent
|optional
},
1774 { 0x0094, sent
|optional
},
1775 { 0x0094, sent
|optional
},
1776 { WM_CAPTURECHANGED
, sent
},
1777 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1778 { HCBT_DESTROYWND
, hook
},
1779 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1783 static const struct message WmTrackPopupMenuAbort
[] = {
1784 { HCBT_CREATEWND
, hook
},
1785 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1786 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1787 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1788 { 0x0093, sent
|optional
},
1789 { 0x0094, sent
|optional
},
1790 { 0x0094, sent
|optional
},
1791 { WM_CAPTURECHANGED
, sent
},
1792 { HCBT_DESTROYWND
, hook
},
1793 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1794 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1795 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1799 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
1800 static int sequence_cnt
, sequence_size
;
1801 static struct recvd_message
* sequence
;
1802 static int log_all_parent_messages
;
1803 static CRITICAL_SECTION sequence_cs
;
1805 /* user32 functions */
1806 static HWND (WINAPI
*pGetAncestor
)(HWND
,UINT
);
1807 static BOOL (WINAPI
*pGetMenuInfo
)(HMENU
,LPCMENUINFO
);
1808 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
1809 static BOOL (WINAPI
*pSetMenuInfo
)(HMENU
,LPCMENUINFO
);
1810 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
1811 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
1812 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
1813 static BOOL (WINAPI
*pGetMonitorInfoA
)(HMONITOR
,LPMONITORINFO
);
1814 static HMONITOR (WINAPI
*pMonitorFromPoint
)(POINT
,DWORD
);
1815 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
1816 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
1817 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
1818 /* kernel32 functions */
1819 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
1821 static void init_procs(void)
1823 HMODULE user32
= GetModuleHandleA("user32.dll");
1824 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
1826 #define GET_PROC(dll, func) \
1827 p ## func = (void*)GetProcAddress(dll, #func); \
1829 trace("GetProcAddress(%s) failed\n", #func); \
1832 GET_PROC(user32
, GetAncestor
)
1833 GET_PROC(user32
, GetMenuInfo
)
1834 GET_PROC(user32
, NotifyWinEvent
)
1835 GET_PROC(user32
, SetMenuInfo
)
1836 GET_PROC(user32
, SetWinEventHook
)
1837 GET_PROC(user32
, TrackMouseEvent
)
1838 GET_PROC(user32
, UnhookWinEvent
)
1839 GET_PROC(user32
, GetMonitorInfoA
)
1840 GET_PROC(user32
, MonitorFromPoint
)
1841 GET_PROC(user32
, UpdateLayeredWindow
)
1842 GET_PROC(user32
, SetSystemTimer
)
1843 GET_PROC(user32
, KillSystemTimer
)
1845 GET_PROC(kernel32
, GetCPInfoExA
)
1850 static const char *get_winpos_flags(UINT flags
)
1852 static char buffer
[300];
1855 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
1856 DUMP( SWP_SHOWWINDOW
);
1857 DUMP( SWP_HIDEWINDOW
);
1858 DUMP( SWP_NOACTIVATE
);
1859 DUMP( SWP_FRAMECHANGED
);
1860 DUMP( SWP_NOCOPYBITS
);
1861 DUMP( SWP_NOOWNERZORDER
);
1862 DUMP( SWP_NOSENDCHANGING
);
1863 DUMP( SWP_DEFERERASE
);
1864 DUMP( SWP_ASYNCWINDOWPOS
);
1865 DUMP( SWP_NOZORDER
);
1866 DUMP( SWP_NOREDRAW
);
1869 DUMP( SWP_NOCLIENTSIZE
);
1870 DUMP( SWP_NOCLIENTMOVE
);
1871 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
1876 static BOOL
ignore_message( UINT message
)
1878 /* these are always ignored */
1879 return (message
>= 0xc000 ||
1880 message
== WM_GETICON
||
1881 message
== WM_GETOBJECT
||
1882 message
== WM_TIMECHANGE
||
1883 message
== WM_DISPLAYCHANGE
||
1884 message
== WM_DEVICECHANGE
||
1885 message
== WM_DWMNCRENDERINGCHANGED
);
1889 #define add_message(msg) add_message_(__LINE__,msg);
1890 static void add_message_(int line
, const struct recvd_message
*msg
)
1892 struct recvd_message
*seq
;
1894 EnterCriticalSection( &sequence_cs
);
1898 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
) );
1900 if (sequence_cnt
== sequence_size
)
1903 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof(*sequence
) );
1907 seq
= &sequence
[sequence_cnt
++];
1908 seq
->hwnd
= msg
->hwnd
;
1909 seq
->message
= msg
->message
;
1910 seq
->flags
= msg
->flags
;
1911 seq
->wParam
= msg
->wParam
;
1912 seq
->lParam
= msg
->lParam
;
1914 seq
->descr
= msg
->descr
;
1916 LeaveCriticalSection( &sequence_cs
);
1920 if (msg
->flags
& hook
)
1922 static const char * const CBT_code_name
[10] =
1930 "HCBT_CLICKSKIPPED",
1935 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
1937 sprintf( seq
->output
, "%s: hook %d (%s) wp %08lx lp %08lx",
1938 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
1940 else if (msg
->flags
& winevent_hook
)
1942 sprintf( seq
->output
, "%s: winevent %p %08x %08lx %08lx",
1943 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
1947 switch (msg
->message
)
1949 case WM_WINDOWPOSCHANGING
:
1950 case WM_WINDOWPOSCHANGED
:
1952 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
1954 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s",
1955 msg
->descr
, msg
->hwnd
,
1956 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
1957 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
1958 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
1959 get_winpos_flags(winpos
->flags
) );
1961 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1962 * in the high word for internal purposes
1964 seq
->wParam
= winpos
->flags
& 0xffff;
1965 /* We are not interested in the flags that don't match under XP and Win9x */
1966 seq
->wParam
&= ~SWP_NOZORDER
;
1972 DRAW_ITEM_STRUCT di
;
1973 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
1975 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
1976 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
1977 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
1980 di
.u
.item
.type
= dis
->CtlType
;
1981 di
.u
.item
.ctl_id
= dis
->CtlID
;
1982 if (dis
->CtlType
== ODT_LISTBOX
||
1983 dis
->CtlType
== ODT_COMBOBOX
||
1984 dis
->CtlType
== ODT_MENU
)
1985 di
.u
.item
.item_id
= dis
->itemID
;
1986 di
.u
.item
.action
= dis
->itemAction
;
1987 di
.u
.item
.state
= dis
->itemState
;
1989 seq
->lParam
= di
.u
.lp
;
1993 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
1994 sprintf( seq
->output
, "%s: %p %04x wp %08lx lp %08lx",
1995 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
1997 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
1998 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
2003 /* try to make sure pending X events have been processed before continuing */
2004 static void flush_events(void)
2008 int min_timeout
= 100;
2009 DWORD time
= GetTickCount() + diff
;
2013 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
2014 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2015 diff
= time
- GetTickCount();
2019 static void flush_sequence(void)
2021 EnterCriticalSection( &sequence_cs
);
2022 HeapFree(GetProcessHeap(), 0, sequence
);
2024 sequence_cnt
= sequence_size
= 0;
2025 LeaveCriticalSection( &sequence_cs
);
2028 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
2030 const struct recvd_message
*actual
= sequence
;
2031 unsigned int count
= 0;
2033 trace_(file
, line
)("Failed sequence %s:\n", context
);
2034 while (expected
->message
&& actual
->message
)
2036 if (actual
->output
[0])
2038 if (expected
->flags
& hook
)
2040 trace_(file
, line
)( " %u: expected: hook %04x - actual: %s\n",
2041 count
, expected
->message
, actual
->output
);
2043 else if (expected
->flags
& winevent_hook
)
2045 trace_(file
, line
)( " %u: expected: winevent %04x - actual: %s\n",
2046 count
, expected
->message
, actual
->output
);
2048 else if (expected
->flags
& kbd_hook
)
2050 trace_(file
, line
)( " %u: expected: kbd %04x - actual: %s\n",
2051 count
, expected
->message
, actual
->output
);
2055 trace_(file
, line
)( " %u: expected: msg %04x - actual: %s\n",
2056 count
, expected
->message
, actual
->output
);
2060 if (expected
->message
== actual
->message
)
2062 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) &&
2063 (expected
->flags
& optional
))
2065 /* don't match messages if their defwinproc status differs */
2074 /* silently drop winevent messages if there is no support for them */
2075 else if ((expected
->flags
& optional
) || ((expected
->flags
& winevent_hook
) && !hEvent_hook
))
2085 /* optional trailing messages */
2086 while (expected
->message
&& ((expected
->flags
& optional
) ||
2087 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2089 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2094 if (expected
->message
)
2096 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2100 while (actual
->message
&& actual
->output
[0])
2102 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
2108 #define ok_sequence( exp, contx, todo) \
2109 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2112 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2113 const char *file
, int line
)
2115 static const struct recvd_message end_of_sequence
;
2116 const struct message
*expected
= expected_list
;
2117 const struct recvd_message
*actual
;
2118 int failcount
= 0, dump
= 0;
2119 unsigned int count
= 0;
2121 add_message(&end_of_sequence
);
2125 while (expected
->message
&& actual
->message
)
2127 if (expected
->message
== actual
->message
&&
2128 !((expected
->flags
^ actual
->flags
) & (hook
|winevent_hook
|kbd_hook
)))
2130 if (expected
->flags
& wparam
)
2132 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2136 if (strcmp(winetest_platform
, "wine")) dump
++;
2137 ok_( file
, line
) (FALSE
,
2138 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2139 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2144 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2145 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2146 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2147 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2151 if (expected
->flags
& lparam
)
2153 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2157 if (strcmp(winetest_platform
, "wine")) dump
++;
2158 ok_( file
, line
) (FALSE
,
2159 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2160 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2165 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2166 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2167 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2168 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2171 if ((expected
->flags
& optional
) &&
2172 ((expected
->flags
^ actual
->flags
) & (defwinproc
|parent
)))
2174 /* don't match optional messages if their defwinproc or parent status differs */
2179 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2183 if (strcmp(winetest_platform
, "wine")) dump
++;
2184 ok_( file
, line
) (FALSE
,
2185 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2186 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2191 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2192 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2193 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2194 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2197 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2198 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n",
2199 context
, count
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2200 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2202 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2203 "%s: %u: the msg 0x%04x should have been %s\n",
2204 context
, count
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2205 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2207 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2208 "%s: %u: the msg 0x%04x was expected in %s\n",
2209 context
, count
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2210 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2212 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
2213 "%s: %u: the msg 0x%04x should have been sent by a hook\n",
2214 context
, count
, expected
->message
);
2215 if ((expected
->flags
& hook
) != (actual
->flags
& hook
)) dump
++;
2217 ok_( file
, line
) ((expected
->flags
& winevent_hook
) == (actual
->flags
& winevent_hook
),
2218 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n",
2219 context
, count
, expected
->message
);
2220 if ((expected
->flags
& winevent_hook
) != (actual
->flags
& winevent_hook
)) dump
++;
2222 ok_( file
, line
) ((expected
->flags
& kbd_hook
) == (actual
->flags
& kbd_hook
),
2223 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n",
2224 context
, count
, expected
->message
);
2225 if ((expected
->flags
& kbd_hook
) != (actual
->flags
& kbd_hook
)) dump
++;
2230 /* silently drop hook messages if there is no support for them */
2231 else if ((expected
->flags
& optional
) ||
2232 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2233 ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2234 ((expected
->flags
& kbd_hook
) && !hKBD_hook
))
2240 if (strcmp(winetest_platform
, "wine")) dump
++;
2241 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2242 context
, count
, expected
->message
, actual
->message
);
2248 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2249 context
, count
, expected
->message
, actual
->message
);
2257 /* skip all optional trailing messages */
2258 while (expected
->message
&& ((expected
->flags
& optional
) ||
2259 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2260 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2266 if (expected
->message
|| actual
->message
) {
2268 if (strcmp(winetest_platform
, "wine")) dump
++;
2269 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2270 context
, count
, expected
->message
, actual
->message
);
2276 if (expected
->message
|| actual
->message
)
2279 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2280 context
, count
, expected
->message
, actual
->message
);
2283 if( todo
&& !failcount
) /* succeeded yet marked todo */
2285 if (!strcmp(winetest_platform
, "wine")) dump
++;
2286 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
2290 if (dump
) dump_sequence(expected_list
, context
, file
, line
);
2294 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
2296 /******************************** MDI test **********************************/
2298 /* CreateWindow for MDI frame window, initially visible */
2299 static const struct message WmCreateMDIframeSeq
[] = {
2300 { HCBT_CREATEWND
, hook
},
2301 { WM_GETMINMAXINFO
, sent
},
2302 { WM_NCCREATE
, sent
},
2303 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2304 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
2305 { WM_CREATE
, sent
},
2306 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2307 { WM_NOTIFYFORMAT
, sent
|optional
},
2308 { WM_QUERYUISTATE
, sent
|optional
},
2309 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2310 { WM_GETMINMAXINFO
, sent
|optional
},
2311 { WM_NCCALCSIZE
, sent
|optional
},
2312 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2313 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2314 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2315 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2316 { HCBT_ACTIVATE
, hook
},
2317 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
2318 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2319 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2320 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2321 { WM_NCACTIVATE
, sent
},
2322 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2323 { WM_ACTIVATE
, sent
|wparam
, 1 },
2324 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2325 { HCBT_SETFOCUS
, hook
},
2326 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2327 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2328 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2329 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2330 /* Win9x adds SWP_NOZORDER below */
2331 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2332 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2333 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2334 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2338 /* DestroyWindow for MDI frame window, initially visible */
2339 static const struct message WmDestroyMDIframeSeq
[] = {
2340 { HCBT_DESTROYWND
, hook
},
2341 { 0x0090, sent
|optional
},
2342 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2343 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2344 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2345 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2346 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
2347 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2348 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
2349 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
2350 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2351 { WM_DESTROY
, sent
},
2352 { WM_NCDESTROY
, sent
},
2355 /* CreateWindow for MDI client window, initially visible */
2356 static const struct message WmCreateMDIclientSeq
[] = {
2357 { HCBT_CREATEWND
, hook
},
2358 { WM_NCCREATE
, sent
},
2359 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2360 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2361 { WM_CREATE
, sent
},
2362 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2363 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2364 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2366 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
2367 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2368 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2369 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2370 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2373 /* ShowWindow(SW_SHOW) for MDI client window */
2374 static const struct message WmShowMDIclientSeq
[] = {
2375 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2376 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2377 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2378 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2381 /* ShowWindow(SW_HIDE) for MDI client window */
2382 static const struct message WmHideMDIclientSeq
[] = {
2383 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2384 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2385 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
2386 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
2387 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2390 /* DestroyWindow for MDI client window, initially visible */
2391 static const struct message WmDestroyMDIclientSeq
[] = {
2392 { HCBT_DESTROYWND
, hook
},
2393 { 0x0090, sent
|optional
},
2394 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
2395 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2396 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2397 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2398 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2399 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2400 { WM_DESTROY
, sent
},
2401 { WM_NCDESTROY
, sent
},
2404 /* CreateWindow for MDI child window, initially visible */
2405 static const struct message WmCreateMDIchildVisibleSeq
[] = {
2406 { HCBT_CREATEWND
, hook
},
2407 { WM_NCCREATE
, sent
},
2408 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2409 { WM_CREATE
, sent
},
2410 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2411 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2413 /* Win2k sends wparam set to
2414 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2415 * while Win9x doesn't bother to set child window id according to
2416 * CLIENTCREATESTRUCT.idFirstChild
2418 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2419 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2420 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2421 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2422 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2423 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2424 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2425 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2426 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2428 /* Win9x: message sequence terminates here. */
2430 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2431 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2432 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2433 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2434 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2435 { WM_SETFOCUS
, sent
}, /* in MDI client */
2436 { HCBT_SETFOCUS
, hook
},
2437 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2438 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2439 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2440 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2441 { WM_SETFOCUS
, sent
|defwinproc
},
2442 { WM_MDIACTIVATE
, sent
|defwinproc
},
2445 /* CreateWindow for MDI child window with invisible parent */
2446 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
2447 { HCBT_CREATEWND
, hook
},
2448 { WM_GETMINMAXINFO
, sent
},
2449 { WM_NCCREATE
, sent
},
2450 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2451 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2452 { WM_CREATE
, sent
},
2453 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2454 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2456 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2457 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2458 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
2459 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2460 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2461 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2463 /* Win9x: message sequence terminates here. */
2465 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2466 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2467 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2468 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2469 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2470 { WM_SETFOCUS
, sent
}, /* in MDI client */
2471 { HCBT_SETFOCUS
, hook
},
2472 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2473 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2474 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2475 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2476 { WM_SETFOCUS
, sent
|defwinproc
},
2477 { WM_MDIACTIVATE
, sent
|defwinproc
},
2480 /* DestroyWindow for MDI child window, initially visible */
2481 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
2482 { HCBT_DESTROYWND
, hook
},
2483 /* Win2k sends wparam set to
2484 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2485 * while Win9x doesn't bother to set child window id according to
2486 * CLIENTCREATESTRUCT.idFirstChild
2488 { 0x0090, sent
|optional
},
2489 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2490 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2491 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2492 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2493 { WM_ERASEBKGND
, sent
|parent
|optional
},
2494 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2496 /* { WM_DESTROY, sent }
2497 * Win9x: message sequence terminates here.
2500 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2501 { WM_KILLFOCUS
, sent
},
2502 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2503 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2504 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2505 { WM_SETFOCUS
, sent
}, /* in MDI client */
2507 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2508 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2509 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2510 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2511 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2512 { WM_SETFOCUS
, sent
}, /* in MDI client */
2514 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2516 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2517 { WM_KILLFOCUS
, sent
},
2518 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2519 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2520 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2521 { WM_SETFOCUS
, sent
}, /* in MDI client */
2523 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2524 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2525 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2526 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2527 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2528 { WM_SETFOCUS
, sent
}, /* in MDI client */
2530 { WM_DESTROY
, sent
},
2532 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2533 { WM_KILLFOCUS
, sent
},
2534 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2535 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2536 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2537 { WM_SETFOCUS
, sent
}, /* in MDI client */
2539 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2540 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2541 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2542 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2543 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2544 { WM_SETFOCUS
, sent
}, /* in MDI client */
2546 { WM_NCDESTROY
, sent
},
2549 /* CreateWindow for MDI child window, initially invisible */
2550 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
2551 { HCBT_CREATEWND
, hook
},
2552 { WM_NCCREATE
, sent
},
2553 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2554 { WM_CREATE
, sent
},
2555 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2556 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2558 /* Win2k sends wparam set to
2559 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2560 * while Win9x doesn't bother to set child window id according to
2561 * CLIENTCREATESTRUCT.idFirstChild
2563 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2566 /* DestroyWindow for MDI child window, initially invisible */
2567 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
2568 { HCBT_DESTROYWND
, hook
},
2569 /* Win2k sends wparam set to
2570 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2571 * while Win9x doesn't bother to set child window id according to
2572 * CLIENTCREATESTRUCT.idFirstChild
2574 { 0x0090, sent
|optional
},
2575 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2576 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2577 { WM_DESTROY
, sent
},
2578 { WM_NCDESTROY
, sent
},
2579 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
2580 { WM_PARENTNOTIFY
, sent
|wparam
|optional
, WM_DESTROY
}, /* MDI client */
2583 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
2584 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
2585 { HCBT_CREATEWND
, hook
},
2586 { WM_NCCREATE
, sent
},
2587 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2588 { WM_CREATE
, sent
},
2589 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2590 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2592 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2593 { WM_GETMINMAXINFO
, sent
},
2594 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2595 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2596 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2597 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2599 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2600 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2601 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2602 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2603 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2604 /* Win2k sends wparam set to
2605 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2606 * while Win9x doesn't bother to set child window id according to
2607 * CLIENTCREATESTRUCT.idFirstChild
2609 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2610 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2611 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2612 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2613 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2614 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2615 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2616 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2617 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
2619 /* Win9x: message sequence terminates here. */
2621 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
2622 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
2623 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2624 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2625 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2626 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2627 { HCBT_SETFOCUS
, hook
|optional
},
2628 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
2629 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2630 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2631 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2632 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
2633 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
2635 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2636 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2637 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2638 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2641 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
2642 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
2643 /* restore the 1st MDI child */
2644 { WM_SETREDRAW
, sent
|wparam
, 0 },
2645 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
2646 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
2647 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2648 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2649 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2650 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2652 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2653 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2654 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2655 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2656 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2657 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
2658 /* create the 2nd MDI child */
2659 { HCBT_CREATEWND
, hook
},
2660 { WM_NCCREATE
, sent
},
2661 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2662 { WM_CREATE
, sent
},
2663 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2664 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2666 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2667 { WM_GETMINMAXINFO
, sent
},
2668 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2669 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2670 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2671 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2672 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2674 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2675 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2676 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2677 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2678 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2679 /* Win2k sends wparam set to
2680 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2681 * while Win9x doesn't bother to set child window id according to
2682 * CLIENTCREATESTRUCT.idFirstChild
2684 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2685 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2686 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2687 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2688 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2689 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2690 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2691 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2693 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
2694 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
2696 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2698 /* Win9x: message sequence terminates here. */
2700 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2701 { HCBT_SETFOCUS
, hook
},
2702 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
2703 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
2704 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2705 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2706 { WM_SETFOCUS
, sent
}, /* in MDI client */
2707 { HCBT_SETFOCUS
, hook
},
2708 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2709 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2710 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2711 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2712 { WM_SETFOCUS
, sent
|defwinproc
},
2714 { WM_MDIACTIVATE
, sent
|defwinproc
},
2716 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2717 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2718 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2719 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2722 /* WM_MDICREATE MDI child window, initially visible and maximized */
2723 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
2724 { WM_MDICREATE
, sent
},
2725 { HCBT_CREATEWND
, hook
},
2726 { WM_NCCREATE
, sent
},
2727 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2728 { WM_CREATE
, sent
},
2729 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2730 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2732 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2733 { WM_GETMINMAXINFO
, sent
},
2734 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2735 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2736 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2737 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2740 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2741 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2742 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2743 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2744 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2746 /* Win2k sends wparam set to
2747 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2748 * while Win9x doesn't bother to set child window id according to
2749 * CLIENTCREATESTRUCT.idFirstChild
2751 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2752 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2753 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2755 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2757 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2758 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2759 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2761 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2762 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2764 /* Win9x: message sequence terminates here. */
2766 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2767 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2768 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2769 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2770 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
2771 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
2772 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2773 { HCBT_SETFOCUS
, hook
|optional
},
2774 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2775 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2776 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2777 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2778 { WM_SETFOCUS
, sent
|defwinproc
},
2780 { WM_MDIACTIVATE
, sent
|defwinproc
},
2783 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2784 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2785 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2786 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2789 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2790 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2791 { 0x0093, sent
|defwinproc
|optional
},
2792 { 0x0093, sent
|defwinproc
|optional
},
2793 { 0x0093, sent
|defwinproc
|optional
},
2794 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2795 { WM_MOVE
, sent
|defwinproc
},
2796 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2799 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2800 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2801 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2802 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2805 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2806 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2807 { 0x0093, sent
|optional
},
2808 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2809 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2811 { 0x0093, sent
|optional
},
2812 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2813 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
2814 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
2815 { 0x0093, sent
|defwinproc
|optional
},
2816 { 0x0093, sent
|defwinproc
|optional
},
2817 { 0x0093, sent
|defwinproc
|optional
},
2818 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2819 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
2823 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
2824 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
2825 { HCBT_CREATEWND
, hook
},
2826 { WM_GETMINMAXINFO
, sent
},
2827 { WM_NCCREATE
, sent
},
2828 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2829 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
2830 { WM_CREATE
, sent
},
2831 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2832 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2833 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
2834 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
2835 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
2837 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2838 { WM_GETMINMAXINFO
, sent
},
2839 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2840 { WM_GETMINMAXINFO
, sent
|defwinproc
},
2841 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2842 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
2843 { WM_MOVE
, sent
|defwinproc
},
2844 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2846 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2847 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2848 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2849 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2850 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
2851 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2852 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2853 /* Win2k sends wparam set to
2854 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2855 * while Win9x doesn't bother to set child window id according to
2856 * CLIENTCREATESTRUCT.idFirstChild
2858 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2861 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
2862 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
2863 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
2864 { HCBT_SYSCOMMAND
, hook
},
2865 { WM_CLOSE
, sent
|defwinproc
},
2866 { WM_MDIDESTROY
, sent
}, /* in MDI client */
2868 /* bring the 1st MDI child to top */
2869 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
2870 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
2872 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2874 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
2875 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
2876 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
2878 /* maximize the 1st MDI child */
2879 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2880 { WM_GETMINMAXINFO
, sent
|defwinproc
},
2881 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
2882 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
2883 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
2884 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2885 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2887 /* restore the 2nd MDI child */
2888 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
2889 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
2890 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
2891 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
2893 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2895 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2896 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2898 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2900 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
2902 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2903 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2904 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2905 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2906 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2908 /* bring the 1st MDI child to top */
2909 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2910 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2911 { HCBT_SETFOCUS
, hook
},
2912 { WM_KILLFOCUS
, sent
|defwinproc
},
2913 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
2914 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2915 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2916 { WM_SETFOCUS
, sent
}, /* in MDI client */
2917 { HCBT_SETFOCUS
, hook
},
2918 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2919 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2920 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2921 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2922 { WM_SETFOCUS
, sent
|defwinproc
},
2923 { WM_MDIACTIVATE
, sent
|defwinproc
},
2924 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2926 /* apparently ShowWindow(SW_SHOW) on an MDI client */
2927 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2928 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2929 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2930 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2931 { WM_MDIREFRESHMENU
, sent
},
2933 { HCBT_DESTROYWND
, hook
},
2934 /* Win2k sends wparam set to
2935 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2936 * while Win9x doesn't bother to set child window id according to
2937 * CLIENTCREATESTRUCT.idFirstChild
2939 { 0x0090, sent
|defwinproc
|optional
},
2940 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2941 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
2942 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2943 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2944 { WM_ERASEBKGND
, sent
|parent
|optional
},
2945 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2947 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2948 { WM_DESTROY
, sent
|defwinproc
},
2949 { WM_NCDESTROY
, sent
|defwinproc
},
2952 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
2953 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
2954 { WM_MDIDESTROY
, sent
}, /* in MDI client */
2955 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2956 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2957 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2958 { WM_ERASEBKGND
, sent
|parent
|optional
},
2959 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2961 { HCBT_SETFOCUS
, hook
},
2962 { WM_KILLFOCUS
, sent
},
2963 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2964 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2965 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2966 { WM_SETFOCUS
, sent
}, /* in MDI client */
2967 { HCBT_SETFOCUS
, hook
},
2968 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2969 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2970 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2971 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2972 { WM_SETFOCUS
, sent
},
2975 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2976 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2977 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2978 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2981 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2982 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2983 { 0x0093, sent
|defwinproc
|optional
},
2984 { 0x0093, sent
|defwinproc
|optional
},
2985 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2986 { WM_MOVE
, sent
|defwinproc
},
2987 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2990 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2991 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2992 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2993 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2996 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2997 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2998 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
2999 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3002 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3003 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3004 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3005 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3008 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3009 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3010 { 0x0093, sent
|defwinproc
|optional
},
3011 { 0x0093, sent
|defwinproc
|optional
},
3012 { 0x0093, sent
|defwinproc
|optional
},
3013 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3014 { WM_MOVE
, sent
|defwinproc
},
3015 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3018 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3019 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3020 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3021 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3024 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3025 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3026 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3027 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3028 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3029 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3031 { 0x0093, sent
|defwinproc
|optional
},
3032 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
3033 { 0x0093, sent
|defwinproc
|optional
},
3034 { 0x0093, sent
|defwinproc
|optional
},
3035 { 0x0093, sent
|defwinproc
|optional
},
3036 { 0x0093, sent
|optional
},
3038 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3039 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3040 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3041 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3042 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3045 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3046 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3047 { 0x0093, sent
|defwinproc
|optional
},
3048 { 0x0093, sent
|defwinproc
|optional
},
3049 { 0x0093, sent
|defwinproc
|optional
},
3050 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3051 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3052 { 0x0093, sent
|optional
},
3054 { WM_NCACTIVATE
, sent
|wparam
, 0 },
3055 { WM_MDIACTIVATE
, sent
},
3057 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3058 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3059 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3061 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3063 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3064 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3065 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3068 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3069 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3070 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3071 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3074 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3075 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3076 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3077 { WM_MOVE
, sent
|defwinproc
},
3078 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3081 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3082 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3083 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3084 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3085 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3086 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3087 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3088 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3089 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3091 { HCBT_SETFOCUS
, hook
},
3092 { WM_KILLFOCUS
, sent
},
3093 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3094 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3095 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3096 { WM_SETFOCUS
, sent
}, /* in MDI client */
3098 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3100 { HCBT_DESTROYWND
, hook
},
3101 /* Win2k sends wparam set to
3102 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3103 * while Win9x doesn't bother to set child window id according to
3104 * CLIENTCREATESTRUCT.idFirstChild
3106 { 0x0090, sent
|optional
},
3107 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3109 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3110 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3111 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3112 { WM_ERASEBKGND
, sent
|parent
|optional
},
3113 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3115 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3116 { WM_DESTROY
, sent
},
3117 { WM_NCDESTROY
, sent
},
3120 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3121 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3122 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3123 { WM_GETMINMAXINFO
, sent
},
3124 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3125 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3126 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3127 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3129 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3130 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3131 { HCBT_SETFOCUS
, hook
|optional
},
3132 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3133 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3134 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3135 { HCBT_SETFOCUS
, hook
|optional
},
3136 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3137 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3138 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3139 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3140 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3141 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3142 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3143 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3145 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3146 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3147 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3148 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3149 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3152 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3153 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3154 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3155 { WM_GETMINMAXINFO
, sent
},
3156 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
3157 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3158 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3159 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3160 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3162 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3163 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3164 { HCBT_SETFOCUS
, hook
|optional
},
3165 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3166 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3167 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3168 { HCBT_SETFOCUS
, hook
|optional
},
3169 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3170 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3171 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3172 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3173 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3174 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3175 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3176 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3179 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3180 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3181 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3182 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3183 { WM_GETMINMAXINFO
, sent
},
3184 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3185 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3186 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3187 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3188 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3189 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3190 { WM_MOVE
, sent
|defwinproc
},
3191 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3193 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3194 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3195 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3196 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3197 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3198 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3200 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3201 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3202 { 0x0093, sent
|defwinproc
|optional
},
3203 { 0x0094, sent
|defwinproc
|optional
},
3204 { 0x0094, sent
|defwinproc
|optional
},
3205 { 0x0094, sent
|defwinproc
|optional
},
3206 { 0x0094, sent
|defwinproc
|optional
},
3207 { 0x0093, sent
|defwinproc
|optional
},
3208 { 0x0093, sent
|defwinproc
|optional
},
3209 { 0x0091, sent
|defwinproc
|optional
},
3210 { 0x0092, sent
|defwinproc
|optional
},
3211 { 0x0092, sent
|defwinproc
|optional
},
3212 { 0x0092, sent
|defwinproc
|optional
},
3213 { 0x0092, sent
|defwinproc
|optional
},
3214 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3215 { WM_MOVE
, sent
|defwinproc
},
3216 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3217 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3219 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3220 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3221 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3222 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3224 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3225 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3226 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3227 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3228 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3229 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3230 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3231 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3232 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3233 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3235 { 0x0093, sent
|optional
},
3236 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3237 { 0x0093, sent
|defwinproc
|optional
},
3238 { 0x0093, sent
|defwinproc
|optional
},
3239 { 0x0093, sent
|defwinproc
|optional
},
3240 { 0x0091, sent
|defwinproc
|optional
},
3241 { 0x0092, sent
|defwinproc
|optional
},
3242 { 0x0092, sent
|defwinproc
|optional
},
3243 { 0x0092, sent
|defwinproc
|optional
},
3244 { 0x0092, sent
|defwinproc
|optional
},
3245 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3246 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3247 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3250 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3251 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3252 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3253 { WM_GETMINMAXINFO
, sent
},
3254 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3255 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3256 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3257 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3258 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3260 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3261 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3262 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3263 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3264 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3267 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3268 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3269 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3270 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3271 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3272 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3273 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3274 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3276 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3277 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3278 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3279 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3280 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3283 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3284 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3285 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3286 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3287 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3288 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3289 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3290 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3291 { WM_MOVE
, sent
|defwinproc
},
3292 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3293 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3294 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3295 { HCBT_SETFOCUS
, hook
},
3296 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3297 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3298 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3299 { WM_SETFOCUS
, sent
},
3302 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3303 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
3304 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
3305 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3306 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3307 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3308 { WM_MOVE
, sent
|defwinproc
},
3309 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
3310 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
3311 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3312 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3313 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3314 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
}, /* MDI client */
3317 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3318 static const struct message WmRestoreMDIchildInisibleSeq
[] = {
3319 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3320 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3321 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3322 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3323 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3324 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3325 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3327 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3328 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3329 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3330 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3331 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3335 static HWND mdi_client
;
3336 static WNDPROC old_mdi_client_proc
;
3338 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3340 struct recvd_message msg
;
3342 /* do not log painting messages */
3343 if (message
!= WM_PAINT
&&
3344 message
!= WM_NCPAINT
&&
3345 message
!= WM_SYNCPAINT
&&
3346 message
!= WM_ERASEBKGND
&&
3347 message
!= WM_NCHITTEST
&&
3348 message
!= WM_GETTEXT
&&
3349 message
!= WM_MDIGETACTIVE
&&
3350 !ignore_message( message
))
3353 msg
.message
= message
;
3354 msg
.flags
= sent
|wparam
|lparam
;
3355 msg
.wParam
= wParam
;
3356 msg
.lParam
= lParam
;
3357 msg
.descr
= "mdi client";
3361 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
3364 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3366 static LONG defwndproc_counter
= 0;
3368 struct recvd_message msg
;
3370 /* do not log painting messages */
3371 if (message
!= WM_PAINT
&&
3372 message
!= WM_NCPAINT
&&
3373 message
!= WM_SYNCPAINT
&&
3374 message
!= WM_ERASEBKGND
&&
3375 message
!= WM_NCHITTEST
&&
3376 message
!= WM_GETTEXT
&&
3377 !ignore_message( message
))
3381 case WM_MDIACTIVATE
:
3383 HWND active
, client
= GetParent(hwnd
);
3385 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
3387 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
3388 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
3390 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
3396 msg
.message
= message
;
3397 msg
.flags
= sent
|wparam
|lparam
;
3398 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3399 msg
.wParam
= wParam
;
3400 msg
.lParam
= lParam
;
3401 msg
.descr
= "mdi child";
3405 defwndproc_counter
++;
3406 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
3407 defwndproc_counter
--;
3412 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3414 static LONG defwndproc_counter
= 0;
3416 struct recvd_message msg
;
3418 /* do not log painting messages */
3419 if (message
!= WM_PAINT
&&
3420 message
!= WM_NCPAINT
&&
3421 message
!= WM_SYNCPAINT
&&
3422 message
!= WM_ERASEBKGND
&&
3423 message
!= WM_NCHITTEST
&&
3424 message
!= WM_GETTEXT
&&
3425 !ignore_message( message
))
3428 msg
.message
= message
;
3429 msg
.flags
= sent
|wparam
|lparam
;
3430 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3431 msg
.wParam
= wParam
;
3432 msg
.lParam
= lParam
;
3433 msg
.descr
= "mdi frame";
3437 defwndproc_counter
++;
3438 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
3439 defwndproc_counter
--;
3444 static BOOL
mdi_RegisterWindowClasses(void)
3449 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
3452 cls
.hInstance
= GetModuleHandleA(0);
3454 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
3455 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
3456 cls
.lpszMenuName
= NULL
;
3457 cls
.lpszClassName
= "MDI_frame_class";
3458 if (!RegisterClassA(&cls
)) return FALSE
;
3460 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
3461 cls
.lpszClassName
= "MDI_child_class";
3462 if (!RegisterClassA(&cls
)) return FALSE
;
3464 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
3465 old_mdi_client_proc
= cls
.lpfnWndProc
;
3466 cls
.hInstance
= GetModuleHandleA(0);
3467 cls
.lpfnWndProc
= mdi_client_hook_proc
;
3468 cls
.lpszClassName
= "MDI_client_class";
3469 if (!RegisterClassA(&cls
)) assert(0);
3474 static void test_mdi_messages(void)
3476 MDICREATESTRUCTA mdi_cs
;
3477 CLIENTCREATESTRUCT client_cs
;
3478 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
3481 HMENU hMenu
= CreateMenu();
3483 if (!mdi_RegisterWindowClasses()) assert(0);
3487 trace("creating MDI frame window\n");
3488 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
3489 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
3490 WS_MAXIMIZEBOX
| WS_VISIBLE
,
3491 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
3492 GetDesktopWindow(), hMenu
,
3493 GetModuleHandleA(0), NULL
);
3495 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
3497 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3498 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
3500 trace("creating MDI client window\n");
3501 GetClientRect(mdi_frame
, &rc
);
3502 client_cs
.hWindowMenu
= 0;
3503 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
3504 mdi_client
= CreateWindowExA(0, "MDI_client_class",
3506 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
3507 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
3508 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
3510 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
3512 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3513 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
3515 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3516 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3517 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3522 trace("creating invisible MDI child window\n");
3523 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3525 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3526 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3530 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
3531 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
3533 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3534 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3536 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3537 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3539 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3540 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3541 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3543 ShowWindow(mdi_child
, SW_HIDE
);
3544 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
3547 ShowWindow(mdi_child
, SW_SHOW
);
3548 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
3550 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3551 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3553 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3554 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3556 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3557 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3558 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3560 DestroyWindow(mdi_child
);
3563 trace("creating visible MDI child window\n");
3564 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3565 WS_CHILD
| WS_VISIBLE
,
3566 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3567 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3569 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
3571 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3572 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3574 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3575 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3577 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3578 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3579 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3582 DestroyWindow(mdi_child
);
3583 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3585 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3586 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3588 /* Win2k: MDI client still returns a just destroyed child as active
3589 * Win9x: MDI client returns 0
3591 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3592 ok(active_child
== mdi_child
|| /* win2k */
3593 !active_child
, /* win9x */
3594 "wrong active MDI child %p\n", active_child
);
3595 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3599 trace("creating invisible MDI child window\n");
3600 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3602 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3603 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3605 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
3607 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
3608 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
3610 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3611 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3613 /* Win2k: MDI client still returns a just destroyed child as active
3614 * Win9x: MDI client returns mdi_child2
3616 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3617 ok(active_child
== mdi_child
|| /* win2k */
3618 active_child
== mdi_child2
, /* win9x */
3619 "wrong active MDI child %p\n", active_child
);
3620 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3623 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3624 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
3626 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3627 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3629 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3630 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3631 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3634 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3635 ok(GetFocus() == mdi_child2
|| /* win2k */
3636 GetFocus() == 0, /* win9x */
3637 "wrong focus window %p\n", GetFocus());
3642 ShowWindow(mdi_child2
, SW_HIDE
);
3643 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3645 ShowWindow(mdi_child2
, SW_RESTORE
);
3646 ok_sequence(WmRestoreMDIchildInisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
3649 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3650 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3652 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3653 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3654 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3660 ShowWindow(mdi_child2
, SW_HIDE
);
3661 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3663 ShowWindow(mdi_child2
, SW_SHOW
);
3664 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
3666 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3667 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3669 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3670 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
3672 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3673 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3675 ShowWindow(mdi_child2
, SW_RESTORE
);
3676 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
3678 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3679 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3681 ShowWindow(mdi_child2
, SW_MINIMIZE
);
3682 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", TRUE
);
3684 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3685 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3687 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3688 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3689 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3692 ShowWindow(mdi_child2
, SW_RESTORE
);
3693 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
3695 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3696 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
3698 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3699 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3700 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3706 ShowWindow(mdi_child2
, SW_HIDE
);
3707 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3709 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3710 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3712 DestroyWindow(mdi_child2
);
3713 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
3715 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3716 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3718 /* test for maximized MDI children */
3719 trace("creating maximized visible MDI child window 1\n");
3720 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3721 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3722 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3723 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3725 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
3726 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
3728 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3729 ok(GetFocus() == mdi_child
|| /* win2k */
3730 GetFocus() == 0, /* win9x */
3731 "wrong focus window %p\n", GetFocus());
3733 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3734 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3735 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3738 trace("creating maximized visible MDI child window 2\n");
3739 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3740 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3741 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3742 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3744 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
3745 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
3746 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
3748 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3749 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
3751 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3752 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3753 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3756 trace("destroying maximized visible MDI child window 2\n");
3757 DestroyWindow(mdi_child2
);
3758 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3760 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
3762 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3763 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3765 /* Win2k: MDI client still returns a just destroyed child as active
3766 * Win9x: MDI client returns 0
3768 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3769 ok(active_child
== mdi_child2
|| /* win2k */
3770 !active_child
, /* win9x */
3771 "wrong active MDI child %p\n", active_child
);
3774 ShowWindow(mdi_child
, SW_MAXIMIZE
);
3775 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
3778 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3779 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3781 trace("re-creating maximized visible MDI child window 2\n");
3782 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3783 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3784 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3785 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3787 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
3788 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
3789 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
3791 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3792 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
3794 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3795 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3796 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3799 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
3800 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
3801 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
3803 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
3804 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3805 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3807 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3808 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3809 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3812 DestroyWindow(mdi_child
);
3813 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3815 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3816 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3818 /* Win2k: MDI client still returns a just destroyed child as active
3819 * Win9x: MDI client returns 0
3821 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3822 ok(active_child
== mdi_child
|| /* win2k */
3823 !active_child
, /* win9x */
3824 "wrong active MDI child %p\n", active_child
);
3827 trace("creating maximized invisible MDI child window\n");
3828 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3829 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
3830 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3831 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3833 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
3834 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
3835 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
3836 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
3838 /* Win2k: MDI client still returns a just destroyed child as active
3839 * Win9x: MDI client returns 0
3841 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3842 ok(active_child
== mdi_child
|| /* win2k */
3843 !active_child
|| active_child
== mdi_child2
, /* win9x */
3844 "wrong active MDI child %p\n", active_child
);
3847 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
3848 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3849 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
3850 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
3851 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3852 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3854 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3855 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3856 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3859 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
3862 /* end of test for maximized MDI children */
3865 trace("creating maximized visible MDI child window 1(Switch test)\n");
3866 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3867 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3868 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3869 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3871 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
3872 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
3874 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
3875 ok(GetFocus() == mdi_child
|| /* win2k */
3876 GetFocus() == 0, /* win9x */
3877 "wrong focus window %p(Switch test)\n", GetFocus());
3879 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3880 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
3881 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
3884 trace("creating maximized visible MDI child window 2(Switch test)\n");
3885 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3886 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3887 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3888 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3890 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
3892 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
3893 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
3895 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
3896 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
3898 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3899 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
3900 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
3903 trace("Switch child window.\n");
3904 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
3905 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
3906 trace("end of test for switch maximized MDI children\n");
3909 /* Prepare for switching test of not maximized MDI children */
3910 ShowWindow( mdi_child
, SW_NORMAL
);
3911 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
3912 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
3913 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
3914 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
3917 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
3918 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
3919 trace("end of test for switch not maximized MDI children\n");
3922 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
3925 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
3930 /* end of tests for switch maximized/not maximized MDI children */
3932 mdi_cs
.szClass
= "MDI_child_Class";
3933 mdi_cs
.szTitle
= "MDI child";
3934 mdi_cs
.hOwner
= GetModuleHandleA(0);
3937 mdi_cs
.cx
= CW_USEDEFAULT
;
3938 mdi_cs
.cy
= CW_USEDEFAULT
;
3939 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
3941 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
3942 ok(mdi_child
!= 0, "MDI child creation failed\n");
3943 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
3945 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
3947 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3948 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3950 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
3951 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3952 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3954 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3955 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3956 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3959 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
3960 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
3962 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
3963 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3964 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3969 DestroyWindow(mdi_client
);
3970 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
3972 /* test maximization of MDI child with invisible parent */
3973 client_cs
.hWindowMenu
= 0;
3974 mdi_client
= CreateWindowA("MDI_client_class",
3976 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
3978 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
3979 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
3981 ShowWindow(mdi_client
, SW_HIDE
);
3982 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
3984 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3985 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
3987 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3988 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
3990 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
3991 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
3992 zoomed
= IsZoomed(mdi_child
);
3993 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3995 ShowWindow(mdi_client
, SW_SHOW
);
3996 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
3998 DestroyWindow(mdi_child
);
3999 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
4001 /* end of test for maximization of MDI child with invisible parent */
4003 DestroyWindow(mdi_client
);
4004 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4006 DestroyWindow(mdi_frame
);
4007 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
4009 /************************* End of MDI test **********************************/
4011 static void test_WM_SETREDRAW(HWND hwnd
)
4013 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4018 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
4019 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
4021 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
4022 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
4025 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
4026 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
4028 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4029 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
4031 /* restore original WS_VISIBLE state */
4032 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4038 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4040 struct recvd_message msg
;
4042 if (ignore_message( message
)) return 0;
4048 case WM_NCMOUSEMOVE
:
4049 case WM_NCMOUSELEAVE
:
4057 msg
.message
= message
;
4058 msg
.flags
= sent
|wparam
|lparam
;
4059 msg
.wParam
= wParam
;
4060 msg
.lParam
= lParam
;
4061 msg
.descr
= "dialog";
4064 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
4065 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
4069 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4071 DWORD style
, exstyle
;
4075 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4076 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4077 /* do not be confused by WS_DLGFRAME set */
4078 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4080 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4081 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4083 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4084 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4085 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4086 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
4088 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
4090 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4091 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4092 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4094 /* a subsequent call should do nothing */
4095 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4096 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4097 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4101 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
4102 ok( ret
, "GetScrollRange(%d) error %d\n", ctl
, GetLastError());
4103 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4104 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
4105 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
4108 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4110 DWORD style
, exstyle
;
4114 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4115 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4116 /* do not be confused by WS_DLGFRAME set */
4117 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4119 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4120 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4122 si
.cbSize
= sizeof(si
);
4123 si
.fMask
= SIF_RANGE
;
4126 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4127 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4128 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4130 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4132 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4133 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4134 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4136 /* a subsequent call should do nothing */
4137 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4138 if (style
& WS_HSCROLL
)
4139 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4140 else if (style
& WS_VSCROLL
)
4141 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4143 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4145 si
.fMask
= SIF_PAGE
;
4147 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4148 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4152 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4153 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4155 si
.fMask
= SIF_RANGE
;
4156 si
.nMin
= 0xdeadbeef;
4157 si
.nMax
= 0xdeadbeef;
4158 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4159 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4160 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4161 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4162 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4165 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4166 static void test_scroll_messages(HWND hwnd
)
4177 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4178 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4179 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4180 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4181 /* values of min and max are undefined */
4184 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4185 ok( ret
, "SetScrollRange error %d\n", GetLastError());
4186 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4187 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4192 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4193 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4194 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4195 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4196 /* values of min and max are undefined */
4199 si
.cbSize
= sizeof(si
);
4200 si
.fMask
= SIF_RANGE
;
4203 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4204 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4205 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4208 si
.fMask
= SIF_PAGE
;
4210 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4211 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4212 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4217 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4218 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4219 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4222 si
.fMask
= SIF_RANGE
;
4223 si
.nMin
= 0xdeadbeef;
4224 si
.nMax
= 0xdeadbeef;
4225 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
4226 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4227 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
4228 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4229 /* values of min and max are undefined */
4232 /* set WS_HSCROLL */
4233 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4234 /* clear WS_HSCROLL */
4235 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4237 /* set WS_HSCROLL */
4238 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4239 /* clear WS_HSCROLL */
4240 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4242 /* set WS_VSCROLL */
4243 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4244 /* clear WS_VSCROLL */
4245 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4247 /* set WS_VSCROLL */
4248 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4249 /* clear WS_VSCROLL */
4250 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4253 static void test_showwindow(void)
4258 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4259 100, 100, 200, 200, 0, 0, 0, NULL
);
4260 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4261 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4262 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
4263 ok (hchild
!= 0, "Failed to create child\n");
4266 /* ShowWindow( SW_SHOWNA) for invisible top level window */
4267 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
4268 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4269 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
4271 /* ShowWindow( SW_SHOWNA) for now visible top level window */
4272 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
4273 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4274 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
4275 /* back to invisible */
4276 ShowWindow(hchild
, SW_HIDE
);
4277 ShowWindow(hwnd
, SW_HIDE
);
4279 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
4280 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
4281 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4282 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
4283 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
4284 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
4286 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
4287 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4288 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
4289 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
4290 ShowWindow( hwnd
, SW_SHOW
);
4292 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
4293 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4294 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
4296 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
4297 ShowWindow( hchild
, SW_HIDE
);
4299 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
4300 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4301 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
4304 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
4305 DestroyWindow(hchild
);
4306 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
4308 DestroyWindow(hwnd
);
4313 * 1. Create invisible maximized popup window.
4314 * 2. Move and resize it.
4315 * 3. Show it maximized.
4317 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4318 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4319 100, 100, 200, 200, 0, 0, 0, NULL
);
4320 ok (hwnd
!= 0, "Failed to create popup window\n");
4321 ok(IsZoomed(hwnd
), "window should be maximized\n");
4322 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4324 GetWindowRect(hwnd
, &rc
);
4325 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4326 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4327 "Invalid maximized size before ShowWindow (%d,%d)-(%d,%d)\n",
4328 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4329 /* Reset window's size & position */
4330 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4331 ok(IsZoomed(hwnd
), "window should be maximized\n");
4334 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4335 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4336 ok(IsZoomed(hwnd
), "window should be maximized\n");
4337 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
4339 GetWindowRect(hwnd
, &rc
);
4340 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4341 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4342 "Invalid maximized size after ShowWindow (%d,%d)-(%d,%d)\n",
4343 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4344 DestroyWindow(hwnd
);
4348 * 1. Create invisible maximized popup window.
4349 * 2. Show it maximized.
4351 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4352 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4353 100, 100, 200, 200, 0, 0, 0, NULL
);
4354 ok (hwnd
!= 0, "Failed to create popup window\n");
4355 ok(IsZoomed(hwnd
), "window should be maximized\n");
4356 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4358 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4359 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4360 ok(IsZoomed(hwnd
), "window should be maximized\n");
4361 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
4362 DestroyWindow(hwnd
);
4366 * 1. Create visible maximized popup window.
4368 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
4369 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
4370 100, 100, 200, 200, 0, 0, 0, NULL
);
4371 ok (hwnd
!= 0, "Failed to create popup window\n");
4372 ok(IsZoomed(hwnd
), "window should be maximized\n");
4373 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4374 DestroyWindow(hwnd
);
4378 * 1. Create visible popup window.
4381 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
4382 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
4383 100, 100, 200, 200, 0, 0, 0, NULL
);
4384 ok (hwnd
!= 0, "Failed to create popup window\n");
4385 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
4386 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
4388 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
4389 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4390 ok(IsZoomed(hwnd
), "window should be maximized\n");
4391 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
4392 DestroyWindow(hwnd
);
4396 static void test_sys_menu(void)
4402 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4403 100, 100, 200, 200, 0, 0, 0, NULL
);
4404 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4408 /* test existing window without CS_NOCLOSE style */
4409 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4410 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4412 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4413 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4414 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4416 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
4417 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4419 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4420 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4421 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
4423 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
4424 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4426 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4427 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4428 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4430 /* test whether removing WS_SYSMENU destroys a system menu */
4431 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
4432 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
4434 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4435 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4437 DestroyWindow(hwnd
);
4439 /* test new window with CS_NOCLOSE style */
4440 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4441 100, 100, 200, 200, 0, 0, 0, NULL
);
4442 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4444 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4445 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4447 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4448 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4450 DestroyWindow(hwnd
);
4452 /* test new window without WS_SYSMENU style */
4453 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
4454 100, 100, 200, 200, 0, 0, 0, NULL
);
4455 ok(hwnd
!= 0, "Failed to create overlapped window\n");
4457 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4458 ok(!hmenu
, "GetSystemMenu error %d\n", GetLastError());
4460 DestroyWindow(hwnd
);
4463 /* For shown WS_OVERLAPPEDWINDOW */
4464 static const struct message WmSetIcon_1
[] = {
4465 { WM_SETICON
, sent
},
4466 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
4467 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4468 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
4472 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
4473 static const struct message WmSetIcon_2
[] = {
4474 { WM_SETICON
, sent
},
4478 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
4479 static const struct message WmInitEndSession
[] = {
4481 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4485 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
4486 static const struct message WmInitEndSession_2
[] = {
4488 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4492 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
4493 static const struct message WmInitEndSession_3
[] = {
4495 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4499 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
4500 static const struct message WmInitEndSession_4
[] = {
4502 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4506 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
4507 static const struct message WmInitEndSession_5
[] = {
4509 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
4513 static const struct message WmOptionalPaint
[] = {
4514 { WM_PAINT
, sent
|optional
},
4515 { WM_NCPAINT
, sent
|beginpaint
|optional
},
4516 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
4517 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
4521 static const struct message WmZOrder
[] = {
4522 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
4523 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
4524 { HCBT_ACTIVATE
, hook
},
4525 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
4526 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
4527 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
4528 { WM_GETTEXT
, sent
|optional
},
4529 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
4530 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
4531 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
4532 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4533 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4534 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
4535 { HCBT_SETFOCUS
, hook
},
4536 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
4537 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
4538 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
4539 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
4540 { WM_GETTEXT
, sent
|optional
},
4541 { WM_NCCALCSIZE
, sent
|optional
},
4545 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
4550 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4551 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4553 PostMessageA(hwnd
, WM_USER
, 0, 0);
4555 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4556 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4558 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4559 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4561 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4562 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4564 PostMessageA(hwnd
, WM_USER
, 0, 0);
4566 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4567 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4569 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
4570 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4572 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
4573 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4574 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4576 PostMessageA(hwnd
, WM_USER
, 0, 0);
4578 /* new incoming message causes it to become signaled again */
4579 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4580 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4582 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4583 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4584 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4585 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4588 /* test if we receive the right sequence of messages */
4589 static void test_messages(void)
4591 HWND hwnd
, hparent
, hchild
;
4592 HWND hchild2
, hbutton
;
4600 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4601 100, 100, 200, 200, 0, 0, 0, NULL
);
4602 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4603 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
4605 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
4606 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
4607 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
4609 /* test WM_SETREDRAW on a not visible top level window */
4610 test_WM_SETREDRAW(hwnd
);
4612 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4614 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
4615 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
4617 ok(GetActiveWindow() == hwnd
, "window should be active\n");
4618 ok(GetFocus() == hwnd
, "window should have input focus\n");
4619 ShowWindow(hwnd
, SW_HIDE
);
4621 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
4623 ShowWindow(hwnd
, SW_SHOW
);
4625 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
4627 ShowWindow(hwnd
, SW_HIDE
);
4629 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
4631 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4633 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
4636 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
4638 ShowWindow(hwnd
, SW_RESTORE
);
4640 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
4644 ShowWindow(hwnd
, SW_MINIMIZE
);
4646 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE
);
4649 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
4651 ShowWindow(hwnd
, SW_RESTORE
);
4653 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
4657 ShowWindow(hwnd
, SW_SHOW
);
4659 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
4661 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4662 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
4663 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
4664 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
4666 /* test WM_SETREDRAW on a visible top level window */
4667 ShowWindow(hwnd
, SW_SHOW
);
4669 test_WM_SETREDRAW(hwnd
);
4671 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
4672 test_scroll_messages(hwnd
);
4674 /* test resizing and moving */
4675 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
4676 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
4679 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
4680 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
4683 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
4684 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
4688 /* popups don't get WM_GETMINMAXINFO */
4689 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
4690 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
4692 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
4693 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
4695 DestroyWindow(hwnd
);
4696 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
4698 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
4699 100, 100, 200, 200, 0, 0, 0, NULL
);
4700 ok (hparent
!= 0, "Failed to create parent window\n");
4703 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
4704 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4705 ok (hchild
!= 0, "Failed to create child window\n");
4706 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
4707 DestroyWindow(hchild
);
4710 /* visible child window with a caption */
4711 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
4712 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
4713 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4714 ok (hchild
!= 0, "Failed to create child window\n");
4715 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
4717 trace("testing scroll APIs on a visible child window %p\n", hchild
);
4718 test_scroll_messages(hchild
);
4720 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4721 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
4723 DestroyWindow(hchild
);
4726 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4727 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4728 ok (hchild
!= 0, "Failed to create child window\n");
4729 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
4731 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
4732 100, 100, 50, 50, hparent
, 0, 0, NULL
);
4733 ok (hchild2
!= 0, "Failed to create child2 window\n");
4736 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
4737 0, 100, 50, 50, hchild
, 0, 0, NULL
);
4738 ok (hbutton
!= 0, "Failed to create button window\n");
4740 /* test WM_SETREDRAW on a not visible child window */
4741 test_WM_SETREDRAW(hchild
);
4743 ShowWindow(hchild
, SW_SHOW
);
4744 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
4746 /* check parent messages too */
4747 log_all_parent_messages
++;
4748 ShowWindow(hchild
, SW_HIDE
);
4749 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
4750 log_all_parent_messages
--;
4752 ShowWindow(hchild
, SW_SHOW
);
4753 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
4755 ShowWindow(hchild
, SW_HIDE
);
4756 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
4758 ShowWindow(hchild
, SW_SHOW
);
4759 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
4761 /* test WM_SETREDRAW on a visible child window */
4762 test_WM_SETREDRAW(hchild
);
4764 log_all_parent_messages
++;
4765 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
4766 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
4767 log_all_parent_messages
--;
4769 ShowWindow(hchild
, SW_HIDE
);
4771 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4772 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
4774 ShowWindow(hchild
, SW_HIDE
);
4776 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
4777 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
4779 /* DestroyWindow sequence below expects that a child has focus */
4783 DestroyWindow(hchild
);
4784 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
4785 DestroyWindow(hchild2
);
4786 DestroyWindow(hbutton
);
4789 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
4790 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4791 ok (hchild
!= 0, "Failed to create child popup window\n");
4792 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
4793 DestroyWindow(hchild
);
4795 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
4797 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
4798 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4799 ok (hchild
!= 0, "Failed to create popup window\n");
4800 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
4801 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4802 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
4804 ShowWindow(hchild
, SW_SHOW
);
4805 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
4807 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
4808 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
4810 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4811 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
4812 DestroyWindow(hchild
);
4814 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
4815 * changes nothing in message sequences.
4818 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
4819 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4820 ok (hchild
!= 0, "Failed to create popup window\n");
4821 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
4822 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4823 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
4825 ShowWindow(hchild
, SW_SHOW
);
4826 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
4828 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
4829 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
4830 DestroyWindow(hchild
);
4833 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
4834 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4835 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
4836 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
4839 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
4840 test_scroll_messages(hwnd
);
4846 SendMessageA(hwnd
, WM_NULL
, 0, 0);
4849 after_end_dialog
= TRUE
;
4850 EndDialog( hwnd
, 0 );
4851 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
4853 DestroyWindow(hwnd
);
4854 after_end_dialog
= FALSE
;
4855 test_def_id
= FALSE
;
4857 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
4858 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
4860 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
4861 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
4862 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
4864 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
4865 ShowWindow(hwnd
, SW_SHOW
);
4866 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
4870 ok(DrawMenuBar(hwnd
), "DrawMenuBar failed: %d\n", GetLastError());
4872 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
4873 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
4874 DestroyWindow(hwnd
);
4877 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
4878 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
4880 DestroyWindow(hparent
);
4883 /* Message sequence for SetMenu */
4884 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
4885 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %d\n", GetLastError());
4886 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
4888 hmenu
= CreateMenu();
4889 ok (hmenu
!= 0, "Failed to create menu\n");
4890 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
4891 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4892 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
4893 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
4894 ok (SetMenu(hwnd
, 0), "SetMenu\n");
4895 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
4896 ok (SetMenu(hwnd
, 0), "SetMenu\n");
4897 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
4898 ShowWindow(hwnd
, SW_SHOW
);
4899 UpdateWindow( hwnd
);
4902 ok (SetMenu(hwnd
, 0), "SetMenu\n");
4903 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
4904 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
4905 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
4907 UpdateWindow( hwnd
);
4910 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
4912 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
4914 DestroyWindow(hwnd
);
4917 /* Message sequence for EnableWindow */
4918 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
4919 100, 100, 200, 200, 0, 0, 0, NULL
);
4920 ok (hparent
!= 0, "Failed to create parent window\n");
4921 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
4922 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4923 ok (hchild
!= 0, "Failed to create child window\n");
4929 EnableWindow(hparent
, FALSE
);
4930 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
4932 EnableWindow(hparent
, TRUE
);
4933 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(TRUE)", FALSE
);
4938 test_MsgWaitForMultipleObjects(hparent
);
4940 /* the following test causes an exception in user.exe under win9x */
4941 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
4943 DestroyWindow(hparent
);
4947 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
4948 /* PeekMessage(NULL) fails, but still removes the message */
4949 SetLastError(0xdeadbeef);
4950 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
4951 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
4952 GetLastError() == 0xdeadbeef, /* NT4 */
4953 "last error is %d\n", GetLastError() );
4954 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
4955 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
4957 DestroyWindow(hchild
);
4958 DestroyWindow(hparent
);
4961 /* Message sequences for WM_SETICON */
4962 trace("testing WM_SETICON\n");
4963 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4964 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
4966 ShowWindow(hwnd
, SW_SHOW
);
4970 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4971 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
4973 ShowWindow(hwnd
, SW_HIDE
);
4976 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4977 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
4978 DestroyWindow(hwnd
);
4981 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
4982 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
4984 ShowWindow(hwnd
, SW_SHOW
);
4988 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4989 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
4991 ShowWindow(hwnd
, SW_HIDE
);
4994 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4995 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
4998 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
5001 todo_wine
win_skip( "Message 0x3b not supported\n" );
5004 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
5005 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res
);
5006 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
5007 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
5008 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res
);
5009 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
5010 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
5011 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res
);
5014 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
5015 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
5016 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res
);
5017 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
5018 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
5019 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res
);
5021 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
5022 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
5023 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res
);
5025 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
5026 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
5027 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res
);
5030 DestroyWindow(hwnd
);
5034 static void test_setwindowpos(void)
5039 const INT winX
= 100;
5040 const INT winY
= 100;
5041 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
5043 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
5044 0, 0, winX
, winY
, 0,
5047 GetWindowRect(hwnd
, &rc
);
5048 expect(sysX
, rc
.right
);
5049 expect(winY
, rc
.bottom
);
5053 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, winX
, winY
, 0);
5054 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
5055 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %ld\n", res
);
5057 GetWindowRect(hwnd
, &rc
);
5058 expect(sysX
, rc
.right
);
5059 expect(winY
, rc
.bottom
);
5060 DestroyWindow(hwnd
);
5063 static void invisible_parent_tests(void)
5065 HWND hparent
, hchild
;
5067 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
5068 100, 100, 200, 200, 0, 0, 0, NULL
);
5069 ok (hparent
!= 0, "Failed to create parent window\n");
5072 /* test showing child with hidden parent */
5074 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5075 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5076 ok (hchild
!= 0, "Failed to create child window\n");
5077 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5079 ShowWindow( hchild
, SW_MINIMIZE
);
5080 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5081 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5082 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5087 ShowWindow( hchild
, SW_MINIMIZE
);
5088 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5090 DestroyWindow(hchild
);
5091 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5092 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5095 ShowWindow( hchild
, SW_MAXIMIZE
);
5096 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5097 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5098 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5103 ShowWindow( hchild
, SW_MAXIMIZE
);
5104 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5106 DestroyWindow(hchild
);
5107 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5108 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5111 ShowWindow( hchild
, SW_RESTORE
);
5112 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
5113 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5114 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5116 DestroyWindow(hchild
);
5117 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5118 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5121 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5122 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5123 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5124 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5129 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5130 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5132 DestroyWindow(hchild
);
5133 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5134 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5137 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
5138 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
5139 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
5140 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5141 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5143 DestroyWindow(hchild
);
5144 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5145 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5148 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5149 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5150 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5151 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5156 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5157 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5159 DestroyWindow(hchild
);
5160 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5161 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5164 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
5165 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
5166 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
5168 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5170 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5172 DestroyWindow(hchild
);
5173 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5174 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5177 ShowWindow( hchild
, SW_SHOWNA
);
5178 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5179 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5180 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5185 ShowWindow( hchild
, SW_SHOWNA
);
5186 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5188 DestroyWindow(hchild
);
5189 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5190 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5193 ShowWindow( hchild
, SW_SHOW
);
5194 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5195 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5196 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5201 ShowWindow( hchild
, SW_SHOW
);
5202 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5204 ShowWindow( hchild
, SW_HIDE
);
5205 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
5206 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5207 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5209 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5210 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
5211 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5212 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5214 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5215 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
5216 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
5217 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5219 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5221 DestroyWindow(hchild
);
5222 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
5224 DestroyWindow(hparent
);
5228 /****************** button message test *************************/
5229 #define ID_BUTTON 0x000e
5231 static const struct message WmSetFocusButtonSeq
[] =
5233 { HCBT_SETFOCUS
, hook
},
5234 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5235 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5236 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5237 { WM_SETFOCUS
, sent
|wparam
, 0 },
5238 { WM_CTLCOLORBTN
, sent
|parent
},
5239 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5240 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5243 static const struct message WmKillFocusButtonSeq
[] =
5245 { HCBT_SETFOCUS
, hook
},
5246 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5247 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5248 { WM_CTLCOLORBTN
, sent
|parent
},
5249 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5250 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5251 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5252 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5254 { WM_CTLCOLORBTN
, sent
|parent
},
5257 static const struct message WmSetFocusStaticSeq
[] =
5259 { HCBT_SETFOCUS
, hook
},
5260 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5261 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5262 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5263 { WM_SETFOCUS
, sent
|wparam
, 0 },
5264 { WM_CTLCOLORSTATIC
, sent
|parent
},
5265 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5266 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
5267 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5270 static const struct message WmKillFocusStaticSeq
[] =
5272 { HCBT_SETFOCUS
, hook
},
5273 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5274 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5275 { WM_CTLCOLORSTATIC
, sent
|parent
},
5276 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5277 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5278 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5279 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5281 { WM_CTLCOLORSTATIC
, sent
|parent
},
5284 static const struct message WmSetFocusOwnerdrawSeq
[] =
5286 { HCBT_SETFOCUS
, hook
},
5287 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5288 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5289 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5290 { WM_SETFOCUS
, sent
|wparam
, 0 },
5291 { WM_CTLCOLORBTN
, sent
|parent
},
5292 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
5293 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5294 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5297 static const struct message WmKillFocusOwnerdrawSeq
[] =
5299 { HCBT_SETFOCUS
, hook
},
5300 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5301 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5302 { WM_CTLCOLORBTN
, sent
|parent
},
5303 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
5304 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5305 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5306 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5307 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5309 { WM_CTLCOLORBTN
, sent
|parent
},
5310 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
5313 static const struct message WmLButtonDownSeq
[] =
5315 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
5316 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
5317 { HCBT_SETFOCUS
, hook
},
5318 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5319 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5320 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5321 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5322 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5323 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
5324 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5325 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5328 static const struct message WmLButtonUpSeq
[] =
5330 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
5331 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
5332 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5333 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5334 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
5335 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
5338 static const struct message WmSetFontButtonSeq
[] =
5340 { WM_SETFONT
, sent
},
5342 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
5343 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5346 static const struct message WmSetStyleButtonSeq
[] =
5348 { BM_SETSTYLE
, sent
},
5349 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5351 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5352 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5353 { WM_CTLCOLORBTN
, sent
|parent
},
5356 static const struct message WmSetStyleStaticSeq
[] =
5358 { BM_SETSTYLE
, sent
},
5359 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5361 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5362 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5363 { WM_CTLCOLORSTATIC
, sent
|parent
},
5366 static const struct message WmSetStyleUserSeq
[] =
5368 { BM_SETSTYLE
, sent
},
5369 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5371 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5372 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5373 { WM_CTLCOLORBTN
, sent
|parent
},
5374 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
5377 static const struct message WmSetStyleOwnerdrawSeq
[] =
5379 { BM_SETSTYLE
, sent
},
5380 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5382 { WM_NCPAINT
, sent
|optional
}, /* FIXME: Wine sends it */
5383 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5384 { WM_CTLCOLORBTN
, sent
|parent
},
5385 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
5386 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
5389 static const struct message WmSetStateButtonSeq
[] =
5391 { BM_SETSTATE
, sent
},
5392 { WM_CTLCOLORBTN
, sent
|parent
},
5393 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5396 static const struct message WmSetStateStaticSeq
[] =
5398 { BM_SETSTATE
, sent
},
5399 { WM_CTLCOLORSTATIC
, sent
|parent
},
5400 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5403 static const struct message WmSetStateUserSeq
[] =
5405 { BM_SETSTATE
, sent
},
5406 { WM_CTLCOLORBTN
, sent
|parent
},
5407 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
5408 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5411 static const struct message WmSetStateOwnerdrawSeq
[] =
5413 { BM_SETSTATE
, sent
},
5414 { WM_CTLCOLORBTN
, sent
|parent
},
5415 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
5416 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5419 static const struct message WmClearStateButtonSeq
[] =
5421 { BM_SETSTATE
, sent
},
5422 { WM_CTLCOLORBTN
, sent
|parent
},
5423 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
5424 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5427 static const struct message WmClearStateOwnerdrawSeq
[] =
5429 { BM_SETSTATE
, sent
},
5430 { WM_CTLCOLORBTN
, sent
|parent
},
5431 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
5432 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5435 static const struct message WmSetCheckIgnoredSeq
[] =
5437 { BM_SETCHECK
, sent
},
5438 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5441 static const struct message WmSetCheckStaticSeq
[] =
5443 { BM_SETCHECK
, sent
},
5444 { WM_CTLCOLORSTATIC
, sent
|parent
},
5445 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5449 static WNDPROC old_button_proc
;
5451 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5453 static LONG defwndproc_counter
= 0;
5455 struct recvd_message msg
;
5457 if (ignore_message( message
)) return 0;
5465 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
5469 msg
.message
= message
;
5470 msg
.flags
= sent
|wparam
|lparam
;
5471 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
5472 msg
.wParam
= wParam
;
5473 msg
.lParam
= lParam
;
5474 msg
.descr
= "button";
5478 defwndproc_counter
++;
5479 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
5480 defwndproc_counter
--;
5485 static void subclass_button(void)
5489 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
5491 old_button_proc
= cls
.lpfnWndProc
;
5493 cls
.hInstance
= GetModuleHandleA(NULL
);
5494 cls
.lpfnWndProc
= button_hook_proc
;
5495 cls
.lpszClassName
= "my_button_class";
5496 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
5497 if (!RegisterClassA(&cls
)) assert(0);
5500 static void test_button_messages(void)
5506 const struct message
*setfocus
;
5507 const struct message
*killfocus
;
5508 const struct message
*setstyle
;
5509 const struct message
*setstate
;
5510 const struct message
*clearstate
;
5511 const struct message
*setcheck
;
5513 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
5514 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
5515 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
},
5516 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
5517 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
5518 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
},
5519 { BS_CHECKBOX
, DLGC_BUTTON
,
5520 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5521 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5522 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
5523 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5524 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5525 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
5526 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5527 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5528 { BS_3STATE
, DLGC_BUTTON
,
5529 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5530 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5531 { BS_AUTO3STATE
, DLGC_BUTTON
,
5532 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5533 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5534 { BS_GROUPBOX
, DLGC_STATIC
,
5535 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5536 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
},
5537 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
5538 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
5539 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
},
5540 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
5541 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5542 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5543 { BS_OWNERDRAW
, DLGC_BUTTON
,
5544 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
5545 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
},
5552 /* selection with VK_SPACE should capture button window */
5553 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
5554 0, 0, 50, 14, 0, 0, 0, NULL
);
5555 ok(hwnd
!= 0, "Failed to create button window\n");
5558 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
5559 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
5560 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
5561 DestroyWindow(hwnd
);
5565 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5566 100, 100, 200, 200, 0, 0, 0, NULL
);
5567 ok(parent
!= 0, "Failed to create parent window\n");
5569 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
5574 trace("button style %08x\n", button
[i
].style
);
5576 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
5577 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
5578 ok(hwnd
!= 0, "Failed to create button window\n");
5580 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5581 style
&= ~(WS_CHILD
| BS_NOTIFY
);
5582 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
5583 if (button
[i
].style
== BS_USERBUTTON
)
5584 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %x\n", style
);
5586 ok(style
== button
[i
].style
, "expected style %x got %x\n", button
[i
].style
, style
);
5588 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
5589 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
5591 ShowWindow(hwnd
, SW_SHOW
);
5598 log_all_parent_messages
++;
5600 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
5602 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5603 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5604 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
5607 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5608 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5609 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
5611 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
5613 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
5614 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5615 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5616 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
5618 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5619 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
5620 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
5621 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5623 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
5624 ok(state
== 0, "expected state 0, got %04x\n", state
);
5628 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
5629 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5630 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5631 ok_sequence(button
[i
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
5633 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
5634 ok(state
== 0x0004, "expected state 0x0004, got %04x\n", state
);
5636 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5637 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5638 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5642 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
5643 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5644 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5645 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
5647 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
5648 ok(state
== 0, "expected state 0, got %04x\n", state
);
5650 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5651 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5652 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5654 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
5655 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
5659 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
5660 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5661 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5662 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
5664 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
5665 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
5667 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5668 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5669 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5673 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
5674 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5675 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5676 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
5678 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
5679 if (button
[i
].style
== BS_PUSHBUTTON
||
5680 button
[i
].style
== BS_DEFPUSHBUTTON
||
5681 button
[i
].style
== BS_GROUPBOX
||
5682 button
[i
].style
== BS_USERBUTTON
||
5683 button
[i
].style
== BS_OWNERDRAW
)
5684 ok(state
== BST_UNCHECKED
, "expected check 0, got %04x\n", state
);
5686 ok(state
== BST_CHECKED
, "expected check 1, got %04x\n", state
);
5688 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5689 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5690 if (button
[i
].style
== BS_RADIOBUTTON
||
5691 button
[i
].style
== BS_AUTORADIOBUTTON
)
5692 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04x | WS_TABSTOP got %04x\n", button
[i
].style
, style
);
5694 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5696 log_all_parent_messages
--;
5698 DestroyWindow(hwnd
);
5701 DestroyWindow(parent
);
5703 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON
| WS_POPUP
| WS_VISIBLE
,
5704 0, 0, 50, 14, 0, 0, 0, NULL
);
5705 ok(hwnd
!= 0, "Failed to create button window\n");
5707 SetForegroundWindow(hwnd
);
5710 SetActiveWindow(hwnd
);
5714 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
5715 ok_sequence(WmLButtonDownSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
5717 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
5718 ok_sequence(WmLButtonUpSeq
, "WM_LBUTTONUP on a button", FALSE
);
5721 zfont
= GetStockObject(SYSTEM_FONT
);
5722 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
5724 ok_sequence(WmSetFontButtonSeq
, "WM_SETFONT on a button", FALSE
);
5726 DestroyWindow(hwnd
);
5729 /****************** static message test *************************/
5730 static const struct message WmSetFontStaticSeq
[] =
5732 { WM_SETFONT
, sent
},
5733 { WM_PAINT
, sent
|defwinproc
|optional
},
5734 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
5735 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
5739 static WNDPROC old_static_proc
;
5741 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5743 static LONG defwndproc_counter
= 0;
5745 struct recvd_message msg
;
5747 if (ignore_message( message
)) return 0;
5750 msg
.message
= message
;
5751 msg
.flags
= sent
|wparam
|lparam
;
5752 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
5753 msg
.wParam
= wParam
;
5754 msg
.lParam
= lParam
;
5755 msg
.descr
= "static";
5758 defwndproc_counter
++;
5759 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
5760 defwndproc_counter
--;
5765 static void subclass_static(void)
5769 if (!GetClassInfoA(0, "static", &cls
)) assert(0);
5771 old_static_proc
= cls
.lpfnWndProc
;
5773 cls
.hInstance
= GetModuleHandleA(NULL
);
5774 cls
.lpfnWndProc
= static_hook_proc
;
5775 cls
.lpszClassName
= "my_static_class";
5776 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
5777 if (!RegisterClassA(&cls
)) assert(0);
5780 static void test_static_messages(void)
5782 /* FIXME: make as comprehensive as the button message test */
5787 const struct message
*setfont
;
5789 { SS_LEFT
, DLGC_STATIC
,
5790 WmSetFontStaticSeq
}
5798 for (i
= 0; i
< sizeof(static_ctrl
)/sizeof(static_ctrl
[0]); i
++)
5800 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
5801 0, 0, 50, 14, 0, 0, 0, NULL
);
5802 ok(hwnd
!= 0, "Failed to create static window\n");
5804 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
5805 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
5807 ShowWindow(hwnd
, SW_SHOW
);
5812 trace("static style %08x\n", static_ctrl
[i
].style
);
5813 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
5814 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
5816 DestroyWindow(hwnd
);
5820 /****************** ComboBox message test *************************/
5821 #define ID_COMBOBOX 0x000f
5823 static const struct message WmKeyDownComboSeq
[] =
5825 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
5826 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
5827 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
5828 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
5829 { WM_CTLCOLOREDIT
, sent
|parent
},
5830 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
5834 static const struct message WmSetPosComboSeq
[] =
5836 { WM_WINDOWPOSCHANGING
, sent
},
5837 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
5838 { WM_CHILDACTIVATE
, sent
},
5839 { WM_WINDOWPOSCHANGED
, sent
},
5840 { WM_MOVE
, sent
|defwinproc
},
5841 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
5842 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
5843 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
5844 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
5845 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
5849 static WNDPROC old_combobox_proc
;
5851 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5853 static LONG defwndproc_counter
= 0;
5855 struct recvd_message msg
;
5857 /* do not log painting messages */
5858 if (message
!= WM_PAINT
&&
5859 message
!= WM_NCPAINT
&&
5860 message
!= WM_SYNCPAINT
&&
5861 message
!= WM_ERASEBKGND
&&
5862 message
!= WM_NCHITTEST
&&
5863 message
!= WM_GETTEXT
&&
5864 !ignore_message( message
))
5867 msg
.message
= message
;
5868 msg
.flags
= sent
|wparam
|lparam
;
5869 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
5870 msg
.wParam
= wParam
;
5871 msg
.lParam
= lParam
;
5872 msg
.descr
= "combo";
5876 defwndproc_counter
++;
5877 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
5878 defwndproc_counter
--;
5883 static void subclass_combobox(void)
5887 if (!GetClassInfoA(0, "ComboBox", &cls
)) assert(0);
5889 old_combobox_proc
= cls
.lpfnWndProc
;
5891 cls
.hInstance
= GetModuleHandleA(NULL
);
5892 cls
.lpfnWndProc
= combobox_hook_proc
;
5893 cls
.lpszClassName
= "my_combobox_class";
5894 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
5895 if (!RegisterClassA(&cls
)) assert(0);
5898 static void test_combobox_messages(void)
5903 subclass_combobox();
5905 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5906 100, 100, 200, 200, 0, 0, 0, NULL
);
5907 ok(parent
!= 0, "Failed to create parent window\n");
5910 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
5911 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
5912 ok(combo
!= 0, "Failed to create combobox window\n");
5914 UpdateWindow(combo
);
5916 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
5917 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", ret
);
5919 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
5920 ok(ret
== 0, "expected 0, got %ld\n", ret
);
5921 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
5922 ok(ret
== 1, "expected 1, got %ld\n", ret
);
5923 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
5924 ok(ret
== 2, "expected 2, got %ld\n", ret
);
5926 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
5930 log_all_parent_messages
++;
5931 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
5932 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
5933 log_all_parent_messages
--;
5934 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
5937 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
5938 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
5940 DestroyWindow(combo
);
5941 DestroyWindow(parent
);
5944 /****************** WM_IME_KEYDOWN message test *******************/
5946 static const struct message WmImeKeydownMsgSeq_0
[] =
5948 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
5949 { WM_CHAR
, wparam
, 'A' },
5953 static const struct message WmImeKeydownMsgSeq_1
[] =
5955 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
5956 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
5960 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5962 struct recvd_message msg
;
5965 msg
.message
= message
;
5966 msg
.flags
= wparam
|lparam
;
5967 msg
.wParam
= wParam
;
5968 msg
.lParam
= lParam
;
5969 msg
.descr
= "wmime_keydown";
5972 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
5975 static void register_wmime_keydown_class(void)
5979 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
5980 cls
.lpfnWndProc
= wmime_keydown_procA
;
5981 cls
.hInstance
= GetModuleHandleA(0);
5982 cls
.lpszClassName
= "wmime_keydown_class";
5983 if (!RegisterClassA(&cls
)) assert(0);
5986 static void test_wmime_keydown_message(void)
5991 trace("Message sequences by WM_IME_KEYDOWN\n");
5993 register_wmime_keydown_class();
5994 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
5995 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6000 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
6001 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
6002 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
6004 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
6006 TranslateMessage(&msg
);
6007 DispatchMessageA(&msg
);
6009 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
6011 DestroyWindow(hwnd
);
6014 /************* painting message test ********************/
6016 void dump_region(HRGN hrgn
)
6019 RGNDATA
*data
= NULL
;
6024 printf( "null region\n" );
6027 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
6028 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
6029 GetRegionData( hrgn
, size
, data
);
6030 printf("%d rects:", data
->rdh
.nCount
);
6031 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
6032 printf( " (%d,%d)-(%d,%d)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
6034 HeapFree( GetProcessHeap(), 0, data
);
6037 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
6041 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
6042 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
6044 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
6045 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
6046 if (ret
== NULLREGION
)
6048 ok( !hrgn
, "Update region shouldn't be empty\n" );
6052 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
6054 ok( 0, "Regions are different\n" );
6055 if (winetest_debug
> 0)
6057 printf( "Update region: " );
6058 dump_region( update
);
6059 printf( "Wanted region: " );
6060 dump_region( hrgn
);
6064 GetRgnBox( update
, &r1
);
6065 GetUpdateRect( hwnd
, &r2
, FALSE
);
6066 ok( r1
.left
== r2
.left
&& r1
.top
== r2
.top
&& r1
.right
== r2
.right
&& r1
.bottom
== r2
.bottom
,
6067 "Rectangles are different: %d,%d-%d,%d / %d,%d-%d,%d\n",
6068 r1
.left
, r1
.top
, r1
.right
, r1
.bottom
, r2
.left
, r2
.top
, r2
.right
, r2
.bottom
);
6070 DeleteObject( tmp
);
6071 DeleteObject( update
);
6074 static const struct message WmInvalidateRgn
[] = {
6075 { WM_NCPAINT
, sent
},
6076 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6080 static const struct message WmGetUpdateRect
[] = {
6081 { WM_NCPAINT
, sent
},
6082 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6087 static const struct message WmInvalidateFull
[] = {
6088 { WM_NCPAINT
, sent
|wparam
, 1 },
6089 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6093 static const struct message WmInvalidateErase
[] = {
6094 { WM_NCPAINT
, sent
|wparam
, 1 },
6095 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6096 { WM_ERASEBKGND
, sent
},
6100 static const struct message WmInvalidatePaint
[] = {
6102 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
6103 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6107 static const struct message WmInvalidateErasePaint
[] = {
6109 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
6110 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6111 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6115 static const struct message WmInvalidateErasePaint2
[] = {
6117 { WM_NCPAINT
, sent
|beginpaint
},
6118 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6119 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6123 static const struct message WmErase
[] = {
6124 { WM_ERASEBKGND
, sent
},
6128 static const struct message WmPaint
[] = {
6133 static const struct message WmParentOnlyPaint
[] = {
6134 { WM_PAINT
, sent
|parent
},
6138 static const struct message WmInvalidateParent
[] = {
6139 { WM_NCPAINT
, sent
|parent
},
6140 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
6141 { WM_ERASEBKGND
, sent
|parent
},
6145 static const struct message WmInvalidateParentChild
[] = {
6146 { WM_NCPAINT
, sent
|parent
},
6147 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
6148 { WM_ERASEBKGND
, sent
|parent
},
6149 { WM_NCPAINT
, sent
},
6150 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6151 { WM_ERASEBKGND
, sent
},
6155 static const struct message WmInvalidateParentChild2
[] = {
6156 { WM_ERASEBKGND
, sent
|parent
},
6157 { WM_NCPAINT
, sent
},
6158 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6159 { WM_ERASEBKGND
, sent
},
6163 static const struct message WmParentPaint
[] = {
6164 { WM_PAINT
, sent
|parent
},
6169 static const struct message WmParentPaintNc
[] = {
6170 { WM_PAINT
, sent
|parent
},
6172 { WM_NCPAINT
, sent
|beginpaint
},
6173 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6174 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6178 static const struct message WmChildPaintNc
[] = {
6180 { WM_NCPAINT
, sent
|beginpaint
},
6181 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6182 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6186 static const struct message WmParentErasePaint
[] = {
6187 { WM_PAINT
, sent
|parent
},
6188 { WM_NCPAINT
, sent
|parent
|beginpaint
},
6189 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
6190 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
6192 { WM_NCPAINT
, sent
|beginpaint
},
6193 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6194 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6198 static const struct message WmParentOnlyNcPaint
[] = {
6199 { WM_PAINT
, sent
|parent
},
6200 { WM_NCPAINT
, sent
|parent
|beginpaint
},
6201 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
6205 static const struct message WmSetParentStyle
[] = {
6206 { WM_STYLECHANGING
, sent
|parent
},
6207 { WM_STYLECHANGED
, sent
|parent
},
6211 static void test_paint_messages(void)
6217 HWND hparent
, hchild
;
6218 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
6219 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
6220 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
6221 100, 100, 200, 200, 0, 0, 0, NULL
);
6222 ok (hwnd
!= 0, "Failed to create overlapped window\n");
6224 ShowWindow( hwnd
, SW_SHOW
);
6225 UpdateWindow( hwnd
);
6229 check_update_rgn( hwnd
, 0 );
6230 SetRectRgn( hrgn
, 10, 10, 20, 20 );
6231 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
6232 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6233 check_update_rgn( hwnd
, hrgn
);
6234 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
6235 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
6236 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6237 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
6238 check_update_rgn( hwnd
, hrgn
);
6239 /* validate everything */
6240 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
6241 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6242 check_update_rgn( hwnd
, 0 );
6244 /* test empty region */
6245 SetRectRgn( hrgn
, 10, 10, 10, 15 );
6246 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
6247 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6248 check_update_rgn( hwnd
, 0 );
6249 /* test empty rect */
6250 SetRect( &rect
, 10, 10, 10, 15 );
6251 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
6252 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6253 check_update_rgn( hwnd
, 0 );
6255 /* flush pending messages */
6259 GetClientRect( hwnd
, &rect
);
6260 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
6261 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
6262 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
6264 trace("testing InvalidateRect(0, NULL, FALSE)\n");
6265 SetRectEmpty( &rect
);
6266 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) should fail\n");
6267 check_update_rgn( hwnd
, hrgn
);
6268 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
6270 ok_sequence( WmPaint
, "Paint", FALSE
);
6271 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
6272 check_update_rgn( hwnd
, 0 );
6274 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
6275 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
6277 trace("testing ValidateRect(0, NULL)\n");
6278 SetRectEmpty( &rect
);
6279 if (ValidateRect(0, &rect
)) /* not supported on Win9x */
6281 check_update_rgn( hwnd
, hrgn
);
6282 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
6284 ok_sequence( WmPaint
, "Paint", FALSE
);
6285 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
6286 check_update_rgn( hwnd
, 0 );
6289 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
6290 SetLastError(0xdeadbeef);
6291 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
6292 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
6293 "wrong error code %d\n", GetLastError());
6294 check_update_rgn( hwnd
, 0 );
6296 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
6298 trace("testing ValidateRgn(0, NULL)\n");
6299 SetLastError(0xdeadbeef);
6300 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
6301 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
6302 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
6303 "wrong error code %d\n", GetLastError());
6304 check_update_rgn( hwnd
, 0 );
6306 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
6308 trace("testing UpdateWindow(NULL)\n");
6309 SetLastError(0xdeadbeef);
6310 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
6311 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
6312 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
6313 "wrong error code %d\n", GetLastError());
6314 check_update_rgn( hwnd
, 0 );
6316 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
6318 /* now with frame */
6319 SetRectRgn( hrgn
, -5, -5, 20, 20 );
6321 /* flush pending messages */
6324 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6325 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
6327 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
6328 check_update_rgn( hwnd
, hrgn
);
6331 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
6332 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
6335 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
6336 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
6338 GetClientRect( hwnd
, &rect
);
6339 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
6340 check_update_rgn( hwnd
, hrgn
);
6343 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
6344 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
6347 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
6348 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
6349 check_update_rgn( hwnd
, 0 );
6352 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
6353 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
6354 check_update_rgn( hwnd
, 0 );
6357 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6358 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
6359 SetRectRgn( hrgn
, 0, 0, 50, 100 );
6360 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
6361 SetRectRgn( hrgn
, 50, 0, 100, 100 );
6362 check_update_rgn( hwnd
, hrgn
);
6363 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
6364 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
6365 check_update_rgn( hwnd
, 0 );
6368 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6369 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
6370 SetRectRgn( hrgn
, 0, 0, 100, 50 );
6371 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
6372 ok_sequence( WmErase
, "Erase", FALSE
);
6373 SetRectRgn( hrgn
, 0, 50, 100, 100 );
6374 check_update_rgn( hwnd
, hrgn
);
6377 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6378 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
6379 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6380 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
6381 ok_sequence( WmPaint
, "Paint", FALSE
);
6384 SetRectRgn( hrgn
, -4, -4, -2, -2 );
6385 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6386 SetRectRgn( hrgn
, -200, -200, -198, -198 );
6387 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
6388 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
6391 SetRectRgn( hrgn
, -4, -4, -2, -2 );
6392 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6393 SetRectRgn( hrgn
, -4, -4, -3, -3 );
6394 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
6395 SetRectRgn( hrgn
, 0, 0, 1, 1 );
6396 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
6397 ok_sequence( WmPaint
, "Paint", FALSE
);
6400 SetRectRgn( hrgn
, -4, -4, -1, -1 );
6401 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6402 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
6403 /* make sure no WM_PAINT was generated */
6405 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
6408 SetRectRgn( hrgn
, -4, -4, -1, -1 );
6409 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6410 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
6412 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
6414 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
6415 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
6416 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
6417 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
6418 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
6419 /* this will send WM_NCPAINT and validate the non client area */
6420 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
6421 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
6423 DispatchMessageA( &msg
);
6425 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
6427 DestroyWindow( hwnd
);
6429 /* now test with a child window */
6431 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
6432 100, 100, 200, 200, 0, 0, 0, NULL
);
6433 ok (hparent
!= 0, "Failed to create parent window\n");
6435 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
6436 10, 10, 100, 100, hparent
, 0, 0, NULL
);
6437 ok (hchild
!= 0, "Failed to create child window\n");
6439 ShowWindow( hparent
, SW_SHOW
);
6440 UpdateWindow( hparent
);
6441 UpdateWindow( hchild
);
6444 log_all_parent_messages
++;
6446 SetRect( &rect
, 0, 0, 50, 50 );
6447 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6448 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
6449 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
6451 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6453 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
6454 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
6455 check_update_rgn( hchild
, hrgn
);
6456 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6457 check_update_rgn( hparent
, hrgn
);
6458 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6459 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
6460 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
6461 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
6464 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
6466 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
6467 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6468 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
6469 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
6470 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
6472 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
6473 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
6474 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
6476 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
6478 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
6479 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6480 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
6482 /* flush all paint messages */
6486 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
6487 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
6488 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6489 check_update_rgn( hparent
, hrgn
);
6490 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
6491 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6492 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6493 check_update_rgn( hparent
, hrgn
);
6495 /* flush all paint messages */
6497 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
6500 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
6501 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6502 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6503 check_update_rgn( hparent
, hrgn
);
6504 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
6505 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6506 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
6507 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
6508 check_update_rgn( hparent
, hrgn
);
6509 /* flush all paint messages */
6513 /* same as above but parent gets completely validated */
6514 SetRect( &rect
, 20, 20, 30, 30 );
6515 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6516 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6517 check_update_rgn( hparent
, hrgn
);
6518 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
6519 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6520 check_update_rgn( hparent
, 0 ); /* no update region */
6522 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
6524 /* make sure RDW_VALIDATE on child doesn't have the same effect */
6526 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6527 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6528 check_update_rgn( hparent
, hrgn
);
6529 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
6530 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6531 check_update_rgn( hparent
, hrgn
);
6533 /* same as above but normal WM_PAINT doesn't validate parent */
6535 SetRect( &rect
, 20, 20, 30, 30 );
6536 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6537 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6538 check_update_rgn( hparent
, hrgn
);
6539 /* no WM_PAINT in child while parent still pending */
6540 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6541 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
6542 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6543 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
6546 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6547 /* no WM_PAINT in child while parent still pending */
6548 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6549 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
6550 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
6551 /* now that parent is valid child should get WM_PAINT */
6552 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6553 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6554 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6555 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
6557 /* same thing with WS_CLIPCHILDREN in parent */
6559 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
6560 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
6561 /* changing style invalidates non client area, but we need to invalidate something else to see it */
6562 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
6563 ok_sequence( WmEmptySeq
, "No message", FALSE
);
6564 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
6565 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
6568 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
6569 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6570 check_update_rgn( hparent
, hrgn
);
6571 /* no WM_PAINT in child while parent still pending */
6572 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6573 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
6574 /* WM_PAINT in parent first */
6575 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6576 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
6578 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
6580 SetRect( &rect
, 0, 0, 30, 30 );
6581 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
6582 SetRectRgn( hrgn
, 0, 0, 30, 30 );
6583 check_update_rgn( hparent
, hrgn
);
6585 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
6587 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
6589 SetRect( &rect
, -10, 0, 30, 30 );
6590 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
6591 SetRect( &rect
, 0, 0, 20, 20 );
6592 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
6593 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
6594 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
6596 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
6598 SetRect( &rect
, -10, 0, 30, 30 );
6599 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
6600 SetRect( &rect
, 0, 0, 100, 100 );
6601 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
6602 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
6603 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
6604 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6605 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
6607 /* test RDW_INTERNALPAINT behavior */
6610 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
6612 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
6614 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
6616 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
6618 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
6620 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
6622 assert( GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
);
6623 UpdateWindow( hparent
);
6626 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
6627 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6628 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
6629 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6631 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
6633 UpdateWindow( hparent
);
6636 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
6637 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6638 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
6639 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6641 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
6643 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
6644 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
6645 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
6647 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
6649 assert( !(GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
) );
6650 UpdateWindow( hparent
);
6653 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
6654 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6655 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
6656 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6658 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
6660 UpdateWindow( hparent
);
6663 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
6664 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6665 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
6666 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6668 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
6670 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
6671 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
6673 UpdateWindow( hparent
);
6676 trace("testing SetWindowPos(-10000, -10000) on child\n");
6677 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
6678 check_update_rgn( hchild
, 0 );
6681 #if 0 /* this one doesn't pass under Wine yet */
6682 UpdateWindow( hparent
);
6685 trace("testing ShowWindow(SW_MINIMIZE) on child\n");
6686 ShowWindow( hchild
, SW_MINIMIZE
);
6687 check_update_rgn( hchild
, 0 );
6691 UpdateWindow( hparent
);
6694 trace("testing SetWindowPos(-10000, -10000) on parent\n");
6695 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
6696 check_update_rgn( hparent
, 0 );
6699 log_all_parent_messages
--;
6700 DestroyWindow( hparent
);
6701 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
6703 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
6705 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
6706 100, 100, 200, 200, 0, 0, 0, NULL
);
6707 ok (hparent
!= 0, "Failed to create parent window\n");
6709 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
6710 10, 10, 100, 100, hparent
, 0, 0, NULL
);
6711 ok (hchild
!= 0, "Failed to create child window\n");
6713 ShowWindow( hparent
, SW_SHOW
);
6714 UpdateWindow( hparent
);
6715 UpdateWindow( hchild
);
6719 /* moving child outside of parent boundaries changes update region */
6720 SetRect( &rect
, 0, 0, 40, 40 );
6721 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
6722 SetRectRgn( hrgn
, 0, 0, 40, 40 );
6723 check_update_rgn( hchild
, hrgn
);
6724 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
6725 SetRectRgn( hrgn
, 10, 0, 40, 40 );
6726 check_update_rgn( hchild
, hrgn
);
6727 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
6728 SetRectRgn( hrgn
, 10, 10, 40, 40 );
6729 check_update_rgn( hchild
, hrgn
);
6731 /* moving parent off-screen does too */
6732 SetRect( &rect
, 0, 0, 100, 100 );
6733 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
6734 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6735 check_update_rgn( hparent
, hrgn
);
6736 SetRectRgn( hrgn
, 10, 10, 40, 40 );
6737 check_update_rgn( hchild
, hrgn
);
6738 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
6739 SetRectRgn( hrgn
, 20, 20, 100, 100 );
6740 check_update_rgn( hparent
, hrgn
);
6741 SetRectRgn( hrgn
, 30, 30, 40, 40 );
6742 check_update_rgn( hchild
, hrgn
);
6744 /* invalidated region is cropped by the parent rects */
6745 SetRect( &rect
, 0, 0, 50, 50 );
6746 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
6747 SetRectRgn( hrgn
, 30, 30, 50, 50 );
6748 check_update_rgn( hchild
, hrgn
);
6750 DestroyWindow( hparent
);
6751 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
6754 DeleteObject( hrgn
);
6755 DeleteObject( hrgn2
);
6766 static DWORD WINAPI
thread_proc(void *param
)
6769 struct wnd_event
*wnd_event
= param
;
6771 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
6772 100, 100, 200, 200, 0, 0, 0, NULL
);
6773 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
6775 SetEvent(wnd_event
->start_event
);
6777 while (GetMessageA(&msg
, 0, 0, 0))
6779 TranslateMessage(&msg
);
6780 DispatchMessageA(&msg
);
6783 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
6788 static DWORD CALLBACK
create_grand_child_thread( void *param
)
6790 struct wnd_event
*wnd_event
= param
;
6794 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
6795 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
6796 ok (hchild
!= 0, "Failed to create child window\n");
6799 SetEvent( wnd_event
->start_event
);
6803 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
6804 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
6805 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6810 static DWORD CALLBACK
create_child_thread( void *param
)
6812 struct wnd_event
*wnd_event
= param
;
6813 struct wnd_event child_event
;
6817 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
6818 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
6819 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
6820 SetFocus( child_event
.hwnd
);
6823 child_event
.start_event
= wnd_event
->start_event
;
6824 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
6827 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
6828 if (ret
!= 1) break;
6829 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6831 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
6832 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
6836 static const char manifest_dep
[] =
6837 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
6838 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
6839 " <file name=\"testdep.dll\" />"
6842 static const char manifest_main
[] =
6843 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
6844 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
6846 " <dependentAssembly>"
6847 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
6848 " </dependentAssembly>"
6852 static void create_manifest_file(const char *filename
, const char *manifest
)
6854 WCHAR path
[MAX_PATH
];
6858 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
6859 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
6860 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
6861 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
6865 static HANDLE
test_create(const char *file
)
6867 WCHAR path
[MAX_PATH
];
6871 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
6872 memset(&actctx
, 0, sizeof(ACTCTXW
));
6873 actctx
.cbSize
= sizeof(ACTCTXW
);
6874 actctx
.lpSource
= path
;
6876 handle
= pCreateActCtxW(&actctx
);
6877 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %u\n", GetLastError());
6879 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%d\n", actctx
.cbSize
);
6880 ok(actctx
.dwFlags
== 0, "dwFlags=%d\n", actctx
.dwFlags
);
6881 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
6882 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
6883 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
6884 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
6885 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
6886 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
6887 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
6892 static void test_interthread_messages(void)
6894 HANDLE hThread
, context
, handle
, event
;
6900 int len
, expected_len
;
6901 struct wnd_event wnd_event
;
6904 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
6905 if (!wnd_event
.start_event
)
6907 win_skip("skipping interthread message test under win9x\n");
6911 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
6912 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
6914 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
6916 CloseHandle(wnd_event
.start_event
);
6918 SetLastError(0xdeadbeef);
6919 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
6920 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
6921 "wrong error code %d\n", GetLastError());
6923 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
6924 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
6926 expected_len
= lstrlenA("window caption text");
6927 memset(buf
, 0, sizeof(buf
));
6928 SetLastError(0xdeadbeef);
6929 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
6930 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
6931 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
6933 msg
.hwnd
= wnd_event
.hwnd
;
6934 msg
.message
= WM_GETTEXT
;
6935 msg
.wParam
= sizeof(buf
);
6936 msg
.lParam
= (LPARAM
)buf
;
6937 memset(buf
, 0, sizeof(buf
));
6938 SetLastError(0xdeadbeef);
6939 len
= DispatchMessageA(&msg
);
6940 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
6941 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len
, GetLastError());
6943 /* the following test causes an exception in user.exe under win9x */
6944 msg
.hwnd
= wnd_event
.hwnd
;
6945 msg
.message
= WM_TIMER
;
6947 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
6948 SetLastError(0xdeadbeef);
6949 len
= DispatchMessageA(&msg
);
6950 ok(!len
&& GetLastError() == 0xdeadbeef,
6951 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len
, GetLastError());
6953 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
6954 ok( ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
6956 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
6957 CloseHandle(hThread
);
6959 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
6961 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6962 100, 100, 200, 200, 0, 0, 0, NULL
);
6963 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
6966 log_all_parent_messages
++;
6967 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
6968 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
6969 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
6972 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
6973 if (ret
!= 1) break;
6974 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6976 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
6977 /* now wait for the thread without processing messages; this shouldn't deadlock */
6978 SetEvent( wnd_event
.stop_event
);
6979 ret
= WaitForSingleObject( hThread
, 5000 );
6980 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
6981 CloseHandle( hThread
);
6983 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
6984 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
6985 CloseHandle( wnd_event
.grand_child
);
6987 CloseHandle( wnd_event
.start_event
);
6988 CloseHandle( wnd_event
.stop_event
);
6990 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
6991 log_all_parent_messages
--;
6992 DestroyWindow( wnd_event
.hwnd
);
6994 /* activation context tests */
6995 if (!pActivateActCtx
)
6997 win_skip("Activation contexts are not supported, skipping\n");
7001 create_manifest_file("testdep1.manifest", manifest_dep
);
7002 create_manifest_file("main.manifest", manifest_main
);
7004 context
= test_create("main.manifest");
7005 DeleteFileA("testdep1.manifest");
7006 DeleteFileA("main.manifest");
7008 handle
= (void*)0xdeadbeef;
7009 ret
= pGetCurrentActCtx(&handle
);
7010 ok(ret
, "GetCurentActCtx failed: %u\n", GetLastError());
7011 ok(handle
== 0, "active context %p\n", handle
);
7013 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
7014 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
7015 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
7016 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7017 CloseHandle(wnd_event
.start_event
);
7019 /* context is activated after thread creation, so it doesn't inherit it by default */
7020 ret
= pActivateActCtx(context
, &cookie
);
7021 ok(ret
, "activation failed: %u\n", GetLastError());
7024 ret
= pGetCurrentActCtx(&handle
);
7025 ok(ret
, "GetCurentActCtx failed: %u\n", GetLastError());
7026 ok(handle
!= 0, "active context %p\n", handle
);
7027 pReleaseActCtx(handle
);
7029 /* destination window will test for active context */
7030 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
7031 ok(ret
, "thread window returned %d\n", ret
);
7033 event
= CreateEventW(NULL
, 0, 0, NULL
);
7034 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
7035 ok(ret
, "thread window returned %d\n", ret
);
7036 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7039 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
7040 ok(ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
7042 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7043 CloseHandle(hThread
);
7045 ret
= pDeactivateActCtx(0, cookie
);
7046 ok(ret
, "DeactivateActCtx failed: %u\n", GetLastError());
7047 pReleaseActCtx(context
);
7051 static const struct message WmVkN
[] = {
7052 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7053 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7054 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7055 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
7056 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
7057 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7058 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7059 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7062 static const struct message WmShiftVkN
[] = {
7063 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7064 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7065 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
7066 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7067 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7068 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7069 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
7070 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
7071 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7072 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7073 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7074 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
7075 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7076 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7079 static const struct message WmCtrlVkN
[] = {
7080 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7081 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7082 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7083 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7084 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7085 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7086 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
7087 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
7088 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7089 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7090 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7091 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7092 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7093 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7096 static const struct message WmCtrlVkN_2
[] = {
7097 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7098 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7099 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7100 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7101 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7102 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
7103 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7104 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7105 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7106 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7107 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7108 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7111 static const struct message WmAltVkN
[] = {
7112 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7113 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7114 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7115 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
7116 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
7117 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
7118 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
7119 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
7120 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
7121 { HCBT_SYSCOMMAND
, hook
},
7122 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7123 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
7124 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
7125 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
7126 { WM_INITMENU
, sent
|defwinproc
},
7127 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7128 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
7129 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
7130 { WM_CAPTURECHANGED
, sent
|defwinproc
},
7131 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
7132 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7133 { WM_EXITMENULOOP
, sent
|defwinproc
},
7134 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
7135 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
7136 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7137 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7138 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7139 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7140 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7141 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7144 static const struct message WmAltVkN_2
[] = {
7145 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7146 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7147 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7148 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
7149 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
7150 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
7151 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7152 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7153 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7154 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7155 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7156 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7159 static const struct message WmCtrlAltVkN
[] = {
7160 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7161 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7162 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7163 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7164 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7165 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7166 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
7167 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
7168 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
7169 { WM_CHAR
, optional
},
7170 { WM_CHAR
, sent
|optional
},
7171 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7172 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7173 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7174 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7175 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7176 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7177 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7178 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7179 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7182 static const struct message WmCtrlShiftVkN
[] = {
7183 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7184 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7185 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7186 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7187 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7188 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
7189 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7190 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7191 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
7192 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7193 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7194 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7195 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
7196 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7197 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7198 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7199 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7200 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7203 static const struct message WmCtrlAltShiftVkN
[] = {
7204 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7205 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7206 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7207 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7208 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7209 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7210 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
7211 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
7212 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
7213 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
7214 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
7215 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
7216 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7217 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7218 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7219 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
7220 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
7221 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
7222 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7223 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7224 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7225 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7226 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7227 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7230 static const struct message WmAltPressRelease
[] = {
7231 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7232 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7233 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7234 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7235 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7236 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7237 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
7238 { HCBT_SYSCOMMAND
, hook
},
7239 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7240 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
7241 { WM_INITMENU
, sent
|defwinproc
},
7242 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7243 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
) },
7244 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
7246 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
7248 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7249 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
7250 { WM_CAPTURECHANGED
, sent
|defwinproc
},
7251 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
7252 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7253 { WM_EXITMENULOOP
, sent
|defwinproc
},
7254 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7255 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7256 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7259 static const struct message WmShiftMouseButton
[] = {
7260 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7261 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7262 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
7263 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
7264 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
7265 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
7266 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
7267 { WM_LBUTTONUP
, wparam
, MK_SHIFT
, 0 },
7268 { WM_LBUTTONUP
, sent
|wparam
, MK_SHIFT
, 0 },
7269 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
7270 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7271 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7274 static const struct message WmF1Seq
[] = {
7275 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
7276 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
7277 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
7278 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
7279 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
7280 { WM_HELP
, sent
|defwinproc
},
7281 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
7282 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
7283 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
7286 static const struct message WmVkAppsSeq
[] = {
7287 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
7288 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
7289 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
7290 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
7291 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
7292 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
7293 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
7294 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
7297 static const struct message WmVkF10Seq
[] = {
7298 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
7299 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
7300 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
7301 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
7302 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
7303 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
7304 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
7305 { HCBT_SYSCOMMAND
, hook
},
7306 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7307 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
7308 { WM_INITMENU
, sent
|defwinproc
},
7309 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7310 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
) },
7311 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
7313 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
7315 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
7316 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7317 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
7318 { WM_CAPTURECHANGED
, sent
|defwinproc
},
7319 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
7320 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7321 { WM_EXITMENULOOP
, sent
|defwinproc
},
7322 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
7323 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
7324 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
7327 static const struct message WmShiftF10Seq
[] = {
7328 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7329 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7330 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
7331 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
7332 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
7333 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
7334 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
7335 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
7336 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
7337 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
7338 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
7339 { HCBT_SYSCOMMAND
, hook
},
7340 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7341 { WM_INITMENU
, sent
|defwinproc
},
7342 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
) },
7343 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
7344 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
7345 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7346 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
7347 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7348 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
7349 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
7350 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
7354 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
7358 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
7360 struct recvd_message log_msg
;
7362 /* ignore some unwanted messages */
7363 if (msg
.message
== WM_MOUSEMOVE
||
7364 msg
.message
== WM_TIMER
||
7365 ignore_message( msg
.message
))
7368 log_msg
.hwnd
= msg
.hwnd
;
7369 log_msg
.message
= msg
.message
;
7370 log_msg
.flags
= wparam
|lparam
;
7371 log_msg
.wParam
= msg
.wParam
;
7372 log_msg
.lParam
= msg
.lParam
;
7373 log_msg
.descr
= "accel";
7374 add_message(&log_msg
);
7376 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
7378 TranslateMessage(&msg
);
7379 DispatchMessageA(&msg
);
7384 static void test_accelerators(void)
7390 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7391 100, 100, 200, 200, 0, 0, 0, NULL
);
7400 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
7402 state
= GetKeyState(VK_SHIFT
);
7403 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
7404 state
= GetKeyState(VK_CAPITAL
);
7405 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
7407 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
7408 assert(hAccel
!= 0);
7411 pump_msg_loop(hwnd
, 0);
7414 trace("testing VK_N press/release\n");
7416 keybd_event('N', 0, 0, 0);
7417 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7418 pump_msg_loop(hwnd
, hAccel
);
7419 if (!sequence_cnt
) /* we didn't get any message */
7421 skip( "queuing key events not supported\n" );
7424 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
7426 trace("testing Shift+VK_N press/release\n");
7428 keybd_event(VK_SHIFT
, 0, 0, 0);
7429 keybd_event('N', 0, 0, 0);
7430 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7431 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7432 pump_msg_loop(hwnd
, hAccel
);
7433 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
7435 trace("testing Ctrl+VK_N press/release\n");
7437 keybd_event(VK_CONTROL
, 0, 0, 0);
7438 keybd_event('N', 0, 0, 0);
7439 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7440 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7441 pump_msg_loop(hwnd
, hAccel
);
7442 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
7444 trace("testing Alt+VK_N press/release\n");
7446 keybd_event(VK_MENU
, 0, 0, 0);
7447 keybd_event('N', 0, 0, 0);
7448 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7449 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7450 pump_msg_loop(hwnd
, hAccel
);
7451 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
7453 trace("testing Ctrl+Alt+VK_N press/release 1\n");
7455 keybd_event(VK_CONTROL
, 0, 0, 0);
7456 keybd_event(VK_MENU
, 0, 0, 0);
7457 keybd_event('N', 0, 0, 0);
7458 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7459 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7460 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7461 pump_msg_loop(hwnd
, hAccel
);
7462 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
7464 ret
= DestroyAcceleratorTable(hAccel
);
7465 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
7467 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
7468 assert(hAccel
!= 0);
7470 trace("testing VK_N press/release\n");
7472 keybd_event('N', 0, 0, 0);
7473 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7474 pump_msg_loop(hwnd
, hAccel
);
7475 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
7477 trace("testing Shift+VK_N press/release\n");
7479 keybd_event(VK_SHIFT
, 0, 0, 0);
7480 keybd_event('N', 0, 0, 0);
7481 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7482 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7483 pump_msg_loop(hwnd
, hAccel
);
7484 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
7486 trace("testing Ctrl+VK_N press/release 2\n");
7488 keybd_event(VK_CONTROL
, 0, 0, 0);
7489 keybd_event('N', 0, 0, 0);
7490 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7491 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7492 pump_msg_loop(hwnd
, hAccel
);
7493 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
7495 trace("testing Alt+VK_N press/release 2\n");
7497 keybd_event(VK_MENU
, 0, 0, 0);
7498 keybd_event('N', 0, 0, 0);
7499 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7500 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7501 pump_msg_loop(hwnd
, hAccel
);
7502 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
7504 trace("testing Ctrl+Alt+VK_N press/release 2\n");
7506 keybd_event(VK_CONTROL
, 0, 0, 0);
7507 keybd_event(VK_MENU
, 0, 0, 0);
7508 keybd_event('N', 0, 0, 0);
7509 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7510 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7511 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7512 pump_msg_loop(hwnd
, hAccel
);
7513 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
7515 trace("testing Ctrl+Shift+VK_N press/release\n");
7517 keybd_event(VK_CONTROL
, 0, 0, 0);
7518 keybd_event(VK_SHIFT
, 0, 0, 0);
7519 keybd_event('N', 0, 0, 0);
7520 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7521 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7522 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7523 pump_msg_loop(hwnd
, hAccel
);
7524 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
7526 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
7528 keybd_event(VK_CONTROL
, 0, 0, 0);
7529 keybd_event(VK_MENU
, 0, 0, 0);
7530 keybd_event(VK_SHIFT
, 0, 0, 0);
7531 keybd_event('N', 0, 0, 0);
7532 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7533 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7534 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7535 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7536 pump_msg_loop(hwnd
, hAccel
);
7537 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
7539 ret
= DestroyAcceleratorTable(hAccel
);
7540 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
7543 trace("testing Alt press/release\n");
7545 keybd_event(VK_MENU
, 0, 0, 0);
7546 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7547 keybd_event(VK_MENU
, 0, 0, 0);
7548 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7549 pump_msg_loop(hwnd
, 0);
7550 /* this test doesn't pass in Wine for managed windows */
7551 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
7553 trace("testing VK_F1 press/release\n");
7554 keybd_event(VK_F1
, 0, 0, 0);
7555 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
7556 pump_msg_loop(hwnd
, 0);
7557 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
7559 trace("testing VK_APPS press/release\n");
7560 keybd_event(VK_APPS
, 0, 0, 0);
7561 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
7562 pump_msg_loop(hwnd
, 0);
7563 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
7565 trace("testing VK_F10 press/release\n");
7566 keybd_event(VK_F10
, 0, 0, 0);
7567 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
7568 keybd_event(VK_F10
, 0, 0, 0);
7569 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
7570 pump_msg_loop(hwnd
, 0);
7571 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", TRUE
);
7573 trace("testing SHIFT+F10 press/release\n");
7574 keybd_event(VK_SHIFT
, 0, 0, 0);
7575 keybd_event(VK_F10
, 0, 0, 0);
7576 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
7577 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7578 keybd_event(VK_ESCAPE
, 0, 0, 0);
7579 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
7580 pump_msg_loop(hwnd
, 0);
7581 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
7583 trace("testing Shift+MouseButton press/release\n");
7584 /* first, move mouse pointer inside of the window client area */
7585 GetClientRect(hwnd
, &rc
);
7586 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
7587 rc
.left
+= (rc
.right
- rc
.left
)/2;
7588 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
7589 SetCursorPos(rc
.left
, rc
.top
);
7590 SetActiveWindow(hwnd
);
7595 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
7598 keybd_event(VK_SHIFT
, 0, 0, 0);
7599 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
7600 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
7601 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7602 pump_msg_loop(hwnd
, 0);
7603 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
7604 if (i
< sequence_cnt
)
7605 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
7607 skip( "Shift+MouseButton event didn't get to the window\n" );
7611 if (hAccel
) DestroyAcceleratorTable(hAccel
);
7612 DestroyWindow(hwnd
);
7615 /************* window procedures ********************/
7617 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
7618 WPARAM wParam
, LPARAM lParam
)
7620 static LONG defwndproc_counter
= 0;
7621 static LONG beginpaint_counter
= 0;
7623 struct recvd_message msg
;
7625 if (ignore_message( message
)) return 0;
7631 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7632 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
7633 "wrong WS_DISABLED state: %ld != %d\n", wParam
, !(style
& WS_DISABLED
));
7637 case WM_CAPTURECHANGED
:
7638 if (test_DestroyWindow_flag
)
7640 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7641 if (style
& WS_CHILD
)
7642 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
7643 else if (style
& WS_POPUP
)
7644 lParam
= WND_POPUP_ID
;
7646 lParam
= WND_PARENT_ID
;
7654 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
7655 capture
= GetCapture();
7658 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
7659 trace("current capture %p, releasing...\n", capture
);
7666 ok(pGetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
7667 if (test_DestroyWindow_flag
)
7669 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7670 if (style
& WS_CHILD
)
7671 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
7672 else if (style
& WS_POPUP
)
7673 lParam
= WND_POPUP_ID
;
7675 lParam
= WND_PARENT_ID
;
7679 /* test_accelerators() depends on this */
7685 HANDLE handle
, event
= (HANDLE
)lParam
;
7688 handle
= (void*)0xdeadbeef;
7689 ret
= pGetCurrentActCtx(&handle
);
7690 ok(ret
, "failed to get current context, %u\n", GetLastError());
7691 ok(handle
== 0, "got active context %p\n", handle
);
7692 if (event
) SetEvent(event
);
7698 case WM_MOUSEACTIVATE
:
7699 case WM_NCMOUSEMOVE
:
7706 msg
.message
= message
;
7707 msg
.flags
= sent
|wparam
|lparam
;
7708 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7709 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
7710 msg
.wParam
= wParam
;
7711 msg
.lParam
= lParam
;
7712 msg
.descr
= "MsgCheckProc";
7715 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
7717 HWND parent
= GetParent(hwnd
);
7719 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
7721 GetClientRect(parent
, &rc
);
7722 trace("parent %p client size = (%d x %d)\n", parent
, rc
.right
, rc
.bottom
);
7723 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
7724 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
7725 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
7726 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
7727 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
7728 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
7730 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %d != %d\n",
7731 minmax
->ptMaxSize
.x
, rc
.right
);
7732 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %d != %d\n",
7733 minmax
->ptMaxSize
.y
, rc
.bottom
);
7736 if (message
== WM_PAINT
)
7739 beginpaint_counter
++;
7740 BeginPaint( hwnd
, &ps
);
7741 beginpaint_counter
--;
7742 EndPaint( hwnd
, &ps
);
7746 defwndproc_counter
++;
7747 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
7748 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7749 defwndproc_counter
--;
7754 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7756 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
7759 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7761 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
7764 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7766 static LONG defwndproc_counter
= 0;
7768 struct recvd_message msg
;
7770 if (ignore_message( message
)) return 0;
7774 case WM_QUERYENDSESSION
:
7776 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
7781 msg
.message
= message
;
7782 msg
.flags
= sent
|wparam
|lparam
;
7783 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7784 msg
.wParam
= wParam
;
7785 msg
.lParam
= lParam
;
7786 msg
.descr
= "popup";
7789 if (message
== WM_CREATE
)
7791 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
7792 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
7795 defwndproc_counter
++;
7796 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7797 defwndproc_counter
--;
7802 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7804 static LONG defwndproc_counter
= 0;
7805 static LONG beginpaint_counter
= 0;
7807 struct recvd_message msg
;
7809 if (ignore_message( message
)) return 0;
7811 if (log_all_parent_messages
||
7812 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
7813 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
7814 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
7815 message
== WM_DRAWITEM
|| message
== WM_COMMAND
||
7816 message
== WM_IME_SETCONTEXT
)
7825 case WM_NCMOUSEMOVE
:
7831 INT ret
= GetClipBox((HDC
)wParam
, &rc
);
7833 trace("WM_ERASEBKGND: GetClipBox()=%d, (%d,%d-%d,%d)\n",
7834 ret
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
7840 msg
.message
= message
;
7841 msg
.flags
= sent
|parent
|wparam
|lparam
;
7842 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7843 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
7844 msg
.wParam
= wParam
;
7845 msg
.lParam
= lParam
;
7846 msg
.descr
= "parent";
7850 if (message
== WM_PAINT
)
7853 beginpaint_counter
++;
7854 BeginPaint( hwnd
, &ps
);
7855 beginpaint_counter
--;
7856 EndPaint( hwnd
, &ps
);
7860 defwndproc_counter
++;
7861 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7862 defwndproc_counter
--;
7867 static INT_PTR CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
7869 if (message
== WM_CREATE
)
7870 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
7871 else if (message
== WM_CLOSE
)
7873 /* Only the first WM_QUIT will survive the window destruction */
7874 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
7875 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
7876 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
7879 return DefWindowProcA(hwnd
, message
, wp
, lp
);
7882 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7884 static LONG defwndproc_counter
= 0;
7886 struct recvd_message msg
;
7888 if (ignore_message( message
)) return 0;
7892 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
7893 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
7894 if (after_end_dialog
)
7895 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
7897 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
7901 msg
.message
= message
;
7902 msg
.flags
= sent
|wparam
|lparam
;
7903 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7904 msg
.wParam
= wParam
;
7905 msg
.lParam
= lParam
;
7906 msg
.descr
= "dialog";
7909 defwndproc_counter
++;
7910 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
7911 defwndproc_counter
--;
7916 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7918 static LONG defwndproc_counter
= 0;
7920 struct recvd_message msg
;
7922 /* log only specific messages we are interested in */
7925 #if 0 /* probably log these as well */
7933 case WM_GETMINMAXINFO
:
7934 case WM_WINDOWPOSCHANGING
:
7935 case WM_WINDOWPOSCHANGED
:
7938 default: /* ignore */
7939 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
7940 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7944 msg
.message
= message
;
7945 msg
.flags
= sent
|wparam
|lparam
;
7946 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7947 msg
.wParam
= wParam
;
7948 msg
.lParam
= lParam
;
7952 defwndproc_counter
++;
7953 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7954 defwndproc_counter
--;
7959 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
7963 case WM_CREATE
: return 0;
7972 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
7974 TranslateMessage(&msg2
);
7975 DispatchMessageA(&msg2
);
7979 else ok(broken(1), "infinite loop\n");
7981 paint_loop_done
= TRUE
;
7982 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
7985 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
7988 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7990 static LONG defwndproc_counter
= 0;
7992 struct recvd_message msg
;
7995 if (ignore_message( message
)) return 0;
7997 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
7998 message
== WM_HOTKEY
|| message
>= WM_APP
)
8001 msg
.message
= message
;
8002 msg
.flags
= sent
|wparam
|lparam
;
8003 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
8004 msg
.wParam
= wParam
;
8005 msg
.lParam
= lParam
;
8006 msg
.descr
= "HotkeyMsgCheckProcA";
8010 defwndproc_counter
++;
8011 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8012 defwndproc_counter
--;
8014 if (message
== WM_APP
)
8016 queue_status
= GetQueueStatus(QS_HOTKEY
);
8017 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
8018 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
8019 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
8020 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
8022 else if (message
== WM_APP
+1)
8024 queue_status
= GetQueueStatus(QS_HOTKEY
);
8025 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
8031 static BOOL
RegisterWindowClasses(void)
8037 cls
.lpfnWndProc
= MsgCheckProcA
;
8040 cls
.hInstance
= GetModuleHandleA(0);
8042 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
8043 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
8044 cls
.lpszMenuName
= NULL
;
8045 cls
.lpszClassName
= "TestWindowClass";
8046 if(!RegisterClassA(&cls
)) return FALSE
;
8048 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
8049 cls
.lpszClassName
= "HotkeyWindowClass";
8050 if(!RegisterClassA(&cls
)) return FALSE
;
8052 cls
.lpfnWndProc
= ShowWindowProcA
;
8053 cls
.lpszClassName
= "ShowWindowClass";
8054 if(!RegisterClassA(&cls
)) return FALSE
;
8056 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
8057 cls
.lpszClassName
= "TestPopupClass";
8058 if(!RegisterClassA(&cls
)) return FALSE
;
8060 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
8061 cls
.lpszClassName
= "TestParentClass";
8062 if(!RegisterClassA(&cls
)) return FALSE
;
8064 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
8065 cls
.lpszClassName
= "StopQuitClass";
8066 if(!RegisterClassA(&cls
)) return FALSE
;
8068 cls
.lpfnWndProc
= DefWindowProcA
;
8069 cls
.lpszClassName
= "SimpleWindowClass";
8070 if(!RegisterClassA(&cls
)) return FALSE
;
8072 cls
.lpfnWndProc
= PaintLoopProcA
;
8073 cls
.lpszClassName
= "PaintLoopWindowClass";
8074 if(!RegisterClassA(&cls
)) return FALSE
;
8076 cls
.style
= CS_NOCLOSE
;
8077 cls
.lpszClassName
= "NoCloseWindowClass";
8078 if(!RegisterClassA(&cls
)) return FALSE
;
8080 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
8082 cls
.hInstance
= GetModuleHandleA(0);
8083 cls
.hbrBackground
= 0;
8084 cls
.lpfnWndProc
= TestDlgProcA
;
8085 cls
.lpszClassName
= "TestDialogClass";
8086 if(!RegisterClassA(&cls
)) return FALSE
;
8089 clsW
.lpfnWndProc
= MsgCheckProcW
;
8090 clsW
.cbClsExtra
= 0;
8091 clsW
.cbWndExtra
= 0;
8092 clsW
.hInstance
= GetModuleHandleW(0);
8094 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
8095 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
8096 clsW
.lpszMenuName
= NULL
;
8097 clsW
.lpszClassName
= testWindowClassW
;
8098 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
8103 static BOOL
is_our_logged_class(HWND hwnd
)
8107 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
8109 if (!lstrcmpiA(buf
, "TestWindowClass") ||
8110 !lstrcmpiA(buf
, "ShowWindowClass") ||
8111 !lstrcmpiA(buf
, "TestParentClass") ||
8112 !lstrcmpiA(buf
, "TestPopupClass") ||
8113 !lstrcmpiA(buf
, "SimpleWindowClass") ||
8114 !lstrcmpiA(buf
, "TestDialogClass") ||
8115 !lstrcmpiA(buf
, "MDI_frame_class") ||
8116 !lstrcmpiA(buf
, "MDI_client_class") ||
8117 !lstrcmpiA(buf
, "MDI_child_class") ||
8118 !lstrcmpiA(buf
, "my_button_class") ||
8119 !lstrcmpiA(buf
, "my_edit_class") ||
8120 !lstrcmpiA(buf
, "static") ||
8121 !lstrcmpiA(buf
, "ListBox") ||
8122 !lstrcmpiA(buf
, "ComboBox") ||
8123 !lstrcmpiA(buf
, "MyDialogClass") ||
8124 !lstrcmpiA(buf
, "#32770") ||
8125 !lstrcmpiA(buf
, "#32768"))
8131 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
8135 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
8137 if (nCode
== HCBT_CLICKSKIPPED
)
8139 /* ignore this event, XP sends it a lot when switching focus between windows */
8140 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
8143 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
8145 struct recvd_message msg
;
8148 msg
.message
= nCode
;
8149 msg
.flags
= hook
|wparam
|lparam
;
8150 msg
.wParam
= wParam
;
8151 msg
.lParam
= lParam
;
8155 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
8158 if (nCode
== HCBT_DESTROYWND
)
8160 if (test_DestroyWindow_flag
)
8162 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
8163 if (style
& WS_CHILD
)
8164 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
8165 else if (style
& WS_POPUP
)
8166 lParam
= WND_POPUP_ID
;
8168 lParam
= WND_PARENT_ID
;
8172 /* Log also SetFocus(0) calls */
8173 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
8175 if (is_our_logged_class(hwnd
))
8177 struct recvd_message msg
;
8180 msg
.message
= nCode
;
8181 msg
.flags
= hook
|wparam
|lparam
;
8182 msg
.wParam
= wParam
;
8183 msg
.lParam
= lParam
;
8187 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
8190 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
8198 ok(thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
8200 /* ignore mouse cursor events */
8201 if (object_id
== OBJID_CURSOR
) return;
8203 if (!hwnd
|| is_our_logged_class(hwnd
))
8205 struct recvd_message msg
;
8208 msg
.message
= event
;
8209 msg
.flags
= winevent_hook
|wparam
|lparam
;
8210 msg
.wParam
= object_id
;
8211 msg
.lParam
= child_id
;
8217 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
8218 static const WCHAR wszAnsi
[] = {'U',0};
8220 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
8224 case CB_FINDSTRINGEXACT
:
8225 trace("String: %p\n", (LPCWSTR
)lParam
);
8226 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
8228 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
8232 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
8235 static const struct message WmGetTextLengthAfromW
[] = {
8236 { WM_GETTEXTLENGTH
, sent
},
8237 { WM_GETTEXT
, sent
|optional
},
8241 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
8243 /* dummy window proc for WM_GETTEXTLENGTH test */
8244 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
8248 case WM_GETTEXTLENGTH
:
8249 return lstrlenW(dummy_window_text
) + 37; /* some random length */
8251 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
8252 return lstrlenW( (LPWSTR
)lp
);
8254 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
8258 static void test_message_conversion(void)
8260 static const WCHAR wszMsgConversionClass
[] =
8261 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
8265 WNDPROC wndproc
, newproc
;
8269 cls
.lpfnWndProc
= MsgConversionProcW
;
8272 cls
.hInstance
= GetModuleHandleW(NULL
);
8274 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
8275 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
8276 cls
.lpszMenuName
= NULL
;
8277 cls
.lpszClassName
= wszMsgConversionClass
;
8278 /* this call will fail on Win9x, but that doesn't matter as this test is
8279 * meaningless on those platforms */
8280 if(!RegisterClassW(&cls
)) return;
8282 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
8283 100, 100, 200, 200, 0, 0, 0, NULL
);
8284 ok(hwnd
!= NULL
, "Window creation failed\n");
8288 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
8289 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8290 ok(lRes
== 0, "String should have been converted\n");
8291 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8292 ok(lRes
== 1, "String shouldn't have been converted\n");
8296 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
8297 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8298 ok(lRes
== 1, "String shouldn't have been converted\n");
8299 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8300 ok(lRes
== 1, "String shouldn't have been converted\n");
8302 /* Synchronous messages */
8304 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8305 ok(lRes
== 0, "String should have been converted\n");
8306 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8307 ok(lRes
== 1, "String shouldn't have been converted\n");
8309 /* Asynchronous messages */
8312 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8313 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8314 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8316 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8317 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8318 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8320 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8321 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8322 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8324 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8325 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8326 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8328 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8329 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8330 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8332 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8333 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8334 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8336 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
8337 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8338 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8340 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
8341 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8342 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8344 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
8346 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
8347 WS_OVERLAPPEDWINDOW
,
8348 100, 100, 200, 200, 0, 0, 0, NULL
);
8351 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
8352 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
8353 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
8354 "got bad length %ld\n", lRes
);
8357 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
8358 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
8359 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
8360 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
8361 "got bad length %ld\n", lRes
);
8363 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
8364 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
8365 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
8366 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
8367 NULL
, 0, NULL
, NULL
) ||
8368 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
8369 "got bad length %ld\n", lRes
);
8371 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
8372 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
8373 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
8374 NULL
, 0, NULL
, NULL
) ||
8375 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
8376 "got bad length %ld\n", lRes
);
8378 ret
= DestroyWindow(hwnd
);
8379 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
8389 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
8393 #define TIMER_ID 0x19
8394 #define TIMER_COUNT_EXPECTED 100
8395 #define TIMER_COUNT_TOLERANCE 10
8397 static int count
= 0;
8398 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
8403 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
8405 struct timer_info
*info
= x
;
8408 r
= KillTimer(info
->hWnd
, 0x19);
8409 ok(r
,"KillTimer failed in thread\n");
8410 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
8411 ok(r
,"SetTimer failed in thread\n");
8412 ok(r
==TIMER_ID
,"SetTimer id different\n");
8413 r
= SetEvent(info
->handles
[0]);
8414 ok(r
,"SetEvent failed in thread\n");
8418 static void test_timers(void)
8420 struct timer_info info
;
8425 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
8426 WS_OVERLAPPEDWINDOW
,
8427 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
8430 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
8431 ok(info
.id
, "SetTimer failed\n");
8432 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
8433 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
8434 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
8436 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
8438 WaitForSingleObject(info
.handles
[1], INFINITE
);
8440 CloseHandle(info
.handles
[0]);
8441 CloseHandle(info
.handles
[1]);
8443 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
8445 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
8446 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
8447 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
8448 * ±9 counts (~4 ms) around the expected value.
8451 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
8452 ok(id
!= 0, "did not get id from SetTimer.\n");
8453 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
8454 start
= GetTickCount();
8455 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
8456 DispatchMessageA(&msg
);
8457 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
8458 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
8459 || broken(abs(count
-43) < TIMER_COUNT_TOLERANCE
) /* w2k3, win8 */,
8460 "did not get expected count for minimum timeout (%d != ~%d).\n",
8461 count
, TIMER_COUNT_EXPECTED
);
8462 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
8463 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
8464 if (pSetSystemTimer
)
8469 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
8470 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
8471 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
8472 start
= GetTickCount();
8473 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
8475 if (msg
.message
== WM_SYSTIMER
)
8477 DispatchMessageA(&msg
);
8479 ok(abs(syscount
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
8480 || broken(abs(syscount
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
8481 || broken(syscount
> 4000 && syscount
< 12000) /* win2k3sp0 */,
8482 "did not get expected count for minimum timeout (%d != ~%d).\n",
8483 syscount
, TIMER_COUNT_EXPECTED
);
8484 todo_wine
ok(count
== 0, "did not get expected count for callback timeout (%d != 0).\n",
8486 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
8489 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
8492 static void test_timers_no_wnd(void)
8499 id
= SetTimer(NULL
, 0, 100, callback_count
);
8500 ok(id
!= 0, "did not get id from SetTimer.\n");
8501 id2
= SetTimer(NULL
, id
, 200, callback_count
);
8502 ok(id2
== id
, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2
, id
);
8504 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8505 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
8507 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8508 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
8509 KillTimer(NULL
, id
);
8511 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8512 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
8514 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
8515 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
8516 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
8517 * ±9 counts (~4 ms) around the expected value.
8520 id
= SetTimer(NULL
, 0, 0, callback_count
);
8521 ok(id
!= 0, "did not get id from SetTimer.\n");
8522 start
= GetTickCount();
8523 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, NULL
, 0, 0))
8524 DispatchMessageA(&msg
);
8525 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
8526 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */,
8527 "did not get expected count for minimum timeout (%d != ~%d).\n",
8528 count
, TIMER_COUNT_EXPECTED
);
8529 KillTimer(NULL
, id
);
8530 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
8533 /* Various win events with arbitrary parameters */
8534 static const struct message WmWinEventsSeq
[] = {
8535 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
8536 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8537 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
8538 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
8539 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
8540 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
8541 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
8542 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
8543 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
8544 /* our win event hook ignores OBJID_CURSOR events */
8545 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
8546 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
8547 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
8548 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
8549 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
8550 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
8551 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8552 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
8553 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
8554 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
8555 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
8556 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
8557 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
8558 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
8561 static const struct message WmWinEventCaretSeq
[] = {
8562 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
8563 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
8564 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
8565 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
8568 static const struct message WmWinEventCaretSeq_2
[] = {
8569 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
8570 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
8571 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
8574 static const struct message WmWinEventAlertSeq
[] = {
8575 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
8578 static const struct message WmWinEventAlertSeq_2
[] = {
8579 /* create window in the thread proc */
8580 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
8581 /* our test event */
8582 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
8585 static const struct message WmGlobalHookSeq_1
[] = {
8586 /* create window in the thread proc */
8587 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
8588 /* our test events */
8589 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
8590 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
8593 static const struct message WmGlobalHookSeq_2
[] = {
8594 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
8595 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
8596 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
8597 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
8601 static const struct message WmMouseLLHookSeq
[] = {
8602 { WM_MOUSEMOVE
, hook
},
8603 { WM_LBUTTONUP
, hook
},
8604 { WM_MOUSEMOVE
, hook
},
8608 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
8618 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
8620 if (!lstrcmpiA(buf
, "TestWindowClass") ||
8621 !lstrcmpiA(buf
, "static"))
8623 struct recvd_message msg
;
8626 msg
.message
= event
;
8627 msg
.flags
= winevent_hook
|wparam
|lparam
;
8628 msg
.wParam
= object_id
;
8629 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
8630 msg
.descr
= "WEH_2";
8636 static HHOOK hCBT_global_hook
;
8637 static DWORD cbt_global_hook_thread_id
;
8639 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
8644 if (nCode
== HCBT_SYSCOMMAND
)
8646 struct recvd_message msg
;
8649 msg
.message
= nCode
;
8650 msg
.flags
= hook
|wparam
|lparam
;
8651 msg
.wParam
= wParam
;
8652 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
8653 msg
.descr
= "CBT_2";
8656 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
8658 /* WH_MOUSE_LL hook */
8659 if (nCode
== HC_ACTION
)
8661 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
8663 /* we can't test for real mouse events */
8664 if (mhll
->flags
& LLMHF_INJECTED
)
8666 struct recvd_message msg
;
8668 memset (&msg
, 0, sizeof (msg
));
8669 msg
.message
= wParam
;
8671 msg
.descr
= "CBT_2";
8674 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
8677 /* Log also SetFocus(0) calls */
8678 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
8680 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
8682 if (!lstrcmpiA(buf
, "TestWindowClass") ||
8683 !lstrcmpiA(buf
, "static"))
8685 struct recvd_message msg
;
8688 msg
.message
= nCode
;
8689 msg
.flags
= hook
|wparam
|lparam
;
8690 msg
.wParam
= wParam
;
8691 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
8692 msg
.descr
= "CBT_2";
8696 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
8699 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
8703 HANDLE hevent
= *(HANDLE
*)param
;
8705 assert(pNotifyWinEvent
);
8707 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
8709 trace("created thread window %p\n", hwnd
);
8711 *(HWND
*)param
= hwnd
;
8714 /* this event should be received only by our new hook proc,
8715 * an old one does not expect an event from another thread.
8717 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
8720 while (GetMessageA(&msg
, 0, 0, 0))
8722 TranslateMessage(&msg
);
8723 DispatchMessageA(&msg
);
8728 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
8732 HANDLE hevent
= *(HANDLE
*)param
;
8735 /* these events should be received only by our new hook proc,
8736 * an old one does not expect an event from another thread.
8739 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
8741 trace("created thread window %p\n", hwnd
);
8743 *(HWND
*)param
= hwnd
;
8745 /* Windows doesn't like when a thread plays games with the focus,
8746 that leads to all kinds of misbehaviours and failures to activate
8747 a window. So, better keep next lines commented out.
8751 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
8752 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
8756 while (GetMessageA(&msg
, 0, 0, 0))
8758 TranslateMessage(&msg
);
8759 DispatchMessageA(&msg
);
8764 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
8768 HANDLE hevent
= *(HANDLE
*)param
;
8770 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
8772 trace("created thread window %p\n", hwnd
);
8774 *(HWND
*)param
= hwnd
;
8778 /* Windows doesn't like when a thread plays games with the focus,
8779 * that leads to all kinds of misbehaviours and failures to activate
8780 * a window. So, better don't generate a mouse click message below.
8782 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
8783 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
8784 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
8787 while (GetMessageA(&msg
, 0, 0, 0))
8789 TranslateMessage(&msg
);
8790 DispatchMessageA(&msg
);
8795 static void test_winevents(void)
8801 HANDLE hthread
, hevent
;
8803 HWINEVENTHOOK hhook
;
8804 const struct message
*events
= WmWinEventsSeq
;
8806 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
8807 WS_OVERLAPPEDWINDOW
,
8808 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
8812 /****** start of global hook test *************/
8813 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
8814 if (!hCBT_global_hook
)
8816 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
8817 skip( "cannot set global hook\n" );
8821 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8825 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
8826 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8828 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8830 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
8833 /* this one should be received only by old hook proc */
8834 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
8835 /* this one should be received only by old hook proc */
8836 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
8838 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
8840 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
8841 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
8843 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8844 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8845 CloseHandle(hthread
);
8846 CloseHandle(hevent
);
8847 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
8848 /****** end of global hook test *************/
8850 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
8852 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
8860 /* this test doesn't pass under Win9x */
8861 /* win2k ignores events with hwnd == 0 */
8862 SetLastError(0xdeadbeef);
8863 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
8864 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
8865 GetLastError() == 0xdeadbeef, /* Win9x */
8866 "unexpected error %d\n", GetLastError());
8867 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
8870 for (i
= 0; i
< sizeof(WmWinEventsSeq
)/sizeof(WmWinEventsSeq
[0]); i
++)
8871 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
8873 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
8875 /****** start of event filtering test *************/
8876 hhook
= pSetWinEventHook(
8877 EVENT_OBJECT_SHOW
, /* 0x8002 */
8878 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
8879 GetModuleHandleA(0), win_event_global_hook_proc
,
8880 GetCurrentProcessId(), 0,
8881 WINEVENT_INCONTEXT
);
8882 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
8884 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8888 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
8889 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8891 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8893 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
8896 /* this one should be received only by old hook proc */
8897 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
8898 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
8899 /* this one should be received only by old hook proc */
8900 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
8902 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
8904 ret
= pUnhookWinEvent(hhook
);
8905 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
8907 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8908 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8909 CloseHandle(hthread
);
8910 CloseHandle(hevent
);
8911 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
8912 /****** end of event filtering test *************/
8914 /****** start of out of context event test *************/
8915 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
8916 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
8917 WINEVENT_OUTOFCONTEXT
);
8918 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
8920 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8926 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
8927 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8929 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8931 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
8932 /* process pending winevent messages */
8933 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
8934 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
8937 /* this one should be received only by old hook proc */
8938 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
8939 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
8940 /* this one should be received only by old hook proc */
8941 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
8943 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
8944 /* process pending winevent messages */
8945 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
8946 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
8948 ret
= pUnhookWinEvent(hhook
);
8949 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
8951 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8952 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8953 CloseHandle(hthread
);
8954 CloseHandle(hevent
);
8955 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
8956 /****** end of out of context event test *************/
8958 /****** start of MOUSE_LL hook test *************/
8959 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
8960 /* WH_MOUSE_LL is not supported on Win9x platforms */
8961 if (!hCBT_global_hook
)
8963 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
8964 goto skip_mouse_ll_hook_test
;
8967 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8971 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
8972 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8974 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
8975 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8977 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
8980 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
8981 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
8982 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
8984 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
8986 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
8987 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
8989 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8990 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8991 CloseHandle(hthread
);
8992 CloseHandle(hevent
);
8993 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
8994 /****** end of MOUSE_LL hook test *************/
8995 skip_mouse_ll_hook_test
:
8997 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
9000 static void test_set_hook(void)
9004 HWINEVENTHOOK hwinevent_hook
;
9006 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
9007 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
9008 UnhookWindowsHookEx(hhook
);
9012 /* this test doesn't pass under Win9x: BUG! */
9013 SetLastError(0xdeadbeef);
9014 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
9015 ok(!hhook
, "global hook requires hModule != 0\n");
9016 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %d\n", GetLastError());
9019 SetLastError(0xdeadbeef);
9020 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
9021 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
9022 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
|| /* Win2k */
9023 GetLastError() == 0xdeadbeef, /* Win9x */
9024 "unexpected error %d\n", GetLastError());
9026 SetLastError(0xdeadbeef);
9027 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
9028 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
|| /* Win2k */
9029 GetLastError() == 0xdeadbeef, /* Win9x */
9030 "unexpected error %d\n", GetLastError());
9032 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
9034 /* even process local incontext hooks require hmodule */
9035 SetLastError(0xdeadbeef);
9036 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9037 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
9038 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
9039 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
9040 GetLastError() == 0xdeadbeef, /* Win9x */
9041 "unexpected error %d\n", GetLastError());
9043 /* even thread local incontext hooks require hmodule */
9044 SetLastError(0xdeadbeef);
9045 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9046 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
9047 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
9048 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
9049 GetLastError() == 0xdeadbeef, /* Win9x */
9050 "unexpected error %d\n", GetLastError());
9054 /* these 3 tests don't pass under Win9x */
9055 SetLastError(0xdeadbeef);
9056 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
9057 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
9058 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
9059 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
9061 SetLastError(0xdeadbeef);
9062 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
9063 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
9064 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
9065 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
9067 SetLastError(0xdeadbeef);
9068 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9069 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
9070 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
9071 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %d\n", GetLastError());
9074 SetLastError(0xdeadbeef);
9075 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
9076 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
9077 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
9078 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
9079 ret
= pUnhookWinEvent(hwinevent_hook
);
9080 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
9083 /* This call succeeds under win2k SP4, but fails under Wine.
9084 Does win2k test/use passed process id? */
9085 SetLastError(0xdeadbeef);
9086 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9087 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
9088 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
9089 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
9090 ret
= pUnhookWinEvent(hwinevent_hook
);
9091 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
9094 SetLastError(0xdeadbeef);
9095 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
9096 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
9097 GetLastError() == 0xdeadbeef, /* Win9x */
9098 "unexpected error %d\n", GetLastError());
9101 static const struct message ScrollWindowPaint1
[] = {
9103 { WM_ERASEBKGND
, sent
|beginpaint
},
9104 { WM_GETTEXTLENGTH
, sent
|optional
},
9105 { WM_PAINT
, sent
|optional
},
9106 { WM_NCPAINT
, sent
|beginpaint
|optional
},
9107 { WM_GETTEXT
, sent
|beginpaint
|optional
},
9108 { WM_GETTEXT
, sent
|beginpaint
|optional
},
9109 { WM_GETTEXT
, sent
|beginpaint
|optional
},
9110 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
9111 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
9115 static const struct message ScrollWindowPaint2
[] = {
9120 static void test_scrollwindowex(void)
9123 RECT rect
={0,0,130,130};
9125 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
9126 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
9127 100, 100, 200, 200, 0, 0, 0, NULL
);
9128 ok (hwnd
!= 0, "Failed to create overlapped window\n");
9129 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
9130 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
9131 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
9132 ok (hchild
!= 0, "Failed to create child\n");
9137 /* scroll without the child window */
9138 trace("start scroll\n");
9139 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
9140 SW_ERASE
|SW_INVALIDATE
);
9141 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
9142 trace("end scroll\n");
9145 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
9149 /* Now without the SW_ERASE flag */
9150 trace("start scroll\n");
9151 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
9152 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
9153 trace("end scroll\n");
9156 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
9160 /* now scroll the child window as well */
9161 trace("start scroll\n");
9162 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
9163 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
9164 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
9165 /* windows sometimes a WM_MOVE */
9166 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
9167 trace("end scroll\n");
9170 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
9174 /* now scroll with ScrollWindow() */
9175 trace("start scroll with ScrollWindow\n");
9176 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
9177 trace("end scroll\n");
9180 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
9182 ok(DestroyWindow(hchild
), "failed to destroy window\n");
9183 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
9187 static const struct message destroy_window_with_children
[] = {
9188 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
9189 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
9190 { 0x0090, sent
|optional
},
9191 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9192 { 0x0090, sent
|optional
},
9193 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
9194 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9195 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9196 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9197 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* parent */
9198 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
9199 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
9200 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
9201 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
9202 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
9203 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
9204 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
9205 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
9209 static void test_DestroyWindow(void)
9212 HWND parent
, child1
, child2
, child3
, child4
, test
;
9213 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
9215 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9216 100, 100, 200, 200, 0, 0, 0, NULL
);
9217 assert(parent
!= 0);
9218 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
9219 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
9220 assert(child1
!= 0);
9221 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
9222 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
9223 assert(child2
!= 0);
9224 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
9225 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
9226 assert(child3
!= 0);
9227 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
9228 0, 0, 50, 50, parent
, 0, 0, NULL
);
9229 assert(child4
!= 0);
9231 /* test owner/parent of child2 */
9232 test
= GetParent(child2
);
9233 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9234 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
9236 test
= pGetAncestor(child2
, GA_PARENT
);
9237 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9239 test
= GetWindow(child2
, GW_OWNER
);
9240 ok(!test
, "wrong owner %p\n", test
);
9242 test
= SetParent(child2
, parent
);
9243 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
9245 /* test owner/parent of the parent */
9246 test
= GetParent(parent
);
9247 ok(!test
, "wrong parent %p\n", test
);
9248 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
9250 test
= pGetAncestor(parent
, GA_PARENT
);
9251 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9253 test
= GetWindow(parent
, GW_OWNER
);
9254 ok(!test
, "wrong owner %p\n", test
);
9256 /* test owner/parent of child1 */
9257 test
= GetParent(child1
);
9258 ok(test
== parent
, "wrong parent %p\n", test
);
9259 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
9261 test
= pGetAncestor(child1
, GA_PARENT
);
9262 ok(test
== parent
, "wrong parent %p\n", test
);
9264 test
= GetWindow(child1
, GW_OWNER
);
9265 ok(!test
, "wrong owner %p\n", test
);
9267 /* test owner/parent of child2 */
9268 test
= GetParent(child2
);
9269 ok(test
== parent
, "wrong parent %p\n", test
);
9270 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
9272 test
= pGetAncestor(child2
, GA_PARENT
);
9273 ok(test
== parent
, "wrong parent %p\n", test
);
9275 test
= GetWindow(child2
, GW_OWNER
);
9276 ok(!test
, "wrong owner %p\n", test
);
9278 /* test owner/parent of child3 */
9279 test
= GetParent(child3
);
9280 ok(test
== child1
, "wrong parent %p\n", test
);
9281 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
9283 test
= pGetAncestor(child3
, GA_PARENT
);
9284 ok(test
== child1
, "wrong parent %p\n", test
);
9286 test
= GetWindow(child3
, GW_OWNER
);
9287 ok(!test
, "wrong owner %p\n", test
);
9289 /* test owner/parent of child4 */
9290 test
= GetParent(child4
);
9291 ok(test
== parent
, "wrong parent %p\n", test
);
9292 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
9294 test
= pGetAncestor(child4
, GA_PARENT
);
9295 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9297 test
= GetWindow(child4
, GW_OWNER
);
9298 ok(test
== parent
, "wrong owner %p\n", test
);
9302 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
9303 parent
, child1
, child2
, child3
, child4
);
9306 test
= GetCapture();
9307 ok(test
== child4
, "wrong capture window %p\n", test
);
9309 test_DestroyWindow_flag
= TRUE
;
9310 ret
= DestroyWindow(parent
);
9311 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
9312 test_DestroyWindow_flag
= FALSE
;
9313 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
9315 ok(!IsWindow(parent
), "parent still exists\n");
9316 ok(!IsWindow(child1
), "child1 still exists\n");
9317 ok(!IsWindow(child2
), "child2 still exists\n");
9318 ok(!IsWindow(child3
), "child3 still exists\n");
9319 ok(!IsWindow(child4
), "child4 still exists\n");
9321 test
= GetCapture();
9322 ok(!test
, "wrong capture window %p\n", test
);
9326 static const struct message WmDispatchPaint
[] = {
9327 { WM_NCPAINT
, sent
},
9328 { WM_GETTEXT
, sent
|defwinproc
|optional
},
9329 { WM_GETTEXT
, sent
|defwinproc
|optional
},
9330 { WM_ERASEBKGND
, sent
},
9334 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9336 if (message
== WM_PAINT
) return 0;
9337 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
9340 static void test_DispatchMessage(void)
9345 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9346 100, 100, 200, 200, 0, 0, 0, NULL
);
9347 ShowWindow( hwnd
, SW_SHOW
);
9348 UpdateWindow( hwnd
);
9351 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
9353 SetRect( &rect
, -5, -5, 5, 5 );
9354 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9356 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9358 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
9362 DispatchMessageA( &msg
);
9363 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
9364 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
9365 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
9366 if (++count
> 10) break;
9369 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
9371 trace("now without DispatchMessage\n");
9373 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9375 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9377 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
9380 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
9382 /* this will send WM_NCCPAINT just like DispatchMessage does */
9383 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
9384 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
9385 DeleteObject( hrgn
);
9386 GetClientRect( hwnd
, &rect
);
9387 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
9388 ok( !count
, "Got multiple WM_PAINTs\n" );
9389 if (++count
> 10) break;
9394 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9396 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9398 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
9404 hdc
= BeginPaint( hwnd
, NULL
);
9405 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
9406 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
9407 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
9408 ok( !count
, "Got multiple WM_PAINTs\n" );
9409 if (++count
> 10) break;
9412 DestroyWindow(hwnd
);
9416 static const struct message WmUser
[] = {
9428 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
9430 struct sendmsg_info
*info
= arg
;
9431 SetLastError( 0xdeadbeef );
9432 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
9433 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
9434 broken(GetLastError() == 0), /* win9x */
9435 "unexpected error %d\n", GetLastError());
9439 static void wait_for_thread( HANDLE thread
)
9441 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
9444 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9448 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9450 if (message
== WM_USER
) Sleep(200);
9451 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
9454 static void test_SendMessageTimeout(void)
9457 struct sendmsg_info info
;
9461 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9462 100, 100, 200, 200, 0, 0, 0, NULL
);
9466 info
.timeout
= 1000;
9467 info
.ret
= 0xdeadbeef;
9468 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9469 wait_for_thread( thread
);
9470 CloseHandle( thread
);
9471 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
9472 ok_sequence( WmUser
, "WmUser", FALSE
);
9475 info
.ret
= 0xdeadbeef;
9476 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9477 Sleep(100); /* SendMessageTimeout should time out here */
9478 wait_for_thread( thread
);
9479 CloseHandle( thread
);
9480 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
9481 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
9483 /* 0 means infinite timeout (but not on win9x) */
9485 info
.ret
= 0xdeadbeef;
9486 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9488 wait_for_thread( thread
);
9489 CloseHandle( thread
);
9490 is_win9x
= !info
.ret
;
9491 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
9492 else ok_sequence( WmUser
, "WmUser", FALSE
);
9494 /* timeout is treated as signed despite the prototype (but not on win9x) */
9495 info
.timeout
= 0x7fffffff;
9496 info
.ret
= 0xdeadbeef;
9497 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9499 wait_for_thread( thread
);
9500 CloseHandle( thread
);
9501 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
9502 ok_sequence( WmUser
, "WmUser", FALSE
);
9504 info
.timeout
= 0x80000000;
9505 info
.ret
= 0xdeadbeef;
9506 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9508 wait_for_thread( thread
);
9509 CloseHandle( thread
);
9512 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
9513 ok_sequence( WmUser
, "WmUser", FALSE
);
9517 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
9518 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
9521 /* now check for timeout during message processing */
9522 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
9524 info
.ret
= 0xdeadbeef;
9525 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9526 wait_for_thread( thread
);
9527 CloseHandle( thread
);
9528 /* we should time out but still get the message */
9529 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
9530 ok_sequence( WmUser
, "WmUser", FALSE
);
9532 DestroyWindow( info
.hwnd
);
9536 /****************** edit message test *************************/
9537 #define ID_EDIT 0x1234
9538 static const struct message sl_edit_setfocus
[] =
9540 { HCBT_SETFOCUS
, hook
},
9541 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
9542 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9543 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9544 { WM_SETFOCUS
, sent
|wparam
, 0 },
9545 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9546 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
9547 { WM_CTLCOLOREDIT
, sent
|parent
},
9548 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9549 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9550 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9551 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9554 static const struct message sl_edit_invisible
[] =
9556 { HCBT_SETFOCUS
, hook
},
9557 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
9558 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9559 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9560 { WM_KILLFOCUS
, sent
|parent
},
9561 { WM_SETFOCUS
, sent
},
9562 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9565 static const struct message ml_edit_setfocus
[] =
9567 { HCBT_SETFOCUS
, hook
},
9568 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
9569 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9570 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9571 { WM_SETFOCUS
, sent
|wparam
, 0 },
9572 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9573 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9574 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9575 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9576 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9579 static const struct message sl_edit_killfocus
[] =
9581 { HCBT_SETFOCUS
, hook
},
9582 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9583 { WM_KILLFOCUS
, sent
|wparam
, 0 },
9584 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9585 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9586 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
9587 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
9588 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
9591 static const struct message sl_edit_lbutton_dblclk
[] =
9593 { WM_LBUTTONDBLCLK
, sent
},
9594 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
9597 static const struct message sl_edit_lbutton_down
[] =
9599 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
9600 { HCBT_SETFOCUS
, hook
},
9601 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
9602 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9603 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9604 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
9605 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9606 { WM_CTLCOLOREDIT
, sent
|parent
},
9607 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9608 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9609 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9610 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9611 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9612 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
9613 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9614 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
9615 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9616 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9617 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9620 static const struct message ml_edit_lbutton_down
[] =
9622 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
9623 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
9624 { HCBT_SETFOCUS
, hook
},
9625 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
9626 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9627 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9628 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
9629 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9630 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9631 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9632 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9633 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9636 static const struct message sl_edit_lbutton_up
[] =
9638 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
9639 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9640 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
9641 { WM_CAPTURECHANGED
, sent
|defwinproc
},
9642 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9645 static const struct message ml_edit_lbutton_up
[] =
9647 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
9648 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
9649 { WM_CAPTURECHANGED
, sent
|defwinproc
},
9653 static WNDPROC old_edit_proc
;
9655 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9657 static LONG defwndproc_counter
= 0;
9659 struct recvd_message msg
;
9661 if (ignore_message( message
)) return 0;
9664 msg
.message
= message
;
9665 msg
.flags
= sent
|wparam
|lparam
;
9666 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9667 msg
.wParam
= wParam
;
9668 msg
.lParam
= lParam
;
9672 defwndproc_counter
++;
9673 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
9674 defwndproc_counter
--;
9679 static void subclass_edit(void)
9683 if (!GetClassInfoA(0, "edit", &cls
)) assert(0);
9685 old_edit_proc
= cls
.lpfnWndProc
;
9687 cls
.hInstance
= GetModuleHandleA(NULL
);
9688 cls
.lpfnWndProc
= edit_hook_proc
;
9689 cls
.lpszClassName
= "my_edit_class";
9690 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
9691 if (!RegisterClassA(&cls
)) assert(0);
9694 static void test_edit_messages(void)
9700 log_all_parent_messages
++;
9702 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9703 100, 100, 200, 200, 0, 0, 0, NULL
);
9704 ok (parent
!= 0, "Failed to create parent window\n");
9706 /* test single line edit */
9707 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
9708 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
9709 ok(hwnd
!= 0, "Failed to create edit window\n");
9711 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
9712 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08x\n", dlg_code
);
9716 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
9718 ShowWindow(hwnd
, SW_SHOW
);
9724 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
9727 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
9733 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
9734 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
9740 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
9741 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
9743 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
9744 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
9746 DestroyWindow(hwnd
);
9748 /* test multiline edit */
9749 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
9750 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
9751 ok(hwnd
!= 0, "Failed to create edit window\n");
9753 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
9754 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
9755 "wrong dlg_code %08x\n", dlg_code
);
9757 ShowWindow(hwnd
, SW_SHOW
);
9763 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
9766 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
9772 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
9773 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
9779 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
9780 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
9782 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
9783 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
9785 DestroyWindow(hwnd
);
9786 DestroyWindow(parent
);
9788 log_all_parent_messages
--;
9791 /**************************** End of Edit test ******************************/
9793 static const struct message WmKeyDownSkippedSeq
[] =
9795 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
9798 static const struct message WmKeyDownWasDownSkippedSeq
[] =
9800 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
9803 static const struct message WmKeyUpSkippedSeq
[] =
9805 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9808 static const struct message WmUserKeyUpSkippedSeq
[] =
9811 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9816 #define EV_SENDMSG 1
9822 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
9825 static DWORD CALLBACK
send_msg_thread_2(void *param
)
9828 struct peekmsg_info
*info
= param
;
9830 trace("thread: looping\n");
9831 SetEvent(info
->hevent
[EV_ACK
]);
9835 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
9839 case WAIT_OBJECT_0
+ EV_STOP
:
9840 trace("thread: exiting\n");
9843 case WAIT_OBJECT_0
+ EV_SENDMSG
:
9844 trace("thread: sending message\n");
9845 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
9846 ok(ret
, "SendNotifyMessageA failed error %u\n", GetLastError());
9847 SetEvent(info
->hevent
[EV_ACK
]);
9851 trace("unexpected return: %04x\n", ret
);
9859 static void test_PeekMessage(void)
9864 UINT qs_all_input
= QS_ALLINPUT
;
9865 UINT qs_input
= QS_INPUT
;
9867 struct peekmsg_info info
;
9869 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9870 100, 100, 200, 200, 0, 0, 0, NULL
);
9872 ShowWindow(info
.hwnd
, SW_SHOW
);
9873 UpdateWindow(info
.hwnd
);
9874 SetFocus(info
.hwnd
);
9876 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
9877 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
9878 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
9880 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
9881 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
9886 SetLastError(0xdeadbeef);
9887 qstatus
= GetQueueStatus(qs_all_input
);
9888 if (GetLastError() == ERROR_INVALID_FLAGS
)
9890 trace("QS_RAWINPUT not supported on this platform\n");
9891 qs_all_input
&= ~QS_RAWINPUT
;
9892 qs_input
&= ~QS_RAWINPUT
;
9894 if (qstatus
& QS_POSTMESSAGE
)
9896 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
9897 qstatus
= GetQueueStatus(qs_all_input
);
9899 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
9901 trace("signalling to send message\n");
9902 SetEvent(info
.hevent
[EV_SENDMSG
]);
9903 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
9905 /* pass invalid QS_xxxx flags */
9906 SetLastError(0xdeadbeef);
9907 qstatus
= GetQueueStatus(0xffffffff);
9908 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus
);
9911 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %d\n", GetLastError());
9912 qstatus
= GetQueueStatus(qs_all_input
);
9914 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
9915 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
),
9916 "wrong qstatus %08x\n", qstatus
);
9919 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
9921 "PeekMessageA should have returned FALSE instead of msg %04x\n",
9923 ok_sequence(WmUser
, "WmUser", FALSE
);
9925 qstatus
= GetQueueStatus(qs_all_input
);
9926 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
9928 keybd_event('N', 0, 0, 0);
9929 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9930 qstatus
= GetQueueStatus(qs_all_input
);
9931 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
9933 skip( "queuing key events not supported\n" );
9936 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
9937 /* keybd_event seems to trigger a sent message on NT4 */
9938 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
9939 "wrong qstatus %08x\n", qstatus
);
9941 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
9942 qstatus
= GetQueueStatus(qs_all_input
);
9943 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
9944 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
9945 "wrong qstatus %08x\n", qstatus
);
9947 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
9948 qstatus
= GetQueueStatus(qs_all_input
);
9949 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
9950 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
9951 "wrong qstatus %08x\n", qstatus
);
9953 trace("signalling to send message\n");
9954 SetEvent(info
.hevent
[EV_SENDMSG
]);
9955 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
9957 qstatus
= GetQueueStatus(qs_all_input
);
9958 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
9959 "wrong qstatus %08x\n", qstatus
);
9962 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
9963 if (ret
&& msg
.message
== WM_CHAR
)
9965 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
9969 "PeekMessageA should have returned FALSE instead of msg %04x\n",
9971 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
9973 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
9976 ok_sequence(WmUser
, "WmUser", FALSE
);
9978 qstatus
= GetQueueStatus(qs_all_input
);
9979 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
9980 "wrong qstatus %08x\n", qstatus
);
9982 trace("signalling to send message\n");
9983 SetEvent(info
.hevent
[EV_SENDMSG
]);
9984 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
9986 qstatus
= GetQueueStatus(qs_all_input
);
9987 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
9988 "wrong qstatus %08x\n", qstatus
);
9991 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
9993 "PeekMessageA should have returned FALSE instead of msg %04x\n",
9995 ok_sequence(WmUser
, "WmUser", FALSE
);
9997 qstatus
= GetQueueStatus(qs_all_input
);
9998 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
9999 "wrong qstatus %08x\n", qstatus
);
10002 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
10003 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10004 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10005 ret
, msg
.message
, msg
.wParam
);
10006 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10008 qstatus
= GetQueueStatus(qs_all_input
);
10009 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
10010 "wrong qstatus %08x\n", qstatus
);
10013 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
10015 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10017 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10019 qstatus
= GetQueueStatus(qs_all_input
);
10020 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
10021 "wrong qstatus %08x\n", qstatus
);
10024 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
10025 ok(ret
&& msg
.message
== WM_PAINT
,
10026 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
10027 DispatchMessageA(&msg
);
10028 ok_sequence(WmPaint
, "WmPaint", FALSE
);
10030 qstatus
= GetQueueStatus(qs_all_input
);
10031 ok(qstatus
== MAKELONG(0, QS_KEY
),
10032 "wrong qstatus %08x\n", qstatus
);
10035 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
10037 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10039 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10041 qstatus
= GetQueueStatus(qs_all_input
);
10042 ok(qstatus
== MAKELONG(0, QS_KEY
),
10043 "wrong qstatus %08x\n", qstatus
);
10045 trace("signalling to send message\n");
10046 SetEvent(info
.hevent
[EV_SENDMSG
]);
10047 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
10049 qstatus
= GetQueueStatus(qs_all_input
);
10050 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
10051 "wrong qstatus %08x\n", qstatus
);
10053 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10055 qstatus
= GetQueueStatus(qs_all_input
);
10056 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
10057 "wrong qstatus %08x\n", qstatus
);
10060 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
10061 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10062 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10063 ret
, msg
.message
, msg
.wParam
);
10064 ok_sequence(WmUser
, "WmUser", FALSE
);
10066 qstatus
= GetQueueStatus(qs_all_input
);
10067 ok(qstatus
== MAKELONG(0, QS_KEY
),
10068 "wrong qstatus %08x\n", qstatus
);
10071 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
10073 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10075 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10077 qstatus
= GetQueueStatus(qs_all_input
);
10078 ok(qstatus
== MAKELONG(0, QS_KEY
),
10079 "wrong qstatus %08x\n", qstatus
);
10081 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10083 qstatus
= GetQueueStatus(qs_all_input
);
10084 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
10085 "wrong qstatus %08x\n", qstatus
);
10087 trace("signalling to send message\n");
10088 SetEvent(info
.hevent
[EV_SENDMSG
]);
10089 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
10091 qstatus
= GetQueueStatus(qs_all_input
);
10092 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
10093 "wrong qstatus %08x\n", qstatus
);
10096 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
10098 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10100 ok_sequence(WmUser
, "WmUser", FALSE
);
10102 qstatus
= GetQueueStatus(qs_all_input
);
10103 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
10104 "wrong qstatus %08x\n", qstatus
);
10107 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
10108 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
10109 else /* workaround for a missing QS_RAWINPUT support */
10110 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
10111 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
10112 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10113 ret
, msg
.message
, msg
.wParam
);
10114 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
10116 qstatus
= GetQueueStatus(qs_all_input
);
10117 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
10118 "wrong qstatus %08x\n", qstatus
);
10121 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
10122 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
10123 else /* workaround for a missing QS_RAWINPUT support */
10124 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
10125 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
10126 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n",
10127 ret
, msg
.message
, msg
.wParam
);
10128 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
10130 qstatus
= GetQueueStatus(qs_all_input
);
10131 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10132 "wrong qstatus %08x\n", qstatus
);
10135 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
10137 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10139 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10141 qstatus
= GetQueueStatus(qs_all_input
);
10142 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10143 "wrong qstatus %08x\n", qstatus
);
10146 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10147 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10148 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10149 ret
, msg
.message
, msg
.wParam
);
10150 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10152 qstatus
= GetQueueStatus(qs_all_input
);
10154 "wrong qstatus %08x\n", qstatus
);
10157 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10159 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10161 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10163 qstatus
= GetQueueStatus(qs_all_input
);
10165 "wrong qstatus %08x\n", qstatus
);
10167 /* test whether presence of the quit flag in the queue affects
10170 PostQuitMessage(0x1234abcd);
10172 qstatus
= GetQueueStatus(qs_all_input
);
10173 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
10174 "wrong qstatus %08x\n", qstatus
);
10176 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
10178 qstatus
= GetQueueStatus(qs_all_input
);
10179 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
10180 "wrong qstatus %08x\n", qstatus
);
10183 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10184 ok(ret
&& msg
.message
== WM_USER
,
10185 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
10186 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10188 qstatus
= GetQueueStatus(qs_all_input
);
10189 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10190 "wrong qstatus %08x\n", qstatus
);
10193 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10194 ok(ret
&& msg
.message
== WM_QUIT
,
10195 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
10196 ok(msg
.wParam
== 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg
.wParam
);
10197 ok(msg
.lParam
== 0, "got lParam %08lx instead of 0\n", msg
.lParam
);
10198 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10200 qstatus
= GetQueueStatus(qs_all_input
);
10202 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10203 "wrong qstatus %08x\n", qstatus
);
10207 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10209 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10211 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10213 qstatus
= GetQueueStatus(qs_all_input
);
10215 "wrong qstatus %08x\n", qstatus
);
10217 /* some GetMessage tests */
10219 keybd_event('N', 0, 0, 0);
10220 qstatus
= GetQueueStatus(qs_all_input
);
10221 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10223 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10224 qstatus
= GetQueueStatus(qs_all_input
);
10225 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10229 ret
= GetMessageA( &msg
, 0, 0, 0 );
10230 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10231 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10232 ret
, msg
.message
, msg
.wParam
);
10233 qstatus
= GetQueueStatus(qs_all_input
);
10234 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10239 ret
= GetMessageA( &msg
, 0, 0, 0 );
10240 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
10241 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10242 ret
, msg
.message
, msg
.wParam
);
10243 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
10244 qstatus
= GetQueueStatus(qs_all_input
);
10245 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10248 keybd_event('N', 0, 0, 0);
10249 qstatus
= GetQueueStatus(qs_all_input
);
10250 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10252 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10253 qstatus
= GetQueueStatus(qs_all_input
);
10254 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10256 if (qstatus
& (QS_KEY
<< 16))
10258 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
10259 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
10260 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10261 ret
, msg
.message
, msg
.wParam
);
10262 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
10263 qstatus
= GetQueueStatus(qs_all_input
);
10264 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
10269 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
10270 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10271 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10272 ret
, msg
.message
, msg
.wParam
);
10273 qstatus
= GetQueueStatus(qs_all_input
);
10274 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10277 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10278 qstatus
= GetQueueStatus(qs_all_input
);
10279 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10281 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10282 qstatus
= GetQueueStatus(qs_all_input
);
10283 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10285 trace("signalling to send message\n");
10286 SetEvent(info
.hevent
[EV_SENDMSG
]);
10287 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
10288 qstatus
= GetQueueStatus(qs_all_input
);
10289 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
10290 "wrong qstatus %08x\n", qstatus
);
10292 if (qstatus
& (QS_KEY
<< 16))
10294 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
10295 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
10296 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10297 ret
, msg
.message
, msg
.wParam
);
10298 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
10299 qstatus
= GetQueueStatus(qs_all_input
);
10300 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
10305 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
10306 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10307 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10308 ret
, msg
.message
, msg
.wParam
);
10309 qstatus
= GetQueueStatus(qs_all_input
);
10310 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10313 trace("signalling to exit\n");
10314 SetEvent(info
.hevent
[EV_STOP
]);
10316 WaitForSingleObject(hthread
, INFINITE
);
10318 CloseHandle(hthread
);
10319 CloseHandle(info
.hevent
[0]);
10320 CloseHandle(info
.hevent
[1]);
10321 CloseHandle(info
.hevent
[2]);
10323 DestroyWindow(info
.hwnd
);
10326 static void wait_move_event(HWND hwnd
, int x
, int y
)
10330 BOOL ret
, go
= FALSE
;
10332 time
= GetTickCount();
10333 while (GetTickCount() - time
< 200 && !go
) {
10334 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10335 go
= ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
;
10336 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, GetTickCount() - time
, QS_ALLINPUT
);
10341 static void test_PeekMessage2(void)
10347 DWORD time1
, time2
, time3
;
10348 int x1
, y1
, x2
, y2
, x3
, y3
;
10351 time1
= time2
= time3
= 0;
10352 x1
= y1
= x2
= y2
= x3
= y3
= 0;
10354 /* Initialise window and make sure it is ready for events */
10355 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
10356 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
10358 trace("Window for test_PeekMessage2 %p\n", hwnd
);
10359 ShowWindow(hwnd
, SW_SHOW
);
10360 UpdateWindow(hwnd
);
10362 GetCursorPos(&pos
);
10363 SetCursorPos(100, 100);
10364 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
10367 /* Do initial mousemove, wait until we can see it
10368 and then do our test peek with PM_NOREMOVE. */
10369 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
10370 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
10372 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10375 skip( "queuing mouse events not supported\n" );
10380 trace("1st move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
10381 message
= msg
.message
;
10385 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
10388 /* Allow time to advance a bit, and then simulate the user moving their
10389 * mouse around. After that we peek again with PM_NOREMOVE.
10390 * Although the previous mousemove message was never removed, the
10391 * mousemove we now peek should reflect the recent mouse movements
10392 * because the input queue will merge the move events. */
10394 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
10395 wait_move_event(hwnd
, x1
, y1
);
10397 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10398 ok(ret
, "no message available\n");
10400 trace("2nd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
10401 message
= msg
.message
;
10405 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
10406 ok(time2
> time1
, "message time not advanced: %x %x\n", time1
, time2
);
10407 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
10410 /* Have another go, to drive the point home */
10412 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
10413 wait_move_event(hwnd
, x2
, y2
);
10415 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10416 ok(ret
, "no message available\n");
10418 trace("3rd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
10419 message
= msg
.message
;
10423 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
10424 ok(time3
> time2
, "message time not advanced: %x %x\n", time2
, time3
);
10425 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
10429 DestroyWindow(hwnd
);
10430 SetCursorPos(pos
.x
, pos
.y
);
10434 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
10436 struct recvd_message msg
;
10438 if (ignore_message( message
)) return 0;
10441 msg
.message
= message
;
10442 msg
.flags
= sent
|wparam
|lparam
;
10445 msg
.descr
= "dialog";
10450 case WM_INITDIALOG
:
10451 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
10452 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
10455 case WM_GETDLGCODE
:
10459 EndDialog(hwnd
, 0);
10466 static const struct message WmQuitDialogSeq
[] = {
10467 { HCBT_CREATEWND
, hook
},
10468 { WM_SETFONT
, sent
},
10469 { WM_INITDIALOG
, sent
},
10470 { WM_CHANGEUISTATE
, sent
|optional
},
10471 { HCBT_DESTROYWND
, hook
},
10472 { 0x0090, sent
|optional
}, /* Vista */
10473 { WM_DESTROY
, sent
},
10474 { WM_NCDESTROY
, sent
},
10478 static const struct message WmStopQuitSeq
[] = {
10479 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
10480 { WM_CLOSE
, posted
},
10481 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
10485 static void test_quit_message(void)
10490 /* test using PostQuitMessage */
10492 PostQuitMessage(0xbeef);
10494 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
10495 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
10496 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10497 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
10499 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
10500 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
10502 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10503 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
10504 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
10506 /* note: WM_QUIT message received after WM_USER message */
10507 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10508 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
10509 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10510 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
10512 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
10513 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
10515 /* now test with PostThreadMessage - different behaviour! */
10516 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
10518 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
10519 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
10520 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10521 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
10523 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
10524 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
10526 /* note: we receive the WM_QUIT message first this time */
10527 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10528 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
10529 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10530 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
10532 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10533 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
10534 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
10538 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
10539 ok(ret
== 1, "expected 1, got %d\n", ret
);
10540 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
10541 memset(&msg
, 0xab, sizeof(msg
));
10542 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
10543 ok(ret
, "PeekMessage failed\n");
10544 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10545 ok(msg
.wParam
== 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg
.wParam
);
10546 ok(msg
.lParam
== 0, "lParam was 0x%lx instead of 0\n", msg
.lParam
);
10548 /* Check what happens to a WM_QUIT message posted to a window that gets
10551 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
10552 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
10554 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
10556 struct recvd_message rmsg
;
10557 rmsg
.hwnd
= msg
.hwnd
;
10558 rmsg
.message
= msg
.message
;
10559 rmsg
.flags
= posted
|wparam
|lparam
;
10560 rmsg
.wParam
= msg
.wParam
;
10561 rmsg
.lParam
= msg
.lParam
;
10562 rmsg
.descr
= "stop/quit";
10563 if (msg
.message
== WM_QUIT
)
10564 /* The hwnd can only be checked here */
10565 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
10566 add_message(&rmsg
);
10567 DispatchMessageA(&msg
);
10569 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
10572 static const struct message WmMouseHoverSeq
[] = {
10573 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
10574 { WM_MOUSEACTIVATE
, sent
|optional
},
10575 { WM_TIMER
, sent
|optional
}, /* XP sends it */
10576 { WM_SYSTIMER
, sent
},
10577 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
10581 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
10584 DWORD start_ticks
, end_ticks
;
10586 start_ticks
= GetTickCount();
10587 /* add some deviation (50%) to cover not expected delays */
10588 start_ticks
+= timeout
/ 2;
10592 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
10594 /* Timer proc messages are not dispatched to the window proc,
10595 * and therefore not logged.
10597 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
10599 struct recvd_message s_msg
;
10601 s_msg
.hwnd
= msg
.hwnd
;
10602 s_msg
.message
= msg
.message
;
10603 s_msg
.flags
= sent
|wparam
|lparam
;
10604 s_msg
.wParam
= msg
.wParam
;
10605 s_msg
.lParam
= msg
.lParam
;
10606 s_msg
.descr
= "msg_loop";
10607 add_message(&s_msg
);
10609 DispatchMessageA(&msg
);
10612 end_ticks
= GetTickCount();
10614 /* inject WM_MOUSEMOVE to see how it changes tracking */
10615 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
10617 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10618 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10620 inject_mouse_move
= FALSE
;
10622 } while (start_ticks
+ timeout
>= end_ticks
);
10625 static void test_TrackMouseEvent(void)
10627 TRACKMOUSEEVENT tme
;
10630 RECT rc_parent
, rc_child
;
10631 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
10633 #define track_hover(track_hwnd, track_hover_time) \
10634 tme.cbSize = sizeof(tme); \
10635 tme.dwFlags = TME_HOVER; \
10636 tme.hwndTrack = track_hwnd; \
10637 tme.dwHoverTime = track_hover_time; \
10638 SetLastError(0xdeadbeef); \
10639 ret = pTrackMouseEvent(&tme); \
10640 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError())
10642 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
10643 tme.cbSize = sizeof(tme); \
10644 tme.dwFlags = TME_QUERY; \
10645 tme.hwndTrack = (HWND)0xdeadbeef; \
10646 tme.dwHoverTime = 0xdeadbeef; \
10647 SetLastError(0xdeadbeef); \
10648 ret = pTrackMouseEvent(&tme); \
10649 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\
10650 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \
10651 ok(tme.dwFlags == (expected_track_flags), \
10652 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
10653 ok(tme.hwndTrack == (expected_track_hwnd), \
10654 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
10655 ok(tme.dwHoverTime == (expected_hover_time), \
10656 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time))
10658 #define track_hover_cancel(track_hwnd) \
10659 tme.cbSize = sizeof(tme); \
10660 tme.dwFlags = TME_HOVER | TME_CANCEL; \
10661 tme.hwndTrack = track_hwnd; \
10662 tme.dwHoverTime = 0xdeadbeef; \
10663 SetLastError(0xdeadbeef); \
10664 ret = pTrackMouseEvent(&tme); \
10665 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError())
10667 default_hover_time
= 0xdeadbeef;
10668 SetLastError(0xdeadbeef);
10669 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
10670 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
10671 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError());
10672 if (!ret
) default_hover_time
= 400;
10673 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
10675 SetLastError(0xdeadbeef);
10676 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
10677 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
10678 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError());
10679 if (!ret
) hover_width
= 4;
10680 SetLastError(0xdeadbeef);
10681 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
10682 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
10683 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError());
10684 if (!ret
) hover_height
= 4;
10685 trace("hover rect is %u x %d\n", hover_width
, hover_height
);
10687 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
10688 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
10689 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
10693 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
10694 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
10695 50, 50, 200, 200, hwnd
,
10699 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
10704 tme
.dwFlags
= TME_QUERY
;
10705 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10706 tme
.dwHoverTime
= 0xdeadbeef;
10707 SetLastError(0xdeadbeef);
10708 ret
= pTrackMouseEvent(&tme
);
10709 ok(!ret
, "TrackMouseEvent should fail\n");
10710 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
10711 "not expected error %u\n", GetLastError());
10713 tme
.cbSize
= sizeof(tme
);
10714 tme
.dwFlags
= TME_HOVER
;
10715 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10716 tme
.dwHoverTime
= 0xdeadbeef;
10717 SetLastError(0xdeadbeef);
10718 ret
= pTrackMouseEvent(&tme
);
10719 ok(!ret
, "TrackMouseEvent should fail\n");
10720 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
10721 "not expected error %u\n", GetLastError());
10723 tme
.cbSize
= sizeof(tme
);
10724 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
10725 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10726 tme
.dwHoverTime
= 0xdeadbeef;
10727 SetLastError(0xdeadbeef);
10728 ret
= pTrackMouseEvent(&tme
);
10729 ok(!ret
, "TrackMouseEvent should fail\n");
10730 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
10731 "not expected error %u\n", GetLastError());
10733 GetWindowRect(hwnd
, &rc_parent
);
10734 GetWindowRect(hchild
, &rc_child
);
10735 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
10737 /* Process messages so that the system updates its internal current
10738 * window and hittest, otherwise TrackMouseEvent calls don't have any
10744 track_query(0, NULL
, 0);
10745 track_hover(hchild
, 0);
10746 track_query(0, NULL
, 0);
10751 track_hover(hwnd
, 0);
10752 tme
.cbSize
= sizeof(tme
);
10753 tme
.dwFlags
= TME_QUERY
;
10754 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10755 tme
.dwHoverTime
= 0xdeadbeef;
10756 SetLastError(0xdeadbeef);
10757 ret
= pTrackMouseEvent(&tme
);
10758 ok(ret
, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());
10759 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %u\n", tme
.cbSize
);
10762 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
10763 DestroyWindow( hwnd
);
10766 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme
.dwFlags
);
10767 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
10768 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %u, expected %u\n",
10769 tme
.dwHoverTime
, default_hover_time
);
10771 pump_msg_loop_timeout(default_hover_time
, FALSE
);
10772 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
10774 track_query(0, NULL
, 0);
10776 track_hover(hwnd
, HOVER_DEFAULT
);
10777 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10779 Sleep(default_hover_time
/ 2);
10780 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10781 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10783 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10785 pump_msg_loop_timeout(default_hover_time
, FALSE
);
10786 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
10788 track_query(0, NULL
, 0);
10790 track_hover(hwnd
, HOVER_DEFAULT
);
10791 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10793 pump_msg_loop_timeout(default_hover_time
, TRUE
);
10794 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
10796 track_query(0, NULL
, 0);
10798 track_hover(hwnd
, HOVER_DEFAULT
);
10799 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10800 track_hover_cancel(hwnd
);
10802 DestroyWindow(hwnd
);
10806 #undef track_hover_cancel
10810 static const struct message WmSetWindowRgn
[] = {
10811 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10812 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
10813 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
10814 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10815 { WM_ERASEBKGND
, sent
|optional
},
10816 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10817 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10821 static const struct message WmSetWindowRgn_no_redraw
[] = {
10822 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
10823 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
10824 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
10825 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10829 static const struct message WmSetWindowRgn_clear
[] = {
10830 { WM_WINDOWPOSCHANGING
, sent
/*|wparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ },
10831 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
10832 { WM_NCPAINT
, sent
|optional
},
10833 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10834 { WM_ERASEBKGND
, sent
|optional
}, /* FIXME: remove optional once Wine is fixed */
10835 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10836 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
10837 { WM_NCPAINT
, sent
|optional
},
10838 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10839 { WM_ERASEBKGND
, sent
|optional
},
10840 { WM_WINDOWPOSCHANGING
, sent
|optional
},
10841 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
10842 { WM_NCPAINT
, sent
|optional
},
10843 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10844 { WM_ERASEBKGND
, sent
|optional
},
10845 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10846 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
10847 { WM_NCPAINT
, sent
|optional
},
10848 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10849 { WM_ERASEBKGND
, sent
|optional
},
10850 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10851 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10855 static void test_SetWindowRgn(void)
10858 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
10859 100, 100, 200, 200, 0, 0, 0, NULL
);
10860 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
10862 ShowWindow( hwnd
, SW_SHOW
);
10863 UpdateWindow( hwnd
);
10867 trace("testing SetWindowRgn\n");
10868 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
10869 SetWindowRgn( hwnd
, hrgn
, TRUE
);
10870 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
10872 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
10873 SetWindowRgn( hwnd
, hrgn
, FALSE
);
10874 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
10876 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
10877 SetWindowRgn( hwnd
, hrgn
, TRUE
);
10878 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
10880 SetWindowRgn( hwnd
, 0, TRUE
);
10881 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
10883 DestroyWindow( hwnd
);
10886 /*************************** ShowWindow() test ******************************/
10887 static const struct message WmShowNormal
[] = {
10888 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10889 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
10890 { HCBT_ACTIVATE
, hook
},
10891 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
10892 { HCBT_SETFOCUS
, hook
},
10893 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10896 static const struct message WmShow
[] = {
10897 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10898 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
10899 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
10900 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
10901 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
10902 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10905 static const struct message WmShowNoActivate_1
[] = {
10906 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
10907 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10908 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10909 { WM_MOVE
, sent
|defwinproc
|optional
},
10910 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
10913 static const struct message WmShowNoActivate_2
[] = {
10914 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
10915 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
10916 { HCBT_ACTIVATE
, hook
|optional
},
10917 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
10918 { HCBT_SETFOCUS
, hook
|optional
},
10919 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
10920 { WM_MOVE
, sent
|defwinproc
},
10921 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
10922 { HCBT_SETFOCUS
, hook
|optional
},
10923 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
10924 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
10925 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10926 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
10929 static const struct message WmShowNA_1
[] = {
10930 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10931 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
10932 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10935 static const struct message WmShowNA_2
[] = {
10936 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10937 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
10938 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10941 static const struct message WmRestore_1
[] = {
10942 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
10943 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10944 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
10945 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
10946 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
10947 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10948 { WM_MOVE
, sent
|defwinproc
},
10949 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
10950 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
10953 static const struct message WmRestore_2
[] = {
10954 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10955 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
10956 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
10957 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
10958 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
10959 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10962 static const struct message WmRestore_3
[] = {
10963 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
10964 { WM_GETMINMAXINFO
, sent
},
10965 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10966 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
10967 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
10968 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
10969 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10970 { WM_MOVE
, sent
|defwinproc
},
10971 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
10972 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
10975 static const struct message WmRestore_4
[] = {
10976 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
10977 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10978 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10979 { WM_MOVE
, sent
|defwinproc
|optional
},
10980 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
10983 static const struct message WmRestore_5
[] = {
10984 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
10985 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10986 { HCBT_ACTIVATE
, hook
|optional
},
10987 { HCBT_SETFOCUS
, hook
|optional
},
10988 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10989 { WM_MOVE
, sent
|defwinproc
|optional
},
10990 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
10993 static const struct message WmHide_1
[] = {
10994 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
10995 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
10996 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
10997 { HCBT_ACTIVATE
, hook
|optional
},
10998 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
11001 static const struct message WmHide_2
[] = {
11002 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
11003 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
11004 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
11005 { HCBT_ACTIVATE
, hook
|optional
},
11008 static const struct message WmHide_3
[] = {
11009 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
11010 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
11011 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11012 { HCBT_SETFOCUS
, hook
|optional
},
11013 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11016 static const struct message WmShowMinimized_1
[] = {
11017 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
11018 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11019 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
11020 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
11021 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11022 { WM_MOVE
, sent
|defwinproc
},
11023 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11026 static const struct message WmMinimize_1
[] = {
11027 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11028 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
11029 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11030 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11031 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11032 { WM_MOVE
, sent
|defwinproc
},
11033 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11036 static const struct message WmMinimize_2
[] = {
11037 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11038 { HCBT_SETFOCUS
, hook
|optional
},
11039 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11040 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11041 { WM_MOVE
, sent
|defwinproc
},
11042 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11045 static const struct message WmMinimize_3
[] = {
11046 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11047 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11048 { HCBT_ACTIVATE
, hook
|optional
},
11049 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11050 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11051 { WM_MOVE
, sent
|defwinproc
},
11052 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11055 static const struct message WmShowMinNoActivate
[] = {
11056 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
11057 { WM_WINDOWPOSCHANGING
, sent
},
11058 { WM_WINDOWPOSCHANGED
, sent
},
11059 { WM_MOVE
, sent
|defwinproc
|optional
},
11060 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
11063 static const struct message WmMinMax_1
[] = {
11064 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
11067 static const struct message WmMinMax_2
[] = {
11068 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11069 { WM_GETMINMAXINFO
, sent
|optional
},
11070 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
11071 { HCBT_ACTIVATE
, hook
|optional
},
11072 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11073 { HCBT_SETFOCUS
, hook
|optional
},
11074 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11075 { WM_MOVE
, sent
|defwinproc
|optional
},
11076 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
11077 { HCBT_SETFOCUS
, hook
|optional
},
11080 static const struct message WmMinMax_3
[] = {
11081 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11082 { HCBT_SETFOCUS
, hook
|optional
},
11083 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11084 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11085 { WM_MOVE
, sent
|defwinproc
|optional
},
11086 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
11089 static const struct message WmMinMax_4
[] = {
11090 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
11093 static const struct message WmShowMaximized_1
[] = {
11094 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11095 { WM_GETMINMAXINFO
, sent
},
11096 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11097 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
11098 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
11099 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
11100 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11101 { WM_MOVE
, sent
|defwinproc
},
11102 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
11103 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
11106 static const struct message WmShowMaximized_2
[] = {
11107 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11108 { WM_GETMINMAXINFO
, sent
},
11109 { WM_WINDOWPOSCHANGING
, sent
|optional
},
11110 { HCBT_ACTIVATE
, hook
|optional
},
11111 { WM_WINDOWPOSCHANGED
, sent
|optional
},
11112 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
11113 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
11114 { WM_WINDOWPOSCHANGING
, sent
|optional
},
11115 { HCBT_SETFOCUS
, hook
|optional
},
11116 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11117 { WM_MOVE
, sent
|defwinproc
},
11118 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
11119 { HCBT_SETFOCUS
, hook
|optional
},
11122 static const struct message WmShowMaximized_3
[] = {
11123 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11124 { WM_GETMINMAXINFO
, sent
|optional
},
11125 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
11126 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
11127 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
11128 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
11129 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
11130 { WM_MOVE
, sent
|defwinproc
|optional
},
11131 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
11135 static void test_ShowWindow(void)
11137 /* ShowWindow commands in random order */
11138 static const struct
11140 INT cmd
; /* ShowWindow command */
11141 LPARAM ret
; /* ShowWindow return value */
11142 DWORD style
; /* window style after the command */
11143 const struct message
*msg
; /* message sequence the command produces */
11144 INT wp_cmd
, wp_flags
; /* window placement after the command */
11145 POINT wp_min
, wp_max
; /* window placement after the command */
11146 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
11149 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
11150 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11151 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11152 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11153 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
11154 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11155 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11156 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11157 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
11158 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11159 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
11160 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11161 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
11162 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11163 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
11164 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11165 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
11166 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11167 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
11168 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11169 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
11170 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11171 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
11172 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11173 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
11174 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11175 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11176 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11177 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
11178 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11179 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11180 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11181 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
11182 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11183 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11184 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11185 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
11186 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11187 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
11188 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11189 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11190 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11191 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
11192 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
11193 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
11194 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11195 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11196 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11197 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
11198 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11199 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
11200 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11201 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
11202 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11203 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11204 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11205 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
11206 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11207 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
11208 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11209 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11210 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11211 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
11212 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11213 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11214 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11215 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
11216 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11217 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
11218 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11219 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11220 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11221 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
11222 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11223 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11224 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11225 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11226 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11227 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
11228 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11229 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
11230 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11231 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
11232 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11233 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
11234 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11235 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
11236 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11237 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
11238 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11239 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
11240 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11241 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
11242 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11243 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
11244 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11245 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
11246 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11247 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
11248 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11249 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
11250 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11251 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
11252 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11253 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11254 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11255 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
11256 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11257 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11258 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11259 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
11260 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11261 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11262 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
11268 WINDOWPLACEMENT wp
;
11269 RECT win_rc
, work_rc
= {0, 0, 0, 0};
11271 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
11272 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
11277 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
11278 ok(style
== 0, "expected style 0, got %08x\n", style
);
11283 if (pGetMonitorInfoA
&& pMonitorFromPoint
)
11289 SetLastError(0xdeadbeef);
11290 hmon
= pMonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
11291 ok(hmon
!= 0, "MonitorFromPoint error %u\n", GetLastError());
11293 mi
.cbSize
= sizeof(mi
);
11294 SetLastError(0xdeadbeef);
11295 ret
= pGetMonitorInfoA(hmon
, &mi
);
11296 ok(ret
, "GetMonitorInfo error %u\n", GetLastError());
11297 trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n",
11298 mi
.rcMonitor
.left
, mi
.rcMonitor
.top
, mi
.rcMonitor
.right
, mi
.rcMonitor
.bottom
,
11299 mi
.rcWork
.left
, mi
.rcWork
.top
, mi
.rcWork
.right
, mi
.rcWork
.bottom
);
11300 work_rc
= mi
.rcWork
;
11303 GetWindowRect(hwnd
, &win_rc
);
11304 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
11306 wp
.length
= sizeof(wp
);
11307 SetLastError(0xdeadbeaf);
11308 ret
= GetWindowPlacement(hwnd
, &wp
);
11309 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
11310 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
11311 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
11312 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
11313 "expected -1,-1 got %d,%d\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
11314 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
11315 "expected -1,-1 got %d,%d\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
11316 if (work_rc
.left
|| work_rc
.top
) todo_wine
/* FIXME: remove once Wine is fixed */
11317 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
),
11318 "expected %d,%d-%d,%d got %d,%d-%d,%d\n",
11319 win_rc
.left
, win_rc
.top
, win_rc
.right
, win_rc
.bottom
,
11320 wp
.rcNormalPosition
.left
, wp
.rcNormalPosition
.top
,
11321 wp
.rcNormalPosition
.right
, wp
.rcNormalPosition
.bottom
);
11323 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
),
11324 "expected %d,%d-%d,%d got %d,%d-%d,%d\n",
11325 win_rc
.left
, win_rc
.top
, win_rc
.right
, win_rc
.bottom
,
11326 wp
.rcNormalPosition
.left
, wp
.rcNormalPosition
.top
,
11327 wp
.rcNormalPosition
.right
, wp
.rcNormalPosition
.bottom
);
11329 for (i
= 0; i
< sizeof(sw
)/sizeof(sw
[0]); i
++)
11331 static const char * const sw_cmd_name
[13] =
11333 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
11334 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
11335 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
11336 "SW_NORMALNA" /* 0xCC */
11339 INT idx
; /* index into the above array of names */
11341 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
11343 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
11344 trace("%d: sending %s, current window style %08x\n", i
+1, sw_cmd_name
[idx
], style
);
11345 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
11346 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %lu, got %lu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
11347 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
11348 ok(style
== sw
[i
].style
, "%d: expected style %08x, got %08x\n", i
+1, sw
[i
].style
, style
);
11350 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
11351 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
11353 wp
.length
= sizeof(wp
);
11354 SetLastError(0xdeadbeaf);
11355 ret
= GetWindowPlacement(hwnd
, &wp
);
11356 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
11357 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
11358 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
11360 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
11361 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
11362 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
11364 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
11365 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
11366 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
11370 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
11371 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
11374 if (wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
11376 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
11377 "expected %d,%d got %d,%d\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
11379 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
11380 "expected %d,%d got %d,%d\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
11382 if (0) /* FIXME: Wine behaves completely different here */
11383 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
),
11384 "expected %d,%d-%d,%d got %d,%d-%d,%d\n",
11385 win_rc
.left
, win_rc
.top
, win_rc
.right
, win_rc
.bottom
,
11386 wp
.rcNormalPosition
.left
, wp
.rcNormalPosition
.top
,
11387 wp
.rcNormalPosition
.right
, wp
.rcNormalPosition
.bottom
);
11389 DestroyWindow(hwnd
);
11393 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11395 struct recvd_message msg
;
11397 if (ignore_message( message
)) return 0;
11400 msg
.message
= message
;
11401 msg
.flags
= sent
|wparam
|lparam
;
11402 msg
.wParam
= wParam
;
11403 msg
.lParam
= lParam
;
11404 msg
.descr
= "dialog";
11407 /* calling DefDlgProc leads to a recursion under XP */
11411 case WM_INITDIALOG
:
11412 case WM_GETDLGCODE
:
11418 static const struct message WmDefDlgSetFocus_1
[] = {
11419 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
11420 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
11421 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
11422 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
11423 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
11424 { HCBT_SETFOCUS
, hook
},
11425 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11426 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11427 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11428 { WM_SETFOCUS
, sent
|wparam
, 0 },
11429 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11430 { WM_CTLCOLOREDIT
, sent
},
11431 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11432 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11433 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11434 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11435 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
11438 static const struct message WmDefDlgSetFocus_2
[] = {
11439 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
11440 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
11441 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
11442 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
11443 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
11444 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11445 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
11446 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11449 /* Creation of a dialog */
11450 static const struct message WmCreateDialogParamSeq_1
[] = {
11451 { HCBT_CREATEWND
, hook
},
11452 { WM_NCCREATE
, sent
},
11453 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
11454 { WM_CREATE
, sent
},
11455 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
11456 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
11458 { WM_SETFONT
, sent
},
11459 { WM_INITDIALOG
, sent
},
11460 { WM_CHANGEUISTATE
, sent
|optional
},
11463 /* Creation of a dialog */
11464 static const struct message WmCreateDialogParamSeq_2
[] = {
11465 { HCBT_CREATEWND
, hook
},
11466 { WM_NCCREATE
, sent
},
11467 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
11468 { WM_CREATE
, sent
},
11469 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
11470 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
11472 { WM_CHANGEUISTATE
, sent
|optional
},
11476 static void test_dialog_messages(void)
11479 HWND hdlg
, hedit1
, hedit2
, hfocus
;
11482 #define set_selection(hctl, start, end) \
11483 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
11484 ok(ret == 1, "EM_SETSEL returned %ld\n", ret);
11486 #define check_selection(hctl, start, end) \
11487 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
11488 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
11492 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
11493 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
11494 0, 0, 100, 100, 0, 0, 0, NULL
);
11495 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
11497 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
11498 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
11499 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
11500 ok(hedit1
!= 0, "Failed to create edit control\n");
11501 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
11502 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
11503 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
11504 ok(hedit2
!= 0, "Failed to create edit control\n");
11506 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
11507 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
11509 hfocus
= GetFocus();
11510 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
11513 hfocus
= GetFocus();
11514 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
11516 check_selection(hedit1
, 0, 0);
11517 check_selection(hedit2
, 0, 0);
11519 set_selection(hedit2
, 0, -1);
11520 check_selection(hedit2
, 0, 3);
11523 hfocus
= GetFocus();
11524 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
11527 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
11528 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
11529 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
11531 hfocus
= GetFocus();
11532 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
11534 check_selection(hedit1
, 0, 5);
11535 check_selection(hedit2
, 0, 3);
11538 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
11539 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
11540 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
11542 hfocus
= GetFocus();
11543 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
11545 check_selection(hedit1
, 0, 5);
11546 check_selection(hedit2
, 0, 3);
11548 EndDialog(hdlg
, 0);
11549 DestroyWindow(hedit1
);
11550 DestroyWindow(hedit2
);
11551 DestroyWindow(hdlg
);
11554 #undef set_selection
11555 #undef check_selection
11557 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
11558 cls
.lpszClassName
= "MyDialogClass";
11559 cls
.hInstance
= GetModuleHandleA(NULL
);
11560 /* need a cast since a dlgproc is used as a wndproc */
11561 cls
.lpfnWndProc
= test_dlg_proc
;
11562 if (!RegisterClassA(&cls
)) assert(0);
11564 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
11565 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
11566 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
11567 EndDialog(hdlg
, 0);
11568 DestroyWindow(hdlg
);
11571 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
11572 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
11573 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
11574 EndDialog(hdlg
, 0);
11575 DestroyWindow(hdlg
);
11578 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
11581 static void test_EndDialog(void)
11583 HWND hparent
, hother
, hactive
, hdlg
;
11586 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
11587 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
11588 100, 100, 200, 200, 0, 0, 0, NULL
);
11589 ok (hparent
!= 0, "Failed to create parent window\n");
11591 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
11592 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11593 100, 100, 200, 200, 0, 0, 0, NULL
);
11594 ok (hother
!= 0, "Failed to create parent window\n");
11596 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
11597 cls
.lpszClassName
= "MyDialogClass";
11598 cls
.hInstance
= GetModuleHandleA(NULL
);
11599 cls
.lpfnWndProc
= test_dlg_proc
;
11600 if (!RegisterClassA(&cls
)) assert(0);
11603 SetForegroundWindow(hother
);
11604 hactive
= GetForegroundWindow();
11605 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
11607 /* create a dialog where the parent is disabled, this parent should still
11608 receive the focus when the dialog exits (even though "normally" a
11609 disabled window should not receive the focus) */
11610 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
11611 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
11612 SetForegroundWindow(hdlg
);
11613 hactive
= GetForegroundWindow();
11614 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
11615 EndDialog(hdlg
, 0);
11616 hactive
= GetForegroundWindow();
11617 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
11618 DestroyWindow(hdlg
);
11621 DestroyWindow( hother
);
11622 DestroyWindow( hparent
);
11623 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
11626 static void test_nullCallback(void)
11630 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
11631 100, 100, 200, 200, 0, 0, 0, NULL
);
11632 ok (hwnd
!= 0, "Failed to create overlapped window\n");
11634 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
11636 DestroyWindow(hwnd
);
11639 /* SetActiveWindow( 0 ) hwnd visible */
11640 static const struct message SetActiveWindowSeq0
[] =
11642 { HCBT_ACTIVATE
, hook
|optional
},
11643 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11644 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11645 { WM_ACTIVATE
, sent
|wparam
, 0 },
11646 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
11647 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
11648 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11649 { WM_KILLFOCUS
, sent
|optional
},
11650 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11651 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11652 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
11653 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11654 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
11655 { HCBT_SETFOCUS
, hook
|optional
},
11656 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
11657 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
11658 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
11659 { WM_IME_SETCONTEXT
, sent
|optional
},
11660 { WM_IME_SETCONTEXT
, sent
|optional
},
11661 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11662 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11663 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
11664 { WM_GETTEXT
, sent
|optional
},
11667 /* SetActiveWindow( hwnd ) hwnd visible */
11668 static const struct message SetActiveWindowSeq1
[] =
11670 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11673 /* SetActiveWindow( popup ) hwnd visible, popup visible */
11674 static const struct message SetActiveWindowSeq2
[] =
11676 { HCBT_ACTIVATE
, hook
},
11677 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11678 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11679 { WM_ACTIVATE
, sent
|wparam
, 0 },
11680 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11681 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11682 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11683 { WM_NCPAINT
, sent
|optional
},
11684 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11685 { WM_ERASEBKGND
, sent
|optional
},
11686 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11687 { WM_NCACTIVATE
, sent
|wparam
, 1 },
11688 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11689 { WM_ACTIVATE
, sent
|wparam
, 1 },
11690 { HCBT_SETFOCUS
, hook
},
11691 { WM_KILLFOCUS
, sent
|defwinproc
},
11692 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
11693 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11694 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11695 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11696 { WM_SETFOCUS
, sent
|defwinproc
},
11697 { WM_GETTEXT
, sent
|optional
},
11701 /* SetActiveWindow( hwnd ) hwnd not visible */
11702 static const struct message SetActiveWindowSeq3
[] =
11704 { HCBT_ACTIVATE
, hook
},
11705 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11706 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11707 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
11708 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11709 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11710 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
11711 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
11712 { WM_NCACTIVATE
, sent
|wparam
, 1 },
11713 { WM_ACTIVATE
, sent
|wparam
, 1 },
11714 { HCBT_SETFOCUS
, hook
},
11715 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11716 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11717 { WM_SETFOCUS
, sent
|defwinproc
},
11720 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
11721 static const struct message SetActiveWindowSeq4
[] =
11723 { HCBT_ACTIVATE
, hook
},
11724 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11725 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11726 { WM_ACTIVATE
, sent
|wparam
, 0 },
11727 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11728 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
11729 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11730 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11731 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11732 { WM_NCACTIVATE
, sent
|wparam
, 1 },
11733 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11734 { WM_ACTIVATE
, sent
|wparam
, 1 },
11735 { HCBT_SETFOCUS
, hook
},
11736 { WM_KILLFOCUS
, sent
|defwinproc
},
11737 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
11738 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11739 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11740 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11741 { WM_SETFOCUS
, sent
|defwinproc
},
11746 static void test_SetActiveWindow(void)
11748 HWND hwnd
, popup
, ret
;
11750 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
11751 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11752 100, 100, 200, 200, 0, 0, 0, NULL
);
11754 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
11755 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
11756 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
11758 ok(hwnd
!= 0, "Failed to create overlapped window\n");
11759 ok(popup
!= 0, "Failed to create popup window\n");
11760 SetForegroundWindow( popup
);
11763 trace("SetActiveWindow(0)\n");
11764 ret
= SetActiveWindow(0);
11765 ok( ret
== popup
, "Failed to SetActiveWindow(0)\n");
11766 ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
11769 trace("SetActiveWindow(hwnd), hwnd visible\n");
11770 ret
= SetActiveWindow(hwnd
);
11771 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
11774 trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
11775 ret
= SetActiveWindow(popup
);
11776 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
11777 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
11780 ShowWindow(hwnd
, SW_HIDE
);
11781 ShowWindow(popup
, SW_HIDE
);
11784 trace("SetActiveWindow(hwnd), hwnd not visible\n");
11785 ret
= SetActiveWindow(hwnd
);
11786 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
11787 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
11790 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
11791 ret
= SetActiveWindow(popup
);
11792 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
11793 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
11798 DestroyWindow(hwnd
);
11801 static const struct message SetForegroundWindowSeq
[] =
11803 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11804 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11805 { WM_ACTIVATE
, sent
|wparam
, 0 },
11806 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
11807 { WM_KILLFOCUS
, sent
},
11808 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
11809 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
11813 static void test_SetForegroundWindow(void)
11817 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
11818 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11819 100, 100, 200, 200, 0, 0, 0, NULL
);
11820 ok (hwnd
!= 0, "Failed to create overlapped window\n");
11821 SetForegroundWindow( hwnd
);
11824 trace("SetForegroundWindow( 0 )\n");
11825 SetForegroundWindow( 0 );
11826 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
11827 trace("SetForegroundWindow( GetDesktopWindow() )\n");
11828 SetForegroundWindow( GetDesktopWindow() );
11829 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
11830 "foreground top level window", FALSE
);
11833 DestroyWindow(hwnd
);
11836 static void test_dbcs_wm_char(void)
11839 WCHAR wch
, bad_wch
;
11847 struct message wmCharSeq
[2];
11850 if (!pGetCPInfoExA
)
11852 win_skip("GetCPInfoExA is not available\n");
11856 pGetCPInfoExA( CP_ACP
, 0, &cpinfo
);
11857 if (cpinfo
.MaxCharSize
!= 2)
11859 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
11863 dbch
[0] = dbch
[1] = 0;
11865 bad_wch
= cpinfo
.UnicodeDefaultChar
;
11866 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
11867 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
11868 for (k
= 128; k
<= 255; k
++)
11874 if (MultiByteToWideChar( CP_ACP
, 0, str
, 2, wstr
, 2 ) == 1 &&
11875 WideCharToMultiByte( CP_ACP
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
11876 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
11877 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
11888 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
11891 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
11892 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
11894 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
11895 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
11896 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
11897 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
11898 ok (hwnd
!= 0, "Failed to create overlapped window\n");
11899 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
11902 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
11903 wmCharSeq
[0].message
= WM_CHAR
;
11904 wmCharSeq
[0].flags
= sent
|wparam
;
11905 wmCharSeq
[0].wParam
= wch
;
11907 /* posted message */
11908 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
11909 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11910 ok( !ret
, "got message %x\n", msg
.message
);
11911 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
11912 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11913 ok( ret
, "no message\n" );
11914 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
11915 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
11916 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11917 ok( !ret
, "got message %x\n", msg
.message
);
11919 /* posted thread message */
11920 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
11921 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11922 ok( !ret
, "got message %x\n", msg
.message
);
11923 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
11924 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11925 ok( ret
, "no message\n" );
11926 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
11927 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
11928 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11929 ok( !ret
, "got message %x\n", msg
.message
);
11933 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
11934 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11935 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
11936 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11937 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11938 ok( !ret
, "got message %x\n", msg
.message
);
11940 /* sent message with timeout */
11942 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
11943 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11944 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
11945 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11946 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11947 ok( !ret
, "got message %x\n", msg
.message
);
11949 /* sent message with timeout and callback */
11951 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
11952 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11953 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
11954 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11955 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11956 ok( !ret
, "got message %x\n", msg
.message
);
11958 /* sent message with callback */
11960 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
11961 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11962 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
11963 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11964 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11965 ok( !ret
, "got message %x\n", msg
.message
);
11967 /* direct window proc call */
11969 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
11970 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11971 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
11972 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11974 /* dispatch message */
11976 msg
.message
= WM_CHAR
;
11977 msg
.wParam
= dbch
[0];
11979 DispatchMessageA( &msg
);
11980 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11981 msg
.wParam
= dbch
[1];
11982 DispatchMessageA( &msg
);
11983 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11985 /* window handle is irrelevant */
11987 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
11988 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11989 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
11990 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11991 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11992 ok( !ret
, "got message %x\n", msg
.message
);
11994 /* interleaved post and send */
11996 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
11997 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
11998 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11999 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12000 ok( !ret
, "got message %x\n", msg
.message
);
12001 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12002 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12003 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12004 ok( ret
, "no message\n" );
12005 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12006 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
12007 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12008 ok( !ret
, "got message %x\n", msg
.message
);
12009 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12010 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12011 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12012 ok( !ret
, "got message %x\n", msg
.message
);
12014 /* interleaved sent message and winproc */
12016 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
12017 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
12018 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12019 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12020 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12021 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
12022 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12024 /* interleaved winproc and dispatch */
12026 msg
.message
= WM_CHAR
;
12027 msg
.wParam
= dbch
[0];
12029 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
12030 DispatchMessageA( &msg
);
12031 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12032 msg
.wParam
= dbch
[1];
12033 DispatchMessageA( &msg
);
12034 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12035 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
12036 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12038 /* interleaved sends */
12040 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
12041 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
12042 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12043 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
12044 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12045 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12046 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12050 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
12051 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12052 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12053 ok( !ret
, "got message %x\n", msg
.message
);
12055 /* other char messages are not magic */
12056 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
12057 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12058 ok( ret
, "no message\n" );
12059 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
12060 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
12061 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12062 ok( !ret
, "got message %x\n", msg
.message
);
12063 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
12064 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12065 ok( ret
, "no message\n" );
12066 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
12067 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
12068 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12069 ok( !ret
, "got message %x\n", msg
.message
);
12071 /* test retrieving messages */
12073 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
12074 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12075 ok( ret
, "no message\n" );
12076 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12077 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12078 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12079 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12080 ok( ret
, "no message\n" );
12081 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12082 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12083 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12084 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12085 ok( !ret
, "got message %x\n", msg
.message
);
12087 /* message filters */
12088 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
12089 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12090 ok( ret
, "no message\n" );
12091 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12092 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12093 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12094 /* message id is filtered, hwnd is not */
12095 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
12096 ok( !ret
, "no message\n" );
12097 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
12098 ok( ret
, "no message\n" );
12099 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12100 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12101 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12102 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12103 ok( !ret
, "got message %x\n", msg
.message
);
12105 /* mixing GetMessage and PostMessage */
12106 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
12107 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
12108 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12109 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12110 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12111 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
12114 ok( time
- GetTickCount() <= 100, "bad time %x\n", msg
.time
);
12115 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
12116 ok( ret
, "no message\n" );
12117 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12118 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12119 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12120 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
12121 ok( msg
.time
== time
, "bad time %x/%x\n", msg
.time
, time
);
12122 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
);
12123 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12124 ok( !ret
, "got message %x\n", msg
.message
);
12126 /* without PM_REMOVE */
12127 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
12128 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
12129 ok( ret
, "no message\n" );
12130 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12131 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12132 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12133 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
12134 ok( ret
, "no message\n" );
12135 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12136 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12137 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12138 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
12139 ok( ret
, "no message\n" );
12140 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12141 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12142 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12143 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
12144 ok( ret
, "no message\n" );
12145 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12146 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12147 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12148 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12149 ok( !ret
, "got message %x\n", msg
.message
);
12151 DestroyWindow(hwnd
);
12152 DestroyWindow(hwnd2
);
12155 static void test_unicode_wm_char(void)
12159 struct message seq
[2];
12160 HKL hkl_orig
, hkl_greek
;
12162 LCID thread_locale
;
12164 hkl_orig
= GetKeyboardLayout( 0 );
12165 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
12168 skip( "Default codepage %d\n", cp
);
12172 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
12173 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
12175 skip( "Unable to load Greek keyboard layout\n" );
12179 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
12180 100, 100, 200, 200, 0, 0, 0, NULL
);
12183 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
12185 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
12187 if (!ignore_message( msg
.message
)) break;
12190 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12191 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12192 ok( msg
.wParam
== 0x3b1, "bad wparam %lx\n", msg
.wParam
);
12193 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
12195 DispatchMessageW( &msg
);
12197 memset( seq
, 0, sizeof(seq
) );
12198 seq
[0].message
= WM_CHAR
;
12199 seq
[0].flags
= sent
|wparam
;
12200 seq
[0].wParam
= 0x3b1;
12202 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
12206 /* greek alpha -> 'a' in cp1252 */
12207 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
12209 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
12210 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12211 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12212 ok( msg
.wParam
== 0x61, "bad wparam %lx\n", msg
.wParam
);
12213 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
12215 DispatchMessageA( &msg
);
12217 seq
[0].wParam
= 0x61;
12218 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
12220 thread_locale
= GetThreadLocale();
12221 ActivateKeyboardLayout( hkl_greek
, 0 );
12222 ok( GetThreadLocale() == thread_locale
, "locale changed from %08x to %08x\n",
12223 thread_locale
, GetThreadLocale() );
12227 /* greek alpha -> 0xe1 in cp1253 */
12228 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
12230 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
12231 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12232 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12233 ok( msg
.wParam
== 0xe1, "bad wparam %lx\n", msg
.wParam
);
12234 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
12236 DispatchMessageA( &msg
);
12238 seq
[0].wParam
= 0x3b1;
12239 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
12241 DestroyWindow( hwnd
);
12242 ActivateKeyboardLayout( hkl_orig
, 0 );
12243 UnloadKeyboardLayout( hkl_greek
);
12246 #define ID_LISTBOX 0x000f
12248 static const struct message wm_lb_setcursel_0
[] =
12250 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
12251 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12252 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
12253 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12254 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12257 static const struct message wm_lb_setcursel_1
[] =
12259 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
12260 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12261 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
12262 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12263 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
12264 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
12265 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
12268 static const struct message wm_lb_setcursel_2
[] =
12270 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
12271 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12272 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
12273 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12274 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
12275 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
12276 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
12279 static const struct message wm_lb_click_0
[] =
12281 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
12282 { HCBT_SETFOCUS
, hook
},
12283 { WM_KILLFOCUS
, sent
|parent
},
12284 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
12285 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
12286 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12287 { WM_SETFOCUS
, sent
|defwinproc
},
12289 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
12290 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
12291 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
12292 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
12293 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
12295 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
12296 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12297 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
12298 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12299 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
12300 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
12302 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12303 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12305 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
12306 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
12307 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
12308 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
12311 static const struct message wm_lb_deletestring
[] =
12313 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
12314 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
12315 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
12316 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
12319 static const struct message wm_lb_deletestring_reset
[] =
12321 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
12322 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
12323 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
12324 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
12325 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
12329 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
12331 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
12333 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12335 static LONG defwndproc_counter
= 0;
12337 struct recvd_message msg
;
12339 /* do not log painting messages */
12340 if (message
!= WM_PAINT
&&
12341 message
!= WM_NCPAINT
&&
12342 message
!= WM_SYNCPAINT
&&
12343 message
!= WM_ERASEBKGND
&&
12344 message
!= WM_NCHITTEST
&&
12345 message
!= WM_GETTEXT
&&
12346 !ignore_message( message
))
12349 msg
.message
= message
;
12350 msg
.flags
= sent
|wparam
|lparam
;
12351 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
12354 msg
.descr
= "listbox";
12358 defwndproc_counter
++;
12359 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
12360 defwndproc_counter
--;
12365 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
12366 int caret_index
, int top_index
, int line
)
12370 /* calling an orig proc helps to avoid unnecessary message logging */
12371 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
12372 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %ld\n", count
, ret
);
12373 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
12374 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %ld\n", cur_sel
, ret
);
12375 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
12376 ok_(__FILE__
, line
)(ret
== caret_index
||
12377 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
12378 "expected caret index %d, got %ld\n", caret_index
, ret
);
12379 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
12380 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %ld\n", top_index
, ret
);
12383 static void test_listbox_messages(void)
12385 HWND parent
, listbox
;
12388 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12389 100, 100, 200, 200, 0, 0, 0, NULL
);
12390 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
12391 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
12392 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
12393 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
12395 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
12397 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
12398 ok(ret
== 0, "expected 0, got %ld\n", ret
);
12399 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
12400 ok(ret
== 1, "expected 1, got %ld\n", ret
);
12401 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
12402 ok(ret
== 2, "expected 2, got %ld\n", ret
);
12404 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
12408 log_all_parent_messages
++;
12410 trace("selecting item 0\n");
12411 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
12412 ok(ret
== 0, "expected 0, got %ld\n", ret
);
12413 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
12414 check_lb_state(listbox
, 3, 0, 0, 0);
12417 trace("selecting item 1\n");
12418 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
12419 ok(ret
== 1, "expected 1, got %ld\n", ret
);
12420 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
12421 check_lb_state(listbox
, 3, 1, 1, 0);
12423 trace("selecting item 2\n");
12424 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
12425 ok(ret
== 2, "expected 2, got %ld\n", ret
);
12426 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
12427 check_lb_state(listbox
, 3, 2, 2, 0);
12429 trace("clicking on item 0\n");
12430 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
12431 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
12432 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
12433 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
12434 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
12435 check_lb_state(listbox
, 3, 0, 0, 0);
12438 trace("deleting item 0\n");
12439 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12440 ok(ret
== 2, "expected 2, got %ld\n", ret
);
12441 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
12442 check_lb_state(listbox
, 2, -1, 0, 0);
12445 trace("deleting item 0\n");
12446 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12447 ok(ret
== 1, "expected 1, got %ld\n", ret
);
12448 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
12449 check_lb_state(listbox
, 1, -1, 0, 0);
12452 trace("deleting item 0\n");
12453 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12454 ok(ret
== 0, "expected 0, got %ld\n", ret
);
12455 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
12456 check_lb_state(listbox
, 0, -1, 0, 0);
12459 trace("deleting item 0\n");
12460 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12461 ok(ret
== LB_ERR
, "expected LB_ERR, got %ld\n", ret
);
12462 check_lb_state(listbox
, 0, -1, 0, 0);
12465 log_all_parent_messages
--;
12467 DestroyWindow(listbox
);
12468 DestroyWindow(parent
);
12471 /*************************** Menu test ******************************/
12472 static const struct message wm_popup_menu_1
[] =
12474 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12475 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12476 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
12477 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
12478 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
12479 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
12480 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12481 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12482 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
12483 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
12484 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
12485 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
12486 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
12487 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
12488 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
12489 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
12490 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12491 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12492 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12493 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
12494 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
12495 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
12498 static const struct message wm_popup_menu_2
[] =
12500 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12501 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12502 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
12503 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
12504 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
12505 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
12506 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12507 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12508 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
12509 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
12510 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
12511 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
12512 { HCBT_CREATEWND
, hook
},
12513 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
12514 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
12515 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
12516 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
12517 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
12518 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
12519 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
12520 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
12521 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
12522 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
12523 { HCBT_DESTROYWND
, hook
},
12524 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12525 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
12526 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12527 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12528 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12529 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
12530 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
12531 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
12534 static const struct message wm_popup_menu_3
[] =
12536 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12537 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12538 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
12539 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
12540 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
12541 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
12542 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12543 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12544 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
12545 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
12546 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
12547 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
12548 { HCBT_CREATEWND
, hook
},
12549 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
12550 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
12551 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
12552 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
12553 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
12554 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
12555 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
12556 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
12557 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
12558 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
12559 { HCBT_DESTROYWND
, hook
},
12560 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12561 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
12562 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12563 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12564 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12565 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
12566 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
12567 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
12571 static const struct message wm_single_menu_item
[] =
12573 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12574 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12575 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
12576 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
12577 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
12578 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
12579 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12580 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12581 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
12582 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12583 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12584 { WM_MENUCOMMAND
, sent
},
12585 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
12586 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
12587 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
12588 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
12590 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
12591 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
12592 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
12593 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
12594 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
12598 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12600 if (message
== WM_ENTERIDLE
||
12601 message
== WM_INITMENU
||
12602 message
== WM_INITMENUPOPUP
||
12603 message
== WM_MENUSELECT
||
12604 message
== WM_PARENTNOTIFY
||
12605 message
== WM_ENTERMENULOOP
||
12606 message
== WM_EXITMENULOOP
||
12607 message
== WM_UNINITMENUPOPUP
||
12608 message
== WM_KEYDOWN
||
12609 message
== WM_KEYUP
||
12610 message
== WM_CHAR
||
12611 message
== WM_SYSKEYDOWN
||
12612 message
== WM_SYSKEYUP
||
12613 message
== WM_SYSCHAR
||
12614 message
== WM_COMMAND
||
12615 message
== WM_MENUCOMMAND
)
12617 struct recvd_message msg
;
12620 msg
.message
= message
;
12621 msg
.flags
= sent
|wparam
|lparam
;
12624 msg
.descr
= "parent_menu_proc";
12628 return DefWindowProcA(hwnd
, message
, wp
, lp
);
12631 static void set_menu_style(HMENU hmenu
, DWORD style
)
12636 mi
.cbSize
= sizeof(mi
);
12637 mi
.fMask
= MIM_STYLE
;
12638 mi
.dwStyle
= style
;
12639 SetLastError(0xdeadbeef);
12640 ret
= pSetMenuInfo(hmenu
, &mi
);
12641 ok(ret
, "SetMenuInfo error %u\n", GetLastError());
12644 static DWORD
get_menu_style(HMENU hmenu
)
12649 mi
.cbSize
= sizeof(mi
);
12650 mi
.fMask
= MIM_STYLE
;
12652 SetLastError(0xdeadbeef);
12653 ret
= pGetMenuInfo(hmenu
, &mi
);
12654 ok(ret
, "GetMenuInfo error %u\n", GetLastError());
12659 static void test_menu_messages(void)
12663 HMENU hmenu
, hmenu_popup
;
12667 if (!pGetMenuInfo
|| !pSetMenuInfo
)
12669 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n");
12673 cls
.lpfnWndProc
= parent_menu_proc
;
12674 cls
.cbClsExtra
= 0;
12675 cls
.cbWndExtra
= 0;
12676 cls
.hInstance
= GetModuleHandleA(0);
12678 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
12679 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
12680 cls
.lpszMenuName
= NULL
;
12681 cls
.lpszClassName
= "TestMenuClass";
12682 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
12683 if (!RegisterClassA(&cls
)) assert(0);
12685 SetLastError(0xdeadbeef);
12686 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12687 100, 100, 200, 200, 0, 0, 0, NULL
);
12688 ok(hwnd
!= 0, "LoadMenuA error %u\n", GetLastError());
12690 SetLastError(0xdeadbeef);
12691 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
12692 ok(hmenu
!= 0, "LoadMenuA error %u\n", GetLastError());
12694 SetMenu(hwnd
, hmenu
);
12695 SetForegroundWindow( hwnd
);
12698 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
12699 style
= get_menu_style(hmenu
);
12700 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
12702 hmenu_popup
= GetSubMenu(hmenu
, 0);
12703 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12704 style
= get_menu_style(hmenu_popup
);
12705 ok(style
== 0, "expected 0, got %u\n", style
);
12707 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
12708 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12709 style
= get_menu_style(hmenu_popup
);
12710 ok(style
== 0, "expected 0, got %u\n", style
);
12713 trace("testing a popup menu command\n");
12715 keybd_event(VK_MENU
, 0, 0, 0);
12716 keybd_event('E', 0, 0, 0);
12717 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
12718 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12719 keybd_event(VK_RETURN
, 0, 0, 0);
12720 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
12721 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12723 TranslateMessage(&msg
);
12724 DispatchMessageA(&msg
);
12726 if (!sequence_cnt
) /* we didn't get any message */
12728 skip( "queuing key events not supported\n" );
12731 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
12732 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
12734 win_skip( "menu tracking through VK_MENU not supported\n" );
12737 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
12739 /* Alt+F, Right, Enter */
12740 trace("testing submenu of a popup menu command\n");
12742 keybd_event(VK_MENU
, 0, 0, 0);
12743 keybd_event('F', 0, 0, 0);
12744 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
12745 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12746 keybd_event(VK_RIGHT
, 0, 0, 0);
12747 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
12748 keybd_event(VK_RETURN
, 0, 0, 0);
12749 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
12750 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12752 TranslateMessage(&msg
);
12753 DispatchMessageA(&msg
);
12755 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
12757 trace("testing single menu item command\n");
12759 keybd_event(VK_MENU
, 0, 0, 0);
12760 keybd_event('Q', 0, 0, 0);
12761 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
12762 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12763 keybd_event(VK_ESCAPE
, 0, 0, 0);
12764 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
12765 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12767 TranslateMessage(&msg
);
12768 DispatchMessageA(&msg
);
12770 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
12772 set_menu_style(hmenu
, 0);
12773 style
= get_menu_style(hmenu
);
12774 ok(style
== 0, "expected 0, got %u\n", style
);
12776 hmenu_popup
= GetSubMenu(hmenu
, 0);
12777 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12778 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
12779 style
= get_menu_style(hmenu_popup
);
12780 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
12782 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
12783 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12784 style
= get_menu_style(hmenu_popup
);
12785 ok(style
== 0, "expected 0, got %u\n", style
);
12787 /* Alt+F, Right, Enter */
12788 trace("testing submenu of a popup menu command\n");
12790 keybd_event(VK_MENU
, 0, 0, 0);
12791 keybd_event('F', 0, 0, 0);
12792 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
12793 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12794 keybd_event(VK_RIGHT
, 0, 0, 0);
12795 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
12796 keybd_event(VK_RETURN
, 0, 0, 0);
12797 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
12798 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12800 TranslateMessage(&msg
);
12801 DispatchMessageA(&msg
);
12803 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
12806 DestroyWindow(hwnd
);
12807 DestroyMenu(hmenu
);
12811 static void test_paintingloop(void)
12815 paint_loop_done
= FALSE
;
12816 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
12817 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
12818 100, 100, 100, 100, 0, 0, 0, NULL
);
12819 ok(hwnd
!= 0, "PaintLoop window error %u\n", GetLastError());
12820 ShowWindow(hwnd
,SW_NORMAL
);
12823 while (!paint_loop_done
)
12826 if (PeekMessageA(&msg
, 0, 0, 0, 1))
12828 TranslateMessage(&msg
);
12829 DispatchMessageA(&msg
);
12832 DestroyWindow(hwnd
);
12835 static void test_defwinproc(void)
12839 BOOL gotwmquit
= FALSE
;
12840 hwnd
= CreateWindowExA(0, "static", "test_defwndproc", WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
12842 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
12843 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
12844 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
12845 DispatchMessageA( &msg
);
12847 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
12848 DestroyWindow( hwnd
);
12851 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
12852 static void clear_clipboard_(int line
, HWND hWnd
)
12855 succ
= OpenClipboard(hWnd
);
12856 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%u\n", GetLastError());
12857 succ
= EmptyClipboard();
12858 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%u\n", GetLastError());
12859 succ
= CloseClipboard();
12860 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%u\n", GetLastError());
12863 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
12864 static void expect_HWND_(int line
, HWND expected
, HWND got
)
12866 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
12869 static WNDPROC pOldViewerProc
;
12871 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12873 static BOOL recursion_guard
;
12875 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
12877 recursion_guard
= TRUE
;
12878 clear_clipboard(hWnd
);
12879 recursion_guard
= FALSE
;
12881 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
12884 static void test_clipboard_viewers(void)
12886 static struct message wm_change_cb_chain
[] =
12888 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
12891 static const struct message wm_clipboard_destroyed
[] =
12893 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12896 static struct message wm_clipboard_changed
[] =
12898 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12901 static struct message wm_clipboard_changed_and_owned
[] =
12903 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12904 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12908 HINSTANCE hInst
= GetModuleHandleA(NULL
);
12909 HWND hWnd1
, hWnd2
, hWnd3
;
12913 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
12914 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
12915 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
12916 GetDesktopWindow(), NULL
, hInst
, NULL
);
12917 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
12918 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
12919 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
12920 GetDesktopWindow(), NULL
, hInst
, NULL
);
12921 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
12922 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
12923 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
12924 GetDesktopWindow(), NULL
, hInst
, NULL
);
12925 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
12926 assert(hWnd1
&& hWnd2
&& hWnd3
);
12930 /* Test getting the clipboard viewer and setting the viewer to NULL. */
12931 hOrigViewer
= GetClipboardViewer();
12932 hRet
= SetClipboardViewer(NULL
);
12933 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
12934 expect_HWND(hOrigViewer
, hRet
);
12935 expect_HWND(NULL
, GetClipboardViewer());
12937 /* Test registering hWnd1 as a viewer. */
12938 hRet
= SetClipboardViewer(hWnd1
);
12939 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
12940 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
12941 expect_HWND(NULL
, hRet
);
12942 expect_HWND(hWnd1
, GetClipboardViewer());
12944 /* Test that changing the clipboard actually refreshes the registered viewer. */
12945 clear_clipboard(hWnd1
);
12946 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
12947 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
12949 /* Again, but with different owner. */
12950 clear_clipboard(hWnd2
);
12951 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
12952 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
12954 /* Test re-registering same window. */
12955 hRet
= SetClipboardViewer(hWnd1
);
12956 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
12957 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
12958 expect_HWND(hWnd1
, hRet
);
12959 expect_HWND(hWnd1
, GetClipboardViewer());
12961 /* Test ChangeClipboardChain. */
12962 ChangeClipboardChain(hWnd2
, hWnd3
);
12963 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
12964 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
12965 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
12966 expect_HWND(hWnd1
, GetClipboardViewer());
12968 ChangeClipboardChain(hWnd2
, NULL
);
12969 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
12970 wm_change_cb_chain
[0].lParam
= 0;
12971 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
12972 expect_HWND(hWnd1
, GetClipboardViewer());
12974 ChangeClipboardChain(NULL
, hWnd2
);
12975 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", TRUE
);
12976 expect_HWND(hWnd1
, GetClipboardViewer());
12978 /* Actually change clipboard viewer with ChangeClipboardChain. */
12979 ChangeClipboardChain(hWnd1
, hWnd2
);
12980 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
12981 expect_HWND(hWnd2
, GetClipboardViewer());
12983 /* Test that no refresh messages are sent when viewer has unregistered. */
12984 clear_clipboard(hWnd2
);
12985 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
12987 /* Register hWnd1 again. */
12988 ChangeClipboardChain(hWnd2
, hWnd1
);
12989 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
12990 expect_HWND(hWnd1
, GetClipboardViewer());
12992 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
12993 * changes the clipboard. When this happens, the system shouldn't send
12994 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
12996 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
12997 clear_clipboard(hWnd2
);
12998 /* The clipboard owner is changed in recursive_viewer_proc: */
12999 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
13000 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
13002 /* Test unregistering. */
13003 ChangeClipboardChain(hWnd1
, NULL
);
13004 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
13005 expect_HWND(NULL
, GetClipboardViewer());
13007 clear_clipboard(hWnd1
);
13008 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
13010 DestroyWindow(hWnd1
);
13011 DestroyWindow(hWnd2
);
13012 DestroyWindow(hWnd3
);
13013 SetClipboardViewer(hOrigViewer
);
13016 static void test_PostMessage(void)
13018 static const struct
13024 { HWND_TOP
/* 0 */, TRUE
},
13025 { HWND_BROADCAST
, TRUE
},
13026 { HWND_BOTTOM
, TRUE
},
13027 { HWND_TOPMOST
, TRUE
},
13028 { HWND_NOTOPMOST
, FALSE
},
13029 { HWND_MESSAGE
, FALSE
},
13030 { (HWND
)0xdeadbeef, FALSE
}
13036 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
13038 SetLastError(0xdeadbeef);
13039 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
13040 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
13042 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
13049 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
13050 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
13052 for (i
= 0; i
< sizeof(data
)/sizeof(data
[0]); i
++)
13054 memset(&msg
, 0xab, sizeof(msg
));
13055 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
13056 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
13060 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
13061 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
13062 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
13063 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
13065 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
13066 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
13067 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
13068 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
13072 DestroyWindow(hwnd
);
13076 static const struct
13080 } wait_idle_expect
[] =
13082 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13083 { WAIT_TIMEOUT
, 0, FALSE
},
13084 { WAIT_TIMEOUT
, 0, FALSE
},
13085 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13086 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13087 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
13088 { WAIT_TIMEOUT
, 0, FALSE
},
13089 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13092 /* 10 */ { 0, 0, FALSE
},
13094 { 0, WAIT_TIMEOUT
, FALSE
},
13097 /* 15 */ { 0, 0, FALSE
},
13098 { WAIT_TIMEOUT
, 0, FALSE
},
13099 { WAIT_TIMEOUT
, 0, FALSE
},
13100 { WAIT_TIMEOUT
, 0, FALSE
},
13101 { WAIT_TIMEOUT
, 0, FALSE
},
13102 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
13105 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
13109 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13111 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
13115 static void do_wait_idle_child( int arg
)
13122 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
13123 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
13125 memset( &cls
, 0, sizeof(cls
) );
13126 cls
.lpfnWndProc
= DefWindowProcA
;
13127 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
13128 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
13129 cls
.lpszClassName
= "TestClass";
13130 RegisterClassA( &cls
);
13132 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
13134 ok( start_event
!= 0, "failed to create start event, error %u\n", GetLastError() );
13135 ok( end_event
!= 0, "failed to create end event, error %u\n", GetLastError() );
13140 SetEvent( start_event
);
13143 SetEvent( start_event
);
13145 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
13148 SetEvent( start_event
);
13150 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13151 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
13152 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
13155 SetEvent( start_event
);
13157 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
13160 SetEvent( start_event
);
13162 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13163 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
13166 SetEvent( start_event
);
13168 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13169 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
13172 SetEvent( start_event
);
13174 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13175 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
13177 GetMessageA( &msg
, 0, 0, 0 );
13178 DispatchMessageA( &msg
);
13182 SetEvent( start_event
);
13184 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13185 SetTimer( hwnd
, 3, 1, NULL
);
13187 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
13190 SetEvent( start_event
);
13192 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13193 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
13196 SetEvent( start_event
);
13198 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13199 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
13200 for (;;) GetMessageA( &msg
, 0, 0, 0 );
13203 SetEvent( start_event
);
13205 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13206 SetTimer( hwnd
, 3, 1, NULL
);
13208 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
13211 SetEvent( start_event
);
13213 return; /* exiting the process makes WaitForInputIdle return success too */
13215 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13217 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
13218 SetEvent( start_event
);
13221 SetEvent( start_event
);
13222 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13224 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
13225 WaitForSingleObject( thread
, 10000 );
13226 CloseHandle( thread
);
13229 SetEvent( start_event
);
13231 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
13234 SetEvent( start_event
);
13236 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
13239 SetEvent( start_event
);
13241 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
13244 SetEvent( start_event
);
13246 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
13249 SetEvent( start_event
);
13251 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
13254 SetEvent( start_event
);
13256 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
13259 SetEvent( start_event
);
13261 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
13264 WaitForSingleObject( end_event
, 2000 );
13265 CloseHandle( start_event
);
13266 CloseHandle( end_event
);
13267 if (hwnd
) DestroyWindow( hwnd
);
13270 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
13272 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
13273 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
13276 static DWORD CALLBACK
wait_idle_thread( void *arg
)
13282 memset( &cls
, 0, sizeof(cls
) );
13283 cls
.lpfnWndProc
= wait_idle_proc
;
13284 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
13285 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
13286 cls
.lpszClassName
= "TestClass";
13287 RegisterClassA( &cls
);
13289 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13290 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
13291 DestroyWindow(hwnd
);
13295 static void test_WaitForInputIdle( char *argv0
)
13297 char path
[MAX_PATH
];
13298 PROCESS_INFORMATION pi
;
13299 STARTUPINFOA startup
;
13301 HANDLE start_event
, end_event
, thread
;
13304 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
13305 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
13306 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
13308 if (console_app
) /* build the test with -mwindows for better coverage */
13309 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
13311 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
13312 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
13313 ok(start_event
!= 0, "failed to create start event, error %u\n", GetLastError());
13314 ok(end_event
!= 0, "failed to create end event, error %u\n", GetLastError());
13316 memset( &startup
, 0, sizeof(startup
) );
13317 startup
.cb
= sizeof(startup
);
13318 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
13319 startup
.wShowWindow
= SW_SHOWNORMAL
;
13321 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
13323 for (i
= 0; i
< sizeof(wait_idle_expect
)/sizeof(wait_idle_expect
[0]); i
++)
13325 ResetEvent( start_event
);
13326 ResetEvent( end_event
);
13327 sprintf( path
, "%s msg %u", argv0
, i
);
13328 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
13329 ok( ret
, "CreateProcess '%s' failed err %u.\n", path
, GetLastError() );
13332 ret
= WaitForSingleObject( start_event
, 5000 );
13333 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
13334 if (ret
== WAIT_OBJECT_0
)
13336 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
13337 if (ret
== WAIT_FAILED
)
13339 ret
== wait_idle_expect
[i
].exp
||
13340 broken(ret
== wait_idle_expect
[i
].broken
),
13341 "%u: WaitForInputIdle error %08x expected %08x\n",
13342 i
, ret
, wait_idle_expect
[i
].exp
);
13343 else if (wait_idle_expect
[i
].todo
)
13345 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
13346 "%u: WaitForInputIdle error %08x expected %08x\n",
13347 i
, ret
, wait_idle_expect
[i
].exp
);
13349 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
13350 "%u: WaitForInputIdle error %08x expected %08x\n",
13351 i
, ret
, wait_idle_expect
[i
].exp
);
13352 SetEvent( end_event
);
13353 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
13355 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
13356 winetest_wait_child_process( pi
.hProcess
);
13357 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
13358 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
13359 CloseHandle( pi
.hProcess
);
13360 CloseHandle( pi
.hThread
);
13363 CloseHandle( start_event
);
13364 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
13365 WaitForSingleObject( thread
, 10000 );
13366 CloseHandle( thread
);
13369 static const struct message WmSetParentSeq_1
[] = {
13370 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
13371 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13372 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
13373 { WM_CHILDACTIVATE
, sent
},
13374 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
13375 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
13376 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13377 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13381 static const struct message WmSetParentSeq_2
[] = {
13382 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
13383 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13384 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13385 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13386 { HCBT_SETFOCUS
, hook
|optional
},
13387 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
13388 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
13389 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13390 { WM_KILLFOCUS
, sent
|wparam
, 0 },
13391 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13392 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
13393 { HCBT_ACTIVATE
, hook
|optional
},
13394 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
13395 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13396 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
13397 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
13398 { HCBT_SETFOCUS
, hook
|optional
},
13399 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13400 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
13401 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
13402 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
13403 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13404 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13405 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13406 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
13407 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13412 static void test_SetParent(void)
13414 HWND parent1
, parent2
, child
, popup
;
13417 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
13418 100, 100, 200, 200, 0, 0, 0, NULL
);
13419 ok(parent1
!= 0, "Failed to create parent1 window\n");
13421 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
13422 400, 100, 200, 200, 0, 0, 0, NULL
);
13423 ok(parent2
!= 0, "Failed to create parent2 window\n");
13425 /* WS_CHILD window */
13426 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
13427 10, 10, 150, 150, parent1
, 0, 0, NULL
);
13428 ok(child
!= 0, "Failed to create child window\n");
13430 GetWindowRect(parent1
, &rc
);
13431 trace("parent1 (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13432 GetWindowRect(child
, &rc_old
);
13433 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
13434 trace("child (%d,%d)-(%d,%d)\n", rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
);
13438 SetParent(child
, parent2
);
13440 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", TRUE
);
13442 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
13443 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
13445 GetWindowRect(parent2
, &rc
);
13446 trace("parent2 (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13447 GetWindowRect(child
, &rc
);
13448 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
13449 trace("child (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13451 ok(EqualRect(&rc_old
, &rc
), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
13452 rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
,
13453 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13455 /* WS_POPUP window */
13456 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
13457 20, 20, 100, 100, 0, 0, 0, NULL
);
13458 ok(popup
!= 0, "Failed to create popup window\n");
13460 GetWindowRect(popup
, &rc_old
);
13461 trace("popup (%d,%d)-(%d,%d)\n", rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
);
13465 SetParent(popup
, child
);
13467 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
13469 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
13470 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
13472 GetWindowRect(child
, &rc
);
13473 trace("parent2 (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13474 GetWindowRect(popup
, &rc
);
13475 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
13476 trace("popup (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13478 ok(EqualRect(&rc_old
, &rc
), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
13479 rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
,
13480 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13482 DestroyWindow(popup
);
13483 DestroyWindow(child
);
13484 DestroyWindow(parent1
);
13485 DestroyWindow(parent2
);
13490 static const struct message WmKeyReleaseOnly
[] = {
13491 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
13492 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
13495 static const struct message WmKeyPressNormal
[] = {
13496 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
13497 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
13500 static const struct message WmKeyPressRepeat
[] = {
13501 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
13502 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
13505 static const struct message WmKeyReleaseNormal
[] = {
13506 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
13507 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
13511 static void test_keyflags(void)
13515 BYTE keyboard_state
[256];
13518 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13519 100, 100, 200, 200, 0, 0, 0, NULL
);
13524 /* keyup without a keydown */
13525 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
13526 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13527 DispatchMessageA(&msg
);
13528 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
13530 key_state
= GetAsyncKeyState(0x41);
13531 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13533 key_state
= GetKeyState(0x41);
13534 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13537 keybd_event(0x41, 0, 0, 0);
13538 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13539 DispatchMessageA(&msg
);
13540 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
13542 key_state
= GetAsyncKeyState(0x41);
13543 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13545 key_state
= GetKeyState(0x41);
13546 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13548 /* keydown repeat */
13549 keybd_event(0x41, 0, 0, 0);
13550 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13551 DispatchMessageA(&msg
);
13552 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
13554 key_state
= GetAsyncKeyState(0x41);
13555 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13557 key_state
= GetKeyState(0x41);
13558 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13561 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
13562 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13563 DispatchMessageA(&msg
);
13564 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
13566 key_state
= GetAsyncKeyState(0x41);
13567 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13569 key_state
= GetKeyState(0x41);
13570 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13572 /* set the key state in this thread */
13573 GetKeyboardState(keyboard_state
);
13574 keyboard_state
[0x41] = 0x80;
13575 SetKeyboardState(keyboard_state
);
13577 key_state
= GetAsyncKeyState(0x41);
13578 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13581 keybd_event(0x41, 0, 0, 0);
13582 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13583 DispatchMessageA(&msg
);
13584 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
13586 key_state
= GetAsyncKeyState(0x41);
13587 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13589 key_state
= GetKeyState(0x41);
13590 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13592 /* clear the key state in this thread */
13593 GetKeyboardState(keyboard_state
);
13594 keyboard_state
[0x41] = 0;
13595 SetKeyboardState(keyboard_state
);
13597 key_state
= GetAsyncKeyState(0x41);
13598 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13601 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
13602 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13603 DispatchMessageA(&msg
);
13604 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
13606 key_state
= GetAsyncKeyState(0x41);
13607 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13609 key_state
= GetKeyState(0x41);
13610 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13612 DestroyWindow(test_window
);
13616 static const struct message WmHotkeyPressLWIN
[] = {
13617 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
13618 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
13619 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
13622 static const struct message WmHotkeyPress
[] = {
13623 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13624 { WM_HOTKEY
, sent
|wparam
, 5 },
13627 static const struct message WmHotkeyRelease
[] = {
13628 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13629 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
13630 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
13633 static const struct message WmHotkeyReleaseLWIN
[] = {
13634 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
13635 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
13636 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
13639 static const struct message WmHotkeyCombined
[] = {
13640 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
13641 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13642 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13643 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
13644 { WM_APP
, sent
, 0, 0 },
13645 { WM_HOTKEY
, sent
|wparam
, 5 },
13646 { WM_APP
+1, sent
, 0, 0 },
13647 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
13648 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
13649 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
13650 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
13651 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
13652 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
13655 static const struct message WmHotkeyPrevious
[] = {
13656 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
13657 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13658 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13659 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
13660 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
13661 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
13662 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
13663 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
13664 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
13665 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
13666 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
13667 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
13670 static const struct message WmHotkeyNew
[] = {
13671 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13672 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13673 { WM_HOTKEY
, sent
|wparam
, 5 },
13674 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
13675 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
13679 static int hotkey_letter
;
13681 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
13683 struct recvd_message msg
;
13685 if (nCode
== HC_ACTION
)
13687 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
13690 msg
.message
= wParam
;
13691 msg
.flags
= kbd_hook
|wparam
|lparam
;
13692 msg
.wParam
= kdbhookstruct
->vkCode
;
13693 msg
.lParam
= kdbhookstruct
->flags
;
13694 msg
.descr
= "KeyboardHookProc";
13697 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
)
13699 ok(kdbhookstruct
->vkCode
== VK_LWIN
|| kdbhookstruct
->vkCode
== hotkey_letter
,
13700 "unexpected keycode %x\n", kdbhookstruct
->vkCode
);
13704 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
13707 static void test_hotkey(void)
13709 HWND test_window
, taskbar_window
;
13712 DWORD queue_status
;
13715 SetLastError(0xdeadbeef);
13716 ret
= UnregisterHotKey(NULL
, 0);
13717 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13718 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13719 "unexpected error %d\n", GetLastError());
13723 skip("hotkeys not supported\n");
13727 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13728 100, 100, 200, 200, 0, 0, 0, NULL
);
13732 SetLastError(0xdeadbeef);
13733 ret
= UnregisterHotKey(test_window
, 0);
13734 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13735 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13736 "unexpected error %d\n", GetLastError());
13738 /* Search for a Windows Key + letter combination that hasn't been registered */
13739 for (hotkey_letter
= 0x41; hotkey_letter
<= 0x51; hotkey_letter
++)
13741 SetLastError(0xdeadbeef);
13742 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
13750 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13751 "unexpected error %d\n", GetLastError());
13755 if (hotkey_letter
== 0x52)
13757 ok(0, "Couldn't find any free Windows Key + letter combination\n");
13761 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
13762 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
13764 /* Same key combination, different id */
13765 SetLastError(0xdeadbeef);
13766 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
13767 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13768 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13769 "unexpected error %d\n", GetLastError());
13771 /* Same key combination, different window */
13772 SetLastError(0xdeadbeef);
13773 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
13774 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13775 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13776 "unexpected error %d\n", GetLastError());
13778 /* Register the same hotkey twice */
13779 SetLastError(0xdeadbeef);
13780 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
13781 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13782 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13783 "unexpected error %d\n", GetLastError());
13785 /* Window on another thread */
13786 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
13787 if (!taskbar_window
)
13789 skip("no taskbar?\n");
13793 SetLastError(0xdeadbeef);
13794 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
13795 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13796 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
13797 "unexpected error %d\n", GetLastError());
13800 /* Inject the appropriate key sequence */
13801 keybd_event(VK_LWIN
, 0, 0, 0);
13802 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13803 DispatchMessageA(&msg
);
13804 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
13806 keybd_event(hotkey_letter
, 0, 0, 0);
13807 queue_status
= GetQueueStatus(QS_HOTKEY
);
13808 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
13809 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13811 if (msg
.message
== WM_HOTKEY
)
13813 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
13814 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13816 DispatchMessageA(&msg
);
13818 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
13820 queue_status
= GetQueueStatus(QS_HOTKEY
);
13821 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
13823 key_state
= GetAsyncKeyState(hotkey_letter
);
13824 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13826 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13827 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13828 DispatchMessageA(&msg
);
13829 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
13831 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13832 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13833 DispatchMessageA(&msg
);
13834 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
13836 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
13837 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
13838 queue_status
= GetQueueStatus(QS_HOTKEY
);
13839 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
13840 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
13841 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
13842 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13843 DispatchMessageA(&msg
);
13846 /* Send and process all messages at once */
13847 PostMessageA(test_window
, WM_APP
, 0, 0);
13848 keybd_event(VK_LWIN
, 0, 0, 0);
13849 keybd_event(hotkey_letter
, 0, 0, 0);
13850 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13851 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13853 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13855 if (msg
.message
== WM_HOTKEY
)
13857 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
13858 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13860 DispatchMessageA(&msg
);
13862 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
13864 /* Register same hwnd/id with different key combination */
13865 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
13866 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13868 /* Previous key combination does not work */
13869 keybd_event(VK_LWIN
, 0, 0, 0);
13870 keybd_event(hotkey_letter
, 0, 0, 0);
13871 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13872 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13874 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13875 DispatchMessageA(&msg
);
13876 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
13878 /* New key combination works */
13879 keybd_event(hotkey_letter
, 0, 0, 0);
13880 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13882 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13884 if (msg
.message
== WM_HOTKEY
)
13886 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
13887 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13889 DispatchMessageA(&msg
);
13891 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
13893 /* Unregister hotkey properly */
13894 ret
= UnregisterHotKey(test_window
, 5);
13895 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13897 /* Unregister hotkey again */
13898 SetLastError(0xdeadbeef);
13899 ret
= UnregisterHotKey(test_window
, 5);
13900 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13901 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13902 "unexpected error %d\n", GetLastError());
13904 /* Register thread hotkey */
13905 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
13906 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13908 /* Inject the appropriate key sequence */
13909 keybd_event(VK_LWIN
, 0, 0, 0);
13910 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13912 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13913 DispatchMessageA(&msg
);
13915 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
13917 keybd_event(hotkey_letter
, 0, 0, 0);
13918 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13920 if (msg
.message
== WM_HOTKEY
)
13922 struct recvd_message message
;
13923 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
13924 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13925 message
.message
= msg
.message
;
13926 message
.flags
= sent
|wparam
|lparam
;
13927 message
.wParam
= msg
.wParam
;
13928 message
.lParam
= msg
.lParam
;
13929 message
.descr
= "test_hotkey thread message";
13930 add_message(&message
);
13933 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13934 DispatchMessageA(&msg
);
13936 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
13938 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13939 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13941 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13942 DispatchMessageA(&msg
);
13944 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
13946 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13947 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13949 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13950 DispatchMessageA(&msg
);
13952 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
13954 /* Unregister thread hotkey */
13955 ret
= UnregisterHotKey(NULL
, 5);
13956 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13958 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
13962 UnregisterHotKey(NULL
, 5);
13963 UnregisterHotKey(test_window
, 5);
13964 DestroyWindow(test_window
);
13969 static const struct message WmSetFocus_1
[] = {
13970 { HCBT_SETFOCUS
, hook
}, /* child */
13971 { HCBT_ACTIVATE
, hook
}, /* parent */
13972 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
13973 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
13974 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
13975 { WM_NCACTIVATE
, sent
|parent
},
13976 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
13977 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
13978 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
13979 { HCBT_SETFOCUS
, hook
}, /* parent */
13980 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
13981 { WM_KILLFOCUS
, sent
|parent
},
13982 { WM_SETFOCUS
, sent
},
13985 static const struct message WmSetFocus_2
[] = {
13986 { HCBT_SETFOCUS
, hook
}, /* parent */
13987 { WM_KILLFOCUS
, sent
},
13988 { WM_SETFOCUS
, sent
|parent
},
13991 static const struct message WmSetFocus_3
[] = {
13992 { HCBT_SETFOCUS
, hook
}, /* child */
13995 static const struct message WmSetFocus_4
[] = {
13999 static void test_SetFocus(void)
14001 HWND parent
, old_parent
, child
, old_focus
, old_active
;
14003 struct wnd_event wnd_event
;
14007 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
14008 ok(wnd_event
.start_event
!= 0, "CreateEvent error %d\n", GetLastError());
14009 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
14010 ok(hthread
!= 0, "CreateThread error %d\n", GetLastError());
14011 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
14012 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
14013 CloseHandle(wnd_event
.start_event
);
14015 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
14016 0, 0, 0, 0, 0, 0, 0, NULL
);
14017 ok(parent
!= 0, "failed to create parent window\n");
14018 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
14019 0, 0, 0, 0, parent
, 0, 0, NULL
);
14020 ok(child
!= 0, "failed to create child window\n");
14022 trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
14025 SetActiveWindow(0);
14030 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
14031 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
14033 log_all_parent_messages
++;
14035 old_focus
= SetFocus(child
);
14036 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14037 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
14038 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
14039 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14040 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
14042 old_focus
= SetFocus(parent
);
14043 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14044 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
14045 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
14046 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14047 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14049 SetLastError(0xdeadbeef);
14050 old_focus
= SetFocus((HWND
)0xdeadbeef);
14051 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14052 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
14053 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14054 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
14055 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14056 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14057 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14059 SetLastError(0xdeadbeef);
14060 old_focus
= SetFocus(GetDesktopWindow());
14061 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
14062 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
14063 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14064 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
14065 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14066 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14067 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14069 SetLastError(0xdeadbeef);
14070 old_focus
= SetFocus(wnd_event
.hwnd
);
14071 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
14072 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
14073 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14074 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
14075 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14076 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14077 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14079 SetLastError(0xdeadbeef);
14080 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
14081 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14082 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
14083 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14084 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
14085 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
14086 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14087 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14089 SetLastError(0xdeadbeef);
14090 old_active
= SetActiveWindow(GetDesktopWindow());
14092 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
14093 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14094 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
14095 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
14096 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14097 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14099 SetLastError(0xdeadbeef);
14100 old_active
= SetActiveWindow(wnd_event
.hwnd
);
14102 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
14103 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14104 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
14105 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
14106 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14107 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14109 SetLastError(0xdeadbeef);
14110 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
14111 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
14114 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14115 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14120 old_focus
= SetFocus(wnd_event
.hwnd
);
14121 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14122 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
14123 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
14124 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
14126 old_focus
= SetFocus(parent
);
14127 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14128 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
14129 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14130 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14135 old_active
= SetActiveWindow(wnd_event
.hwnd
);
14136 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14137 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
14138 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
14139 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
14141 SetLastError(0xdeadbeef);
14142 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
14143 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
14145 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
14146 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
14148 old_parent
= SetParent(child
, GetDesktopWindow());
14149 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
14151 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
14152 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
14154 old_focus
= SetFocus(parent
);
14155 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14156 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
14157 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14158 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14163 SetLastError(0xdeadbeef);
14164 old_focus
= SetFocus(child
);
14166 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
14167 broken(GetLastError() == 0) /* XP */ ||
14168 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
14169 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14170 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
14171 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14172 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14173 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14175 SetLastError(0xdeadbeef);
14176 old_active
= SetActiveWindow(child
);
14177 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
14178 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14179 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
14180 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
14181 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14182 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14184 log_all_parent_messages
--;
14186 DestroyWindow(child
);
14187 DestroyWindow(parent
);
14189 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
14190 ok(ret
, "PostMessage(WM_QUIT) error %d\n", GetLastError());
14191 ret
= WaitForSingleObject(hthread
, INFINITE
);
14192 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
14193 CloseHandle(hthread
);
14196 static const struct message WmSetLayeredStyle
[] = {
14197 { WM_STYLECHANGING
, sent
},
14198 { WM_STYLECHANGED
, sent
},
14199 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14203 static const struct message WmSetLayeredStyle2
[] = {
14204 { WM_STYLECHANGING
, sent
},
14205 { WM_STYLECHANGED
, sent
},
14206 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14207 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
14208 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14209 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
14210 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
14214 struct layered_window_info
14223 static DWORD CALLBACK
update_layered_proc( void *param
)
14225 struct layered_window_info
*info
= param
;
14226 POINT src
= { 0, 0 };
14228 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
14229 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14230 ok( info
->ret
, "failed\n");
14231 SetEvent( info
->event
);
14235 static void test_layered_window(void)
14246 struct layered_window_info info
;
14248 if (!pUpdateLayeredWindow
)
14250 win_skip( "UpdateLayeredWindow not supported\n" );
14254 hdc
= CreateCompatibleDC( 0 );
14255 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
14256 SelectObject( hdc
, bmp
);
14258 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
14259 100, 100, 300, 300, 0, 0, 0, NULL
);
14260 ok( hwnd
!= 0, "failed to create window\n" );
14261 ShowWindow( hwnd
, SW_SHOWNORMAL
);
14262 UpdateWindow( hwnd
);
14266 GetWindowRect( hwnd
, &rect
);
14267 GetClientRect( hwnd
, &client
);
14268 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
14269 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
14272 pos
.x
= pos
.y
= 300;
14273 size
.cx
= size
.cy
= 250;
14274 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14275 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
14276 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
14277 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
14278 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
14280 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14281 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
14282 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
14283 GetWindowRect( hwnd
, &rect
);
14284 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
14285 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14286 GetClientRect( hwnd
, &rect
);
14287 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
14288 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14292 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14293 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
14294 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
14295 GetWindowRect( hwnd
, &rect
);
14296 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
14297 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14298 GetClientRect( hwnd
, &rect
);
14299 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
14300 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14302 SetWindowLongA( hwnd
, GWL_STYLE
,
14303 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
14304 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
14308 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14309 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
14310 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
14311 GetWindowRect( hwnd
, &rect
);
14312 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
14313 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14314 GetClientRect( hwnd
, &rect
);
14315 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
14316 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
14317 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14320 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14321 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
14322 ok( GetLastError() == ERROR_INVALID_PARAMETER
|| broken(ERROR_MR_MID_NOT_FOUND
) /* win7 */,
14323 "wrong error %u\n", GetLastError() );
14326 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14327 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
14328 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
14330 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
14331 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
14332 GetWindowRect( hwnd
, &rect
);
14333 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
14334 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14335 GetClientRect( hwnd
, &rect
);
14336 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
14337 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
14338 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14340 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
14343 info
.size
.cx
= 250;
14344 info
.size
.cy
= 300;
14345 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
14347 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
14348 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
14349 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
14350 WaitForSingleObject( thread
, 1000 );
14351 CloseHandle( thread
);
14352 GetWindowRect( hwnd
, &rect
);
14353 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
14354 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14355 GetClientRect( hwnd
, &rect
);
14356 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
14357 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
14358 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14360 DestroyWindow( hwnd
);
14362 DeleteObject( bmp
);
14365 static HMENU hpopupmenu
;
14367 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14369 if (ignore_message( message
)) return 0;
14373 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
14377 case WM_INITMENUPOPUP
:
14378 case WM_UNINITMENUPOPUP
:
14379 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %lx\n", hpopupmenu
, wParam
);
14381 case WM_CAPTURECHANGED
:
14382 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %lx\n", lParam
);
14386 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
14389 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14391 if (ignore_message( message
)) return 0;
14394 case WM_ENTERMENULOOP
:
14395 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
14399 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
14402 static void test_TrackPopupMenu(void)
14407 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
14410 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
14412 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
14414 hpopupmenu
= CreatePopupMenu();
14415 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
14417 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
14418 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
14422 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14423 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
14424 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
14426 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
14430 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14431 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
14432 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
14434 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
14440 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14441 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
14442 ok(ret
== 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError());
14444 DestroyMenu(hpopupmenu
);
14445 DestroyWindow(hwnd
);
14448 static void test_TrackPopupMenuEmpty(void)
14453 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
14456 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
14458 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
14460 hpopupmenu
= CreatePopupMenu();
14461 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
14465 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14466 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
14467 todo_wine
ok(ret
== 0, "TrackPopupMenu succeeded\n");
14469 DestroyMenu(hpopupmenu
);
14470 DestroyWindow(hwnd
);
14473 static void init_funcs(void)
14475 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
14477 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
14480 X(DeactivateActCtx
);
14481 X(GetCurrentActCtx
);
14490 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
14491 HMODULE hModuleImm32
;
14492 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
14497 argc
= winetest_get_mainargs( &test_argv
);
14501 /* Child process. */
14502 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
14503 do_wait_idle_child( arg
);
14507 InitializeCriticalSection( &sequence_cs
);
14510 hModuleImm32
= LoadLibraryA("imm32.dll");
14511 if (hModuleImm32
) {
14512 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
14513 if (pImmDisableIME
)
14516 pImmDisableIME
= NULL
;
14517 FreeLibrary(hModuleImm32
);
14519 if (!RegisterWindowClasses()) assert(0);
14521 if (pSetWinEventHook
)
14523 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
14524 GetModuleHandleA(0), win_event_proc
,
14525 0, GetCurrentThreadId(),
14526 WINEVENT_INCONTEXT
);
14527 if (pIsWinEventHookInstalled
&& hEvent_hook
)
14530 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
14531 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
14534 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
14536 cbt_hook_thread_id
= GetCurrentThreadId();
14537 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
14538 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
14542 /* Fix message sequences before removing 4 lines below */
14543 if (pUnhookWinEvent
&& hEvent_hook
)
14545 ret
= pUnhookWinEvent(hEvent_hook
);
14546 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
14547 pUnhookWinEvent
= 0;
14552 test_PostMessage();
14554 test_PeekMessage();
14555 test_PeekMessage2();
14556 test_WaitForInputIdle( test_argv
[0] );
14557 test_scrollwindowex();
14559 test_setwindowpos();
14561 invisible_parent_tests();
14562 test_mdi_messages();
14563 test_button_messages();
14564 test_static_messages();
14565 test_listbox_messages();
14566 test_combobox_messages();
14567 test_wmime_keydown_message();
14568 test_paint_messages();
14569 test_interthread_messages();
14570 test_message_conversion();
14571 test_accelerators();
14573 test_timers_no_wnd();
14574 if (hCBT_hook
) test_set_hook();
14575 test_DestroyWindow();
14576 test_DispatchMessage();
14577 test_SendMessageTimeout();
14578 test_edit_messages();
14579 test_quit_message();
14580 test_SetActiveWindow();
14582 if (!pTrackMouseEvent
)
14583 win_skip("TrackMouseEvent is not available\n");
14585 test_TrackMouseEvent();
14587 test_SetWindowRgn();
14589 test_dialog_messages();
14591 test_nullCallback();
14592 test_dbcs_wm_char();
14593 test_unicode_wm_char();
14594 test_menu_messages();
14595 test_paintingloop();
14597 test_clipboard_viewers();
14600 test_layered_window();
14601 if(!winetest_interactive
)
14602 skip("CORE-8299 : Skip Tracking popup menu tests.\n");
14605 test_TrackPopupMenu();
14606 test_TrackPopupMenuEmpty();
14608 /* keep it the last test, under Windows it tends to break the tests
14609 * which rely on active/foreground windows being correct.
14611 test_SetForegroundWindow();
14613 UnhookWindowsHookEx(hCBT_hook
);
14614 if (pUnhookWinEvent
&& hEvent_hook
)
14616 ret
= pUnhookWinEvent(hEvent_hook
);
14617 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
14618 SetLastError(0xdeadbeef);
14619 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
14620 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
14621 GetLastError() == 0xdeadbeef, /* Win9x */
14622 "unexpected error %d\n", GetLastError());
14624 DeleteCriticalSection( &sequence_cs
);