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 /* Resizing child window with MoveWindow (32) */
1176 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1177 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1178 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1179 { WM_ERASEBKGND
, sent
|parent
|optional
},
1180 { WM_ERASEBKGND
, sent
|optional
},
1181 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1182 { WM_MOVE
, sent
|defwinproc
},
1183 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1184 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1187 /* Creation of a custom dialog (32) */
1188 static const struct message WmCreateCustomDialogSeq
[] = {
1189 { HCBT_CREATEWND
, hook
},
1190 { WM_GETMINMAXINFO
, sent
},
1191 { WM_NCCREATE
, sent
},
1192 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1193 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1194 { WM_CREATE
, sent
},
1195 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1196 { WM_NOTIFYFORMAT
, sent
|optional
},
1197 { WM_QUERYUISTATE
, sent
|optional
},
1198 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1199 { WM_GETMINMAXINFO
, sent
|optional
},
1200 { WM_NCCALCSIZE
, sent
|optional
},
1201 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1202 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1203 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1204 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1205 { HCBT_ACTIVATE
, hook
},
1206 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1209 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1211 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1213 { WM_NCACTIVATE
, sent
},
1214 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1215 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1216 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1217 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1218 { WM_ACTIVATE
, sent
|wparam
, 1 },
1219 { WM_GETTEXT
, sent
|optional
},
1220 { WM_KILLFOCUS
, sent
|parent
},
1221 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1222 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1223 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1224 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1225 { WM_SETFOCUS
, sent
},
1226 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1227 { WM_NCPAINT
, sent
|wparam
, 1 },
1228 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1229 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1230 { WM_ERASEBKGND
, sent
},
1231 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1232 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1233 { WM_GETTEXT
, sent
|optional
},
1234 { WM_GETTEXT
, sent
|optional
},
1235 { WM_NCCALCSIZE
, sent
|optional
},
1236 { WM_NCPAINT
, sent
|optional
},
1237 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1238 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1239 { WM_ERASEBKGND
, sent
|optional
},
1240 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1241 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1242 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1246 /* Calling EndDialog for a custom dialog (32) */
1247 static const struct message WmEndCustomDialogSeq
[] = {
1248 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1249 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1250 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1251 { WM_GETTEXT
, sent
|optional
},
1252 { HCBT_ACTIVATE
, hook
},
1253 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1254 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1255 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1256 { WM_ACTIVATE
, sent
|wparam
, 0 },
1257 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1258 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1259 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1260 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1261 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1262 { HCBT_SETFOCUS
, hook
},
1263 { WM_KILLFOCUS
, sent
},
1264 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1265 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1266 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1267 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1268 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1271 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1272 static const struct message WmShowCustomDialogSeq
[] = {
1273 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1274 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1275 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1276 { HCBT_ACTIVATE
, hook
},
1277 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1279 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1281 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1282 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1283 { WM_NCACTIVATE
, sent
},
1284 { WM_ACTIVATE
, sent
|wparam
, 1 },
1285 { WM_GETTEXT
, sent
|optional
},
1287 { WM_KILLFOCUS
, sent
|parent
},
1288 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1289 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1290 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1291 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1292 { WM_SETFOCUS
, sent
},
1293 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1294 { WM_NCPAINT
, sent
|wparam
, 1 },
1295 { WM_ERASEBKGND
, sent
},
1296 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1297 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1300 /* Creation and destruction of a modal dialog (32) */
1301 static const struct message WmModalDialogSeq
[] = {
1302 { WM_CANCELMODE
, sent
|parent
},
1303 { HCBT_SETFOCUS
, hook
},
1304 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1305 { WM_KILLFOCUS
, sent
|parent
},
1306 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1307 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1308 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1309 { HCBT_CREATEWND
, hook
},
1310 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1311 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1312 { WM_SETFONT
, sent
},
1313 { WM_INITDIALOG
, sent
},
1314 { WM_CHANGEUISTATE
, sent
|optional
},
1315 { WM_UPDATEUISTATE
, sent
|optional
},
1316 { WM_SHOWWINDOW
, sent
},
1317 { HCBT_ACTIVATE
, hook
},
1318 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1319 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1320 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1321 { WM_NCACTIVATE
, sent
},
1322 { WM_GETTEXT
, sent
|optional
},
1323 { WM_ACTIVATE
, sent
|wparam
, 1 },
1324 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1325 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1326 { WM_NCPAINT
, sent
|optional
},
1327 { WM_GETTEXT
, sent
|optional
},
1328 { WM_ERASEBKGND
, sent
|optional
},
1329 { WM_CTLCOLORDLG
, sent
|optional
},
1330 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1331 { WM_GETTEXT
, sent
|optional
},
1332 { WM_NCCALCSIZE
, sent
|optional
},
1333 { WM_NCPAINT
, sent
|optional
},
1334 { WM_GETTEXT
, sent
|optional
},
1335 { WM_ERASEBKGND
, sent
|optional
},
1336 { WM_CTLCOLORDLG
, sent
|optional
},
1337 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1338 { WM_PAINT
, sent
|optional
},
1339 { WM_CTLCOLORBTN
, sent
|optional
},
1340 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1341 { WM_ENTERIDLE
, sent
|parent
|optional
},
1342 { WM_ENTERIDLE
, sent
|parent
|optional
},
1343 { WM_ENTERIDLE
, sent
|parent
|optional
},
1344 { WM_ENTERIDLE
, sent
|parent
|optional
},
1345 { WM_ENTERIDLE
, sent
|parent
|optional
},
1346 { WM_ENTERIDLE
, sent
|parent
|optional
},
1347 { WM_ENTERIDLE
, sent
|parent
|optional
},
1348 { WM_ENTERIDLE
, sent
|parent
|optional
},
1349 { WM_ENTERIDLE
, sent
|parent
|optional
},
1350 { WM_ENTERIDLE
, sent
|parent
|optional
},
1351 { WM_ENTERIDLE
, sent
|parent
|optional
},
1352 { WM_ENTERIDLE
, sent
|parent
|optional
},
1353 { WM_ENTERIDLE
, sent
|parent
|optional
},
1354 { WM_ENTERIDLE
, sent
|parent
|optional
},
1355 { WM_ENTERIDLE
, sent
|parent
|optional
},
1356 { WM_ENTERIDLE
, sent
|parent
|optional
},
1357 { WM_ENTERIDLE
, sent
|parent
|optional
},
1358 { WM_ENTERIDLE
, sent
|parent
|optional
},
1359 { WM_ENTERIDLE
, sent
|parent
|optional
},
1360 { WM_ENTERIDLE
, sent
|parent
|optional
},
1362 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1363 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1364 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1365 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1366 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1367 { WM_GETTEXT
, sent
|optional
},
1368 { HCBT_ACTIVATE
, hook
},
1369 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1370 { WM_GETTEXT
, sent
|optional
},
1371 { WM_ACTIVATE
, sent
|wparam
, 0 },
1372 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1373 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1374 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1375 { HCBT_SETFOCUS
, hook
},
1376 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1377 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1378 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1379 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1380 { HCBT_DESTROYWND
, hook
},
1381 { 0x0090, sent
|optional
},
1382 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1383 { WM_DESTROY
, sent
},
1384 { WM_NCDESTROY
, sent
},
1387 /* SetMenu for NonVisible windows with size change*/
1388 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1389 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1390 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1391 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1392 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1393 { WM_MOVE
, sent
|defwinproc
},
1394 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1395 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1396 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1397 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1398 { WM_GETTEXT
, sent
|optional
},
1399 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1402 /* SetMenu for NonVisible windows with no size change */
1403 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1404 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1405 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1406 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1407 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1410 /* SetMenu for Visible windows with size change */
1411 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1412 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1413 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1414 { 0x0093, sent
|defwinproc
|optional
},
1415 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1416 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1417 { 0x0093, sent
|defwinproc
|optional
},
1418 { 0x0093, sent
|defwinproc
|optional
},
1419 { 0x0091, sent
|defwinproc
|optional
},
1420 { 0x0092, sent
|defwinproc
|optional
},
1421 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1422 { WM_ERASEBKGND
, sent
|optional
},
1423 { WM_ACTIVATE
, sent
|optional
},
1424 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1425 { WM_MOVE
, sent
|defwinproc
},
1426 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1427 { 0x0093, sent
|optional
},
1428 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1429 { 0x0093, sent
|defwinproc
|optional
},
1430 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1431 { 0x0093, sent
|defwinproc
|optional
},
1432 { 0x0093, sent
|defwinproc
|optional
},
1433 { 0x0091, sent
|defwinproc
|optional
},
1434 { 0x0092, sent
|defwinproc
|optional
},
1435 { WM_ERASEBKGND
, sent
|optional
},
1436 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1437 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1440 /* SetMenu for Visible windows with no size change */
1441 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1442 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1443 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1444 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1445 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1446 { WM_ERASEBKGND
, sent
|optional
},
1447 { WM_ACTIVATE
, sent
|optional
},
1448 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1449 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1452 /* DrawMenuBar for a visible window */
1453 static const struct message WmDrawMenuBarSeq
[] =
1455 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1456 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1457 { 0x0093, sent
|defwinproc
|optional
},
1458 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1459 { 0x0093, sent
|defwinproc
|optional
},
1460 { 0x0093, sent
|defwinproc
|optional
},
1461 { 0x0091, sent
|defwinproc
|optional
},
1462 { 0x0092, sent
|defwinproc
|optional
},
1463 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1464 { WM_ERASEBKGND
, sent
|optional
},
1465 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1466 { 0x0093, sent
|optional
},
1467 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1471 static const struct message WmSetRedrawFalseSeq
[] =
1473 { WM_SETREDRAW
, sent
|wparam
, 0 },
1477 static const struct message WmSetRedrawTrueSeq
[] =
1479 { WM_SETREDRAW
, sent
|wparam
, 1 },
1483 static const struct message WmEnableWindowSeq_1
[] =
1485 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1486 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1487 { HCBT_SETFOCUS
, hook
|optional
},
1488 { WM_KILLFOCUS
, sent
|optional
},
1489 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
1493 static const struct message WmEnableWindowSeq_2
[] =
1495 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1496 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
1500 static const struct message WmGetScrollRangeSeq
[] =
1502 { SBM_GETRANGE
, sent
},
1505 static const struct message WmGetScrollInfoSeq
[] =
1507 { SBM_GETSCROLLINFO
, sent
},
1510 static const struct message WmSetScrollRangeSeq
[] =
1512 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1513 sends SBM_SETSCROLLINFO.
1515 { SBM_SETSCROLLINFO
, sent
},
1518 /* SetScrollRange for a window without a non-client area */
1519 static const struct message WmSetScrollRangeHSeq_empty
[] =
1521 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 0 },
1524 static const struct message WmSetScrollRangeVSeq_empty
[] =
1526 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 0 },
1529 static const struct message WmSetScrollRangeHVSeq
[] =
1531 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1532 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1533 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1534 { WM_ERASEBKGND
, sent
|optional
},
1535 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1536 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1537 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1540 /* SetScrollRange for a window with a non-client area */
1541 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
1543 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1544 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1545 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1546 { WM_NCPAINT
, sent
|optional
},
1547 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1548 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1549 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1550 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1551 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1552 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1553 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1554 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1555 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1556 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1557 { WM_ERASEBKGND
, sent
|optional
},
1558 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
1559 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
1560 { WM_SIZE
, sent
|defwinproc
|optional
},
1561 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1562 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1563 { WM_GETTEXT
, sent
|optional
},
1564 { WM_GETTEXT
, sent
|optional
},
1565 { WM_GETTEXT
, sent
|optional
},
1566 { WM_GETTEXT
, sent
|optional
},
1569 /* test if we receive the right sequence of messages */
1570 /* after calling ShowWindow( SW_SHOWNA) */
1571 static const struct message WmSHOWNAChildInvisParInvis
[] = {
1572 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1575 static const struct message WmSHOWNAChildVisParInvis
[] = {
1576 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1579 static const struct message WmSHOWNAChildVisParVis
[] = {
1580 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1581 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1584 static const struct message WmSHOWNAChildInvisParVis
[] = {
1585 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1586 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1587 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1588 { WM_ERASEBKGND
, sent
|optional
},
1589 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
1592 static const struct message WmSHOWNATopVisible
[] = {
1593 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1594 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1595 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1596 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1597 { WM_ERASEBKGND
, sent
|optional
},
1598 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1601 static const struct message WmSHOWNATopInvisible
[] = {
1602 { WM_NOTIFYFORMAT
, sent
|optional
},
1603 { WM_QUERYUISTATE
, sent
|optional
},
1604 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1605 { WM_GETMINMAXINFO
, sent
|optional
},
1606 { WM_NCCALCSIZE
, sent
|optional
},
1607 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1608 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1609 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1610 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1611 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1612 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1613 { WM_ERASEBKGND
, sent
|optional
},
1614 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1615 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1616 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1617 { WM_ERASEBKGND
, sent
|optional
},
1618 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1619 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1624 static const struct message WmTrackPopupMenu
[] = {
1625 { HCBT_CREATEWND
, hook
},
1626 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1627 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1628 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1629 { 0x0093, sent
|optional
},
1630 { 0x0094, sent
|optional
},
1631 { 0x0094, sent
|optional
},
1632 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1633 { WM_CAPTURECHANGED
, sent
},
1634 { HCBT_DESTROYWND
, hook
},
1635 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1636 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1637 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1641 static const struct message WmTrackPopupMenuCapture
[] = {
1642 { HCBT_CREATEWND
, hook
},
1643 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1644 { WM_CAPTURECHANGED
, sent
},
1645 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1646 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1647 { 0x0093, sent
|optional
},
1648 { 0x0094, sent
|optional
},
1649 { 0x0094, sent
|optional
},
1650 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1651 { WM_CAPTURECHANGED
, sent
},
1652 { HCBT_DESTROYWND
, hook
},
1653 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1654 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1655 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1659 static const struct message WmTrackPopupMenuEmpty
[] = {
1660 { HCBT_CREATEWND
, hook
},
1661 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1662 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1663 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1664 { 0x0093, sent
|optional
},
1665 { 0x0094, sent
|optional
},
1666 { 0x0094, sent
|optional
},
1667 { WM_CAPTURECHANGED
, sent
},
1668 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1669 { HCBT_DESTROYWND
, hook
},
1670 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1674 static const struct message WmTrackPopupMenuAbort
[] = {
1675 { HCBT_CREATEWND
, hook
},
1676 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1677 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1678 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1679 { 0x0093, sent
|optional
},
1680 { 0x0094, sent
|optional
},
1681 { 0x0094, sent
|optional
},
1682 { WM_CAPTURECHANGED
, sent
},
1683 { HCBT_DESTROYWND
, hook
},
1684 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1685 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1686 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1690 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
1691 static int sequence_cnt
, sequence_size
;
1692 static struct recvd_message
* sequence
;
1693 static int log_all_parent_messages
;
1694 static CRITICAL_SECTION sequence_cs
;
1696 /* user32 functions */
1697 static HWND (WINAPI
*pGetAncestor
)(HWND
,UINT
);
1698 static BOOL (WINAPI
*pGetMenuInfo
)(HMENU
,LPCMENUINFO
);
1699 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
1700 static BOOL (WINAPI
*pSetMenuInfo
)(HMENU
,LPCMENUINFO
);
1701 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
1702 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
1703 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
1704 static BOOL (WINAPI
*pGetMonitorInfoA
)(HMONITOR
,LPMONITORINFO
);
1705 static HMONITOR (WINAPI
*pMonitorFromPoint
)(POINT
,DWORD
);
1706 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
1707 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
1708 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
1709 /* kernel32 functions */
1710 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
1712 static void init_procs(void)
1714 HMODULE user32
= GetModuleHandleA("user32.dll");
1715 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
1717 #define GET_PROC(dll, func) \
1718 p ## func = (void*)GetProcAddress(dll, #func); \
1720 trace("GetProcAddress(%s) failed\n", #func); \
1723 GET_PROC(user32
, GetAncestor
)
1724 GET_PROC(user32
, GetMenuInfo
)
1725 GET_PROC(user32
, NotifyWinEvent
)
1726 GET_PROC(user32
, SetMenuInfo
)
1727 GET_PROC(user32
, SetWinEventHook
)
1728 GET_PROC(user32
, TrackMouseEvent
)
1729 GET_PROC(user32
, UnhookWinEvent
)
1730 GET_PROC(user32
, GetMonitorInfoA
)
1731 GET_PROC(user32
, MonitorFromPoint
)
1732 GET_PROC(user32
, UpdateLayeredWindow
)
1733 GET_PROC(user32
, SetSystemTimer
)
1734 GET_PROC(user32
, KillSystemTimer
)
1736 GET_PROC(kernel32
, GetCPInfoExA
)
1741 static const char *get_winpos_flags(UINT flags
)
1743 static char buffer
[300];
1746 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
1747 DUMP( SWP_SHOWWINDOW
);
1748 DUMP( SWP_HIDEWINDOW
);
1749 DUMP( SWP_NOACTIVATE
);
1750 DUMP( SWP_FRAMECHANGED
);
1751 DUMP( SWP_NOCOPYBITS
);
1752 DUMP( SWP_NOOWNERZORDER
);
1753 DUMP( SWP_NOSENDCHANGING
);
1754 DUMP( SWP_DEFERERASE
);
1755 DUMP( SWP_ASYNCWINDOWPOS
);
1756 DUMP( SWP_NOZORDER
);
1757 DUMP( SWP_NOREDRAW
);
1760 DUMP( SWP_NOCLIENTSIZE
);
1761 DUMP( SWP_NOCLIENTMOVE
);
1762 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
1767 static BOOL
ignore_message( UINT message
)
1769 /* these are always ignored */
1770 return (message
>= 0xc000 ||
1771 message
== WM_GETICON
||
1772 message
== WM_GETOBJECT
||
1773 message
== WM_TIMECHANGE
||
1774 message
== WM_DISPLAYCHANGE
||
1775 message
== WM_DEVICECHANGE
||
1776 message
== WM_DWMNCRENDERINGCHANGED
);
1780 #define add_message(msg) add_message_(__LINE__,msg);
1781 static void add_message_(int line
, const struct recvd_message
*msg
)
1783 struct recvd_message
*seq
;
1785 EnterCriticalSection( &sequence_cs
);
1789 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
) );
1791 if (sequence_cnt
== sequence_size
)
1794 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof(*sequence
) );
1798 seq
= &sequence
[sequence_cnt
++];
1799 seq
->hwnd
= msg
->hwnd
;
1800 seq
->message
= msg
->message
;
1801 seq
->flags
= msg
->flags
;
1802 seq
->wParam
= msg
->wParam
;
1803 seq
->lParam
= msg
->lParam
;
1805 seq
->descr
= msg
->descr
;
1807 LeaveCriticalSection( &sequence_cs
);
1811 if (msg
->flags
& hook
)
1813 static const char * const CBT_code_name
[10] =
1821 "HCBT_CLICKSKIPPED",
1826 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
1828 sprintf( seq
->output
, "%s: hook %d (%s) wp %08lx lp %08lx",
1829 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
1831 else if (msg
->flags
& winevent_hook
)
1833 sprintf( seq
->output
, "%s: winevent %p %08x %08lx %08lx",
1834 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
1838 switch (msg
->message
)
1840 case WM_WINDOWPOSCHANGING
:
1841 case WM_WINDOWPOSCHANGED
:
1843 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
1845 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s",
1846 msg
->descr
, msg
->hwnd
,
1847 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
1848 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
1849 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
1850 get_winpos_flags(winpos
->flags
) );
1852 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1853 * in the high word for internal purposes
1855 seq
->wParam
= winpos
->flags
& 0xffff;
1856 /* We are not interested in the flags that don't match under XP and Win9x */
1857 seq
->wParam
&= ~SWP_NOZORDER
;
1863 DRAW_ITEM_STRUCT di
;
1864 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
1866 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
1867 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
1868 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
1871 di
.u
.item
.type
= dis
->CtlType
;
1872 di
.u
.item
.ctl_id
= dis
->CtlID
;
1873 if (dis
->CtlType
== ODT_LISTBOX
||
1874 dis
->CtlType
== ODT_COMBOBOX
||
1875 dis
->CtlType
== ODT_MENU
)
1876 di
.u
.item
.item_id
= dis
->itemID
;
1877 di
.u
.item
.action
= dis
->itemAction
;
1878 di
.u
.item
.state
= dis
->itemState
;
1880 seq
->lParam
= di
.u
.lp
;
1884 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
1885 sprintf( seq
->output
, "%s: %p %04x wp %08lx lp %08lx",
1886 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
1888 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
1889 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
1894 /* try to make sure pending X events have been processed before continuing */
1895 static void flush_events(void)
1899 int min_timeout
= 100;
1900 DWORD time
= GetTickCount() + diff
;
1904 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
1905 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
1906 diff
= time
- GetTickCount();
1910 static void flush_sequence(void)
1912 EnterCriticalSection( &sequence_cs
);
1913 HeapFree(GetProcessHeap(), 0, sequence
);
1915 sequence_cnt
= sequence_size
= 0;
1916 LeaveCriticalSection( &sequence_cs
);
1919 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
1921 const struct recvd_message
*actual
= sequence
;
1922 unsigned int count
= 0;
1924 trace_(file
, line
)("Failed sequence %s:\n", context
);
1925 while (expected
->message
&& actual
->message
)
1927 if (actual
->output
[0])
1929 if (expected
->flags
& hook
)
1931 trace_(file
, line
)( " %u: expected: hook %04x - actual: %s\n",
1932 count
, expected
->message
, actual
->output
);
1934 else if (expected
->flags
& winevent_hook
)
1936 trace_(file
, line
)( " %u: expected: winevent %04x - actual: %s\n",
1937 count
, expected
->message
, actual
->output
);
1939 else if (expected
->flags
& kbd_hook
)
1941 trace_(file
, line
)( " %u: expected: kbd %04x - actual: %s\n",
1942 count
, expected
->message
, actual
->output
);
1946 trace_(file
, line
)( " %u: expected: msg %04x - actual: %s\n",
1947 count
, expected
->message
, actual
->output
);
1951 if (expected
->message
== actual
->message
)
1953 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) &&
1954 (expected
->flags
& optional
))
1956 /* don't match messages if their defwinproc status differs */
1965 /* silently drop winevent messages if there is no support for them */
1966 else if ((expected
->flags
& optional
) || ((expected
->flags
& winevent_hook
) && !hEvent_hook
))
1976 /* optional trailing messages */
1977 while (expected
->message
&& ((expected
->flags
& optional
) ||
1978 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
1980 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
1985 if (expected
->message
)
1987 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
1991 while (actual
->message
&& actual
->output
[0])
1993 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
1999 #define ok_sequence( exp, contx, todo) \
2000 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2003 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2004 const char *file
, int line
)
2006 static const struct recvd_message end_of_sequence
;
2007 const struct message
*expected
= expected_list
;
2008 const struct recvd_message
*actual
;
2009 int failcount
= 0, dump
= 0;
2010 unsigned int count
= 0;
2012 add_message(&end_of_sequence
);
2016 while (expected
->message
&& actual
->message
)
2018 if (expected
->message
== actual
->message
&&
2019 !((expected
->flags
^ actual
->flags
) & (hook
|winevent_hook
|kbd_hook
)))
2021 if (expected
->flags
& wparam
)
2023 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2027 if (strcmp(winetest_platform
, "wine")) dump
++;
2028 ok_( file
, line
) (FALSE
,
2029 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2030 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2035 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2036 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2037 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2038 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2042 if (expected
->flags
& lparam
)
2044 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2048 if (strcmp(winetest_platform
, "wine")) dump
++;
2049 ok_( file
, line
) (FALSE
,
2050 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2051 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2056 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2057 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2058 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2059 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2062 if ((expected
->flags
& optional
) &&
2063 ((expected
->flags
^ actual
->flags
) & (defwinproc
|parent
)))
2065 /* don't match optional messages if their defwinproc or parent status differs */
2070 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2074 if (strcmp(winetest_platform
, "wine")) dump
++;
2075 ok_( file
, line
) (FALSE
,
2076 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2077 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2082 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2083 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2084 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2085 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2088 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2089 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n",
2090 context
, count
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2091 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2093 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2094 "%s: %u: the msg 0x%04x should have been %s\n",
2095 context
, count
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2096 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2098 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2099 "%s: %u: the msg 0x%04x was expected in %s\n",
2100 context
, count
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2101 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2103 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
2104 "%s: %u: the msg 0x%04x should have been sent by a hook\n",
2105 context
, count
, expected
->message
);
2106 if ((expected
->flags
& hook
) != (actual
->flags
& hook
)) dump
++;
2108 ok_( file
, line
) ((expected
->flags
& winevent_hook
) == (actual
->flags
& winevent_hook
),
2109 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n",
2110 context
, count
, expected
->message
);
2111 if ((expected
->flags
& winevent_hook
) != (actual
->flags
& winevent_hook
)) dump
++;
2113 ok_( file
, line
) ((expected
->flags
& kbd_hook
) == (actual
->flags
& kbd_hook
),
2114 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n",
2115 context
, count
, expected
->message
);
2116 if ((expected
->flags
& kbd_hook
) != (actual
->flags
& kbd_hook
)) dump
++;
2121 /* silently drop hook messages if there is no support for them */
2122 else if ((expected
->flags
& optional
) ||
2123 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2124 ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2125 ((expected
->flags
& kbd_hook
) && !hKBD_hook
))
2131 if (strcmp(winetest_platform
, "wine")) dump
++;
2132 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2133 context
, count
, expected
->message
, actual
->message
);
2139 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2140 context
, count
, expected
->message
, actual
->message
);
2148 /* skip all optional trailing messages */
2149 while (expected
->message
&& ((expected
->flags
& optional
) ||
2150 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2151 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2157 if (expected
->message
|| actual
->message
) {
2159 if (strcmp(winetest_platform
, "wine")) dump
++;
2160 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2161 context
, count
, expected
->message
, actual
->message
);
2167 if (expected
->message
|| actual
->message
)
2170 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2171 context
, count
, expected
->message
, actual
->message
);
2174 if( todo
&& !failcount
) /* succeeded yet marked todo */
2176 if (!strcmp(winetest_platform
, "wine")) dump
++;
2177 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
2181 if (dump
) dump_sequence(expected_list
, context
, file
, line
);
2185 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
2187 /******************************** MDI test **********************************/
2189 /* CreateWindow for MDI frame window, initially visible */
2190 static const struct message WmCreateMDIframeSeq
[] = {
2191 { HCBT_CREATEWND
, hook
},
2192 { WM_GETMINMAXINFO
, sent
},
2193 { WM_NCCREATE
, sent
},
2194 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2195 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
2196 { WM_CREATE
, sent
},
2197 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2198 { WM_NOTIFYFORMAT
, sent
|optional
},
2199 { WM_QUERYUISTATE
, sent
|optional
},
2200 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2201 { WM_GETMINMAXINFO
, sent
|optional
},
2202 { WM_NCCALCSIZE
, sent
|optional
},
2203 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2204 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2205 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2206 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2207 { HCBT_ACTIVATE
, hook
},
2208 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
2209 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2210 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2211 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2212 { WM_NCACTIVATE
, sent
},
2213 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2214 { WM_ACTIVATE
, sent
|wparam
, 1 },
2215 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2216 { HCBT_SETFOCUS
, hook
},
2217 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2218 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2219 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2220 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2221 /* Win9x adds SWP_NOZORDER below */
2222 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2223 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2224 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2225 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2229 /* DestroyWindow for MDI frame window, initially visible */
2230 static const struct message WmDestroyMDIframeSeq
[] = {
2231 { HCBT_DESTROYWND
, hook
},
2232 { 0x0090, sent
|optional
},
2233 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2234 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2235 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2236 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2237 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
2238 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2239 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
2240 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
2241 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2242 { WM_DESTROY
, sent
},
2243 { WM_NCDESTROY
, sent
},
2246 /* CreateWindow for MDI client window, initially visible */
2247 static const struct message WmCreateMDIclientSeq
[] = {
2248 { HCBT_CREATEWND
, hook
},
2249 { WM_NCCREATE
, sent
},
2250 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2251 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2252 { WM_CREATE
, sent
},
2253 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2254 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2255 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2257 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
2258 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2259 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2260 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2261 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2264 /* ShowWindow(SW_SHOW) for MDI client window */
2265 static const struct message WmShowMDIclientSeq
[] = {
2266 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2267 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2268 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2269 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2272 /* ShowWindow(SW_HIDE) for MDI client window */
2273 static const struct message WmHideMDIclientSeq
[] = {
2274 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2275 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2276 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
2277 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
2278 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2281 /* DestroyWindow for MDI client window, initially visible */
2282 static const struct message WmDestroyMDIclientSeq
[] = {
2283 { HCBT_DESTROYWND
, hook
},
2284 { 0x0090, sent
|optional
},
2285 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
2286 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2287 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2288 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2289 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2290 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2291 { WM_DESTROY
, sent
},
2292 { WM_NCDESTROY
, sent
},
2295 /* CreateWindow for MDI child window, initially visible */
2296 static const struct message WmCreateMDIchildVisibleSeq
[] = {
2297 { HCBT_CREATEWND
, hook
},
2298 { WM_NCCREATE
, sent
},
2299 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2300 { WM_CREATE
, sent
},
2301 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2302 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2304 /* Win2k sends wparam set to
2305 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2306 * while Win9x doesn't bother to set child window id according to
2307 * CLIENTCREATESTRUCT.idFirstChild
2309 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2310 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2311 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2312 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2313 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2314 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2315 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2316 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2317 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2319 /* Win9x: message sequence terminates here. */
2321 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2322 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2323 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2324 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2325 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2326 { WM_SETFOCUS
, sent
}, /* in MDI client */
2327 { HCBT_SETFOCUS
, hook
},
2328 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2329 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2330 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2331 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2332 { WM_SETFOCUS
, sent
|defwinproc
},
2333 { WM_MDIACTIVATE
, sent
|defwinproc
},
2336 /* CreateWindow for MDI child window with invisible parent */
2337 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
2338 { HCBT_CREATEWND
, hook
},
2339 { WM_GETMINMAXINFO
, sent
},
2340 { WM_NCCREATE
, sent
},
2341 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2342 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2343 { WM_CREATE
, sent
},
2344 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2345 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2347 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2348 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2349 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
2350 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2351 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2352 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2354 /* Win9x: message sequence terminates here. */
2356 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2357 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2358 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2359 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2360 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2361 { WM_SETFOCUS
, sent
}, /* in MDI client */
2362 { HCBT_SETFOCUS
, hook
},
2363 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2364 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2365 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2366 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2367 { WM_SETFOCUS
, sent
|defwinproc
},
2368 { WM_MDIACTIVATE
, sent
|defwinproc
},
2371 /* DestroyWindow for MDI child window, initially visible */
2372 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
2373 { HCBT_DESTROYWND
, hook
},
2374 /* Win2k sends wparam set to
2375 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2376 * while Win9x doesn't bother to set child window id according to
2377 * CLIENTCREATESTRUCT.idFirstChild
2379 { 0x0090, sent
|optional
},
2380 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2381 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2382 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2383 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2384 { WM_ERASEBKGND
, sent
|parent
|optional
},
2385 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2387 /* { WM_DESTROY, sent }
2388 * Win9x: message sequence terminates here.
2391 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2392 { WM_KILLFOCUS
, sent
},
2393 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2394 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2395 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2396 { WM_SETFOCUS
, sent
}, /* in MDI client */
2398 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2399 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2400 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2401 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2402 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2403 { WM_SETFOCUS
, sent
}, /* in MDI client */
2405 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2407 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2408 { WM_KILLFOCUS
, sent
},
2409 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2410 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2411 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2412 { WM_SETFOCUS
, sent
}, /* in MDI client */
2414 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2415 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2416 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2417 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2418 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2419 { WM_SETFOCUS
, sent
}, /* in MDI client */
2421 { WM_DESTROY
, sent
},
2423 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2424 { WM_KILLFOCUS
, sent
},
2425 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2426 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2427 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2428 { WM_SETFOCUS
, sent
}, /* in MDI client */
2430 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2431 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2432 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2433 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2434 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2435 { WM_SETFOCUS
, sent
}, /* in MDI client */
2437 { WM_NCDESTROY
, sent
},
2440 /* CreateWindow for MDI child window, initially invisible */
2441 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
2442 { HCBT_CREATEWND
, hook
},
2443 { WM_NCCREATE
, sent
},
2444 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2445 { WM_CREATE
, sent
},
2446 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2447 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2449 /* Win2k sends wparam set to
2450 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2451 * while Win9x doesn't bother to set child window id according to
2452 * CLIENTCREATESTRUCT.idFirstChild
2454 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2457 /* DestroyWindow for MDI child window, initially invisible */
2458 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
2459 { HCBT_DESTROYWND
, hook
},
2460 /* Win2k sends wparam set to
2461 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2462 * while Win9x doesn't bother to set child window id according to
2463 * CLIENTCREATESTRUCT.idFirstChild
2465 { 0x0090, sent
|optional
},
2466 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2467 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2468 { WM_DESTROY
, sent
},
2469 { WM_NCDESTROY
, sent
},
2470 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
2471 { WM_PARENTNOTIFY
, sent
|wparam
|optional
, WM_DESTROY
}, /* MDI client */
2474 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
2475 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
2476 { HCBT_CREATEWND
, hook
},
2477 { WM_NCCREATE
, sent
},
2478 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2479 { WM_CREATE
, sent
},
2480 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2481 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2483 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2484 { WM_GETMINMAXINFO
, sent
},
2485 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2486 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2487 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2488 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2490 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2491 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2492 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2493 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2494 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2495 /* Win2k sends wparam set to
2496 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2497 * while Win9x doesn't bother to set child window id according to
2498 * CLIENTCREATESTRUCT.idFirstChild
2500 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2501 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2502 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2503 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2504 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2505 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2506 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2507 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2508 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
2510 /* Win9x: message sequence terminates here. */
2512 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
2513 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
2514 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2515 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2516 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2517 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2518 { HCBT_SETFOCUS
, hook
|optional
},
2519 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
2520 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2521 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2522 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2523 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
2524 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
2526 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2527 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2528 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2529 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2532 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
2533 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
2534 /* restore the 1st MDI child */
2535 { WM_SETREDRAW
, sent
|wparam
, 0 },
2536 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
2537 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
2538 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2539 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2540 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2541 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2543 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2544 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2545 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2546 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2547 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2548 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
2549 /* create the 2nd MDI child */
2550 { HCBT_CREATEWND
, hook
},
2551 { WM_NCCREATE
, sent
},
2552 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2553 { WM_CREATE
, sent
},
2554 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2555 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2557 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2558 { WM_GETMINMAXINFO
, sent
},
2559 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2560 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2561 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2562 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2563 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2565 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2566 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2567 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2568 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2569 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2570 /* Win2k sends wparam set to
2571 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2572 * while Win9x doesn't bother to set child window id according to
2573 * CLIENTCREATESTRUCT.idFirstChild
2575 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2576 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2577 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2578 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2579 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2580 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2581 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2582 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2584 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
2585 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
2587 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2589 /* Win9x: message sequence terminates here. */
2591 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2592 { HCBT_SETFOCUS
, hook
},
2593 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
2594 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
2595 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2596 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2597 { WM_SETFOCUS
, sent
}, /* in MDI client */
2598 { HCBT_SETFOCUS
, hook
},
2599 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2600 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2601 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2602 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2603 { WM_SETFOCUS
, sent
|defwinproc
},
2605 { WM_MDIACTIVATE
, sent
|defwinproc
},
2607 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2608 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2609 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2610 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2613 /* WM_MDICREATE MDI child window, initially visible and maximized */
2614 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
2615 { WM_MDICREATE
, sent
},
2616 { HCBT_CREATEWND
, hook
},
2617 { WM_NCCREATE
, sent
},
2618 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2619 { WM_CREATE
, sent
},
2620 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2621 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2623 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2624 { WM_GETMINMAXINFO
, sent
},
2625 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2626 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2627 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2628 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2631 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2632 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2633 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2634 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2635 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2637 /* Win2k sends wparam set to
2638 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2639 * while Win9x doesn't bother to set child window id according to
2640 * CLIENTCREATESTRUCT.idFirstChild
2642 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2643 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2644 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2646 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2648 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2649 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2650 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2652 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2653 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2655 /* Win9x: message sequence terminates here. */
2657 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2658 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2659 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2660 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2661 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
2662 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
2663 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2664 { HCBT_SETFOCUS
, hook
|optional
},
2665 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2666 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2667 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2668 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2669 { WM_SETFOCUS
, sent
|defwinproc
},
2671 { WM_MDIACTIVATE
, sent
|defwinproc
},
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 },
2680 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2681 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2682 { 0x0093, sent
|defwinproc
|optional
},
2683 { 0x0093, sent
|defwinproc
|optional
},
2684 { 0x0093, sent
|defwinproc
|optional
},
2685 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2686 { WM_MOVE
, sent
|defwinproc
},
2687 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2690 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2691 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2692 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2693 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2696 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2697 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2698 { 0x0093, sent
|optional
},
2699 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2700 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2702 { 0x0093, sent
|optional
},
2703 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2704 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
2705 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
2706 { 0x0093, sent
|defwinproc
|optional
},
2707 { 0x0093, sent
|defwinproc
|optional
},
2708 { 0x0093, sent
|defwinproc
|optional
},
2709 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2710 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
2714 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
2715 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
2716 { HCBT_CREATEWND
, hook
},
2717 { WM_GETMINMAXINFO
, sent
},
2718 { WM_NCCREATE
, sent
},
2719 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2720 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
2721 { WM_CREATE
, sent
},
2722 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2723 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2724 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
2725 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
2726 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
2728 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2729 { WM_GETMINMAXINFO
, sent
},
2730 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2731 { WM_GETMINMAXINFO
, sent
|defwinproc
},
2732 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2733 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
2734 { WM_MOVE
, sent
|defwinproc
},
2735 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2737 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2738 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2739 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2740 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2741 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
2742 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2743 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2744 /* Win2k sends wparam set to
2745 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2746 * while Win9x doesn't bother to set child window id according to
2747 * CLIENTCREATESTRUCT.idFirstChild
2749 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2752 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
2753 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
2754 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
2755 { HCBT_SYSCOMMAND
, hook
},
2756 { WM_CLOSE
, sent
|defwinproc
},
2757 { WM_MDIDESTROY
, sent
}, /* in MDI client */
2759 /* bring the 1st MDI child to top */
2760 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
2761 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
2763 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2765 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
2766 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
2767 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
2769 /* maximize the 1st MDI child */
2770 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2771 { WM_GETMINMAXINFO
, sent
|defwinproc
},
2772 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
2773 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
2774 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
2775 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2776 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2778 /* restore the 2nd MDI child */
2779 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
2780 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
2781 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
2782 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
2784 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2786 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2787 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2789 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2791 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
2793 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2794 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2795 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2796 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2797 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2799 /* bring the 1st MDI child to top */
2800 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2801 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2802 { HCBT_SETFOCUS
, hook
},
2803 { WM_KILLFOCUS
, sent
|defwinproc
},
2804 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
2805 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2806 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2807 { WM_SETFOCUS
, sent
}, /* in MDI client */
2808 { HCBT_SETFOCUS
, hook
},
2809 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2810 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2811 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2812 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2813 { WM_SETFOCUS
, sent
|defwinproc
},
2814 { WM_MDIACTIVATE
, sent
|defwinproc
},
2815 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2817 /* apparently ShowWindow(SW_SHOW) on an MDI client */
2818 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2819 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2820 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2821 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2822 { WM_MDIREFRESHMENU
, sent
},
2824 { HCBT_DESTROYWND
, hook
},
2825 /* Win2k sends wparam set to
2826 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2827 * while Win9x doesn't bother to set child window id according to
2828 * CLIENTCREATESTRUCT.idFirstChild
2830 { 0x0090, sent
|defwinproc
|optional
},
2831 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2832 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
2833 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2834 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2835 { WM_ERASEBKGND
, sent
|parent
|optional
},
2836 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2838 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2839 { WM_DESTROY
, sent
|defwinproc
},
2840 { WM_NCDESTROY
, sent
|defwinproc
},
2843 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
2844 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
2845 { WM_MDIDESTROY
, sent
}, /* in MDI client */
2846 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2847 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2848 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2849 { WM_ERASEBKGND
, sent
|parent
|optional
},
2850 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2852 { HCBT_SETFOCUS
, hook
},
2853 { WM_KILLFOCUS
, sent
},
2854 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2855 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2856 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2857 { WM_SETFOCUS
, sent
}, /* in MDI client */
2858 { HCBT_SETFOCUS
, hook
},
2859 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2860 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2861 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2862 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2863 { WM_SETFOCUS
, sent
},
2866 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2867 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2868 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2869 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2872 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2873 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2874 { 0x0093, sent
|defwinproc
|optional
},
2875 { 0x0093, sent
|defwinproc
|optional
},
2876 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2877 { WM_MOVE
, sent
|defwinproc
},
2878 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2881 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2882 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2883 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2884 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2887 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2888 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2889 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
2890 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2893 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2894 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
2895 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2896 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2899 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2900 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
2901 { 0x0093, sent
|defwinproc
|optional
},
2902 { 0x0093, sent
|defwinproc
|optional
},
2903 { 0x0093, sent
|defwinproc
|optional
},
2904 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2905 { WM_MOVE
, sent
|defwinproc
},
2906 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2909 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2910 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2911 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2912 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2915 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
2916 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
2917 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
2918 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2919 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2920 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
2922 { 0x0093, sent
|defwinproc
|optional
},
2923 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
2924 { 0x0093, sent
|defwinproc
|optional
},
2925 { 0x0093, sent
|defwinproc
|optional
},
2926 { 0x0093, sent
|defwinproc
|optional
},
2927 { 0x0093, sent
|optional
},
2929 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2930 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2931 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
2932 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2933 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
2936 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2937 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2938 { 0x0093, sent
|defwinproc
|optional
},
2939 { 0x0093, sent
|defwinproc
|optional
},
2940 { 0x0093, sent
|defwinproc
|optional
},
2941 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2942 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2943 { 0x0093, sent
|optional
},
2945 { WM_NCACTIVATE
, sent
|wparam
, 0 },
2946 { WM_MDIACTIVATE
, sent
},
2948 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
2949 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
2950 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2952 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2954 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2955 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2956 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2959 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2960 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
2961 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2962 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2965 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2966 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2967 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2968 { WM_MOVE
, sent
|defwinproc
},
2969 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2972 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
2973 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2974 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
2975 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2976 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2977 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2978 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
2979 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2980 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
2982 { HCBT_SETFOCUS
, hook
},
2983 { WM_KILLFOCUS
, sent
},
2984 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2985 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2986 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2987 { WM_SETFOCUS
, sent
}, /* in MDI client */
2989 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
2991 { HCBT_DESTROYWND
, hook
},
2992 /* Win2k sends wparam set to
2993 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2994 * while Win9x doesn't bother to set child window id according to
2995 * CLIENTCREATESTRUCT.idFirstChild
2997 { 0x0090, sent
|optional
},
2998 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3000 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3001 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3002 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3003 { WM_ERASEBKGND
, sent
|parent
|optional
},
3004 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3006 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3007 { WM_DESTROY
, sent
},
3008 { WM_NCDESTROY
, sent
},
3011 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3012 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3013 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3014 { WM_GETMINMAXINFO
, sent
},
3015 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3016 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3017 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3018 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3020 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3021 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3022 { HCBT_SETFOCUS
, hook
|optional
},
3023 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3024 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3025 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3026 { HCBT_SETFOCUS
, hook
|optional
},
3027 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3028 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3029 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3030 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3031 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3032 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3033 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3034 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3036 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3037 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3038 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3039 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3040 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3043 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3044 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3045 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3046 { WM_GETMINMAXINFO
, sent
},
3047 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
3048 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3049 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3050 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3051 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3053 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3054 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3055 { HCBT_SETFOCUS
, hook
|optional
},
3056 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3057 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3058 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3059 { HCBT_SETFOCUS
, hook
|optional
},
3060 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3061 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3062 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3063 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3064 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3065 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3066 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3067 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3070 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3071 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3072 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3073 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3074 { WM_GETMINMAXINFO
, sent
},
3075 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3076 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3077 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3078 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3079 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3080 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3081 { WM_MOVE
, sent
|defwinproc
},
3082 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3084 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3085 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3086 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3087 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3088 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3089 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3091 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3092 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3093 { 0x0093, sent
|defwinproc
|optional
},
3094 { 0x0094, sent
|defwinproc
|optional
},
3095 { 0x0094, sent
|defwinproc
|optional
},
3096 { 0x0094, sent
|defwinproc
|optional
},
3097 { 0x0094, sent
|defwinproc
|optional
},
3098 { 0x0093, sent
|defwinproc
|optional
},
3099 { 0x0093, sent
|defwinproc
|optional
},
3100 { 0x0091, sent
|defwinproc
|optional
},
3101 { 0x0092, sent
|defwinproc
|optional
},
3102 { 0x0092, sent
|defwinproc
|optional
},
3103 { 0x0092, sent
|defwinproc
|optional
},
3104 { 0x0092, sent
|defwinproc
|optional
},
3105 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3106 { WM_MOVE
, sent
|defwinproc
},
3107 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3108 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3110 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3111 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3112 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3113 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3115 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3116 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3117 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3118 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3119 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3120 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3121 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3122 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3123 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3124 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3126 { 0x0093, sent
|optional
},
3127 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3128 { 0x0093, sent
|defwinproc
|optional
},
3129 { 0x0093, sent
|defwinproc
|optional
},
3130 { 0x0093, sent
|defwinproc
|optional
},
3131 { 0x0091, sent
|defwinproc
|optional
},
3132 { 0x0092, sent
|defwinproc
|optional
},
3133 { 0x0092, sent
|defwinproc
|optional
},
3134 { 0x0092, sent
|defwinproc
|optional
},
3135 { 0x0092, sent
|defwinproc
|optional
},
3136 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3137 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3138 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3141 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3142 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3143 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3144 { WM_GETMINMAXINFO
, sent
},
3145 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3146 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3147 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3148 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3149 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3151 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3152 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3153 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3154 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3155 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3158 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3159 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3160 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3161 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3162 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3163 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3164 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3165 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3167 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3168 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3169 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3170 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3171 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3174 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3175 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3176 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3177 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3178 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3179 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3180 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3181 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3182 { WM_MOVE
, sent
|defwinproc
},
3183 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3184 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3185 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3186 { HCBT_SETFOCUS
, hook
},
3187 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3188 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3189 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3190 { WM_SETFOCUS
, sent
},
3193 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3194 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
3195 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
3196 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3197 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3198 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3199 { WM_MOVE
, sent
|defwinproc
},
3200 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
3201 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
3202 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3203 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3204 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3205 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
}, /* MDI client */
3208 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3209 static const struct message WmRestoreMDIchildInisibleSeq
[] = {
3210 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3211 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3212 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3213 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3214 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3215 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3216 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3218 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3219 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3220 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3221 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3222 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3226 static HWND mdi_client
;
3227 static WNDPROC old_mdi_client_proc
;
3229 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3231 struct recvd_message msg
;
3233 /* do not log painting messages */
3234 if (message
!= WM_PAINT
&&
3235 message
!= WM_NCPAINT
&&
3236 message
!= WM_SYNCPAINT
&&
3237 message
!= WM_ERASEBKGND
&&
3238 message
!= WM_NCHITTEST
&&
3239 message
!= WM_GETTEXT
&&
3240 message
!= WM_MDIGETACTIVE
&&
3241 !ignore_message( message
))
3244 msg
.message
= message
;
3245 msg
.flags
= sent
|wparam
|lparam
;
3246 msg
.wParam
= wParam
;
3247 msg
.lParam
= lParam
;
3248 msg
.descr
= "mdi client";
3252 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
3255 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3257 static LONG defwndproc_counter
= 0;
3259 struct recvd_message msg
;
3261 /* do not log painting messages */
3262 if (message
!= WM_PAINT
&&
3263 message
!= WM_NCPAINT
&&
3264 message
!= WM_SYNCPAINT
&&
3265 message
!= WM_ERASEBKGND
&&
3266 message
!= WM_NCHITTEST
&&
3267 message
!= WM_GETTEXT
&&
3268 !ignore_message( message
))
3272 case WM_MDIACTIVATE
:
3274 HWND active
, client
= GetParent(hwnd
);
3276 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
3278 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
3279 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
3281 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
3287 msg
.message
= message
;
3288 msg
.flags
= sent
|wparam
|lparam
;
3289 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3290 msg
.wParam
= wParam
;
3291 msg
.lParam
= lParam
;
3292 msg
.descr
= "mdi child";
3296 defwndproc_counter
++;
3297 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
3298 defwndproc_counter
--;
3303 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3305 static LONG defwndproc_counter
= 0;
3307 struct recvd_message msg
;
3309 /* do not log painting messages */
3310 if (message
!= WM_PAINT
&&
3311 message
!= WM_NCPAINT
&&
3312 message
!= WM_SYNCPAINT
&&
3313 message
!= WM_ERASEBKGND
&&
3314 message
!= WM_NCHITTEST
&&
3315 message
!= WM_GETTEXT
&&
3316 !ignore_message( message
))
3319 msg
.message
= message
;
3320 msg
.flags
= sent
|wparam
|lparam
;
3321 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3322 msg
.wParam
= wParam
;
3323 msg
.lParam
= lParam
;
3324 msg
.descr
= "mdi frame";
3328 defwndproc_counter
++;
3329 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
3330 defwndproc_counter
--;
3335 static BOOL
mdi_RegisterWindowClasses(void)
3340 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
3343 cls
.hInstance
= GetModuleHandleA(0);
3345 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
3346 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
3347 cls
.lpszMenuName
= NULL
;
3348 cls
.lpszClassName
= "MDI_frame_class";
3349 if (!RegisterClassA(&cls
)) return FALSE
;
3351 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
3352 cls
.lpszClassName
= "MDI_child_class";
3353 if (!RegisterClassA(&cls
)) return FALSE
;
3355 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
3356 old_mdi_client_proc
= cls
.lpfnWndProc
;
3357 cls
.hInstance
= GetModuleHandleA(0);
3358 cls
.lpfnWndProc
= mdi_client_hook_proc
;
3359 cls
.lpszClassName
= "MDI_client_class";
3360 if (!RegisterClassA(&cls
)) assert(0);
3365 static void test_mdi_messages(void)
3367 MDICREATESTRUCTA mdi_cs
;
3368 CLIENTCREATESTRUCT client_cs
;
3369 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
3372 HMENU hMenu
= CreateMenu();
3374 if (!mdi_RegisterWindowClasses()) assert(0);
3378 trace("creating MDI frame window\n");
3379 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
3380 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
3381 WS_MAXIMIZEBOX
| WS_VISIBLE
,
3382 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
3383 GetDesktopWindow(), hMenu
,
3384 GetModuleHandleA(0), NULL
);
3386 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
3388 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3389 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
3391 trace("creating MDI client window\n");
3392 GetClientRect(mdi_frame
, &rc
);
3393 client_cs
.hWindowMenu
= 0;
3394 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
3395 mdi_client
= CreateWindowExA(0, "MDI_client_class",
3397 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
3398 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
3399 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
3401 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
3403 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3404 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
3406 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3407 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3408 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3413 trace("creating invisible MDI child window\n");
3414 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3416 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3417 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3421 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
3422 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
3424 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3425 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3427 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3428 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3430 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3431 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3432 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3434 ShowWindow(mdi_child
, SW_HIDE
);
3435 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
3438 ShowWindow(mdi_child
, SW_SHOW
);
3439 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
3441 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3442 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3444 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3445 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3447 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3448 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3449 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3451 DestroyWindow(mdi_child
);
3454 trace("creating visible MDI child window\n");
3455 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3456 WS_CHILD
| WS_VISIBLE
,
3457 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3458 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3460 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
3462 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3463 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3465 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3466 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3468 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3469 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3470 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3473 DestroyWindow(mdi_child
);
3474 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3476 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3477 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3479 /* Win2k: MDI client still returns a just destroyed child as active
3480 * Win9x: MDI client returns 0
3482 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3483 ok(active_child
== mdi_child
|| /* win2k */
3484 !active_child
, /* win9x */
3485 "wrong active MDI child %p\n", active_child
);
3486 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3490 trace("creating invisible MDI child window\n");
3491 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3493 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3494 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3496 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
3498 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
3499 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
3501 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3502 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3504 /* Win2k: MDI client still returns a just destroyed child as active
3505 * Win9x: MDI client returns mdi_child2
3507 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3508 ok(active_child
== mdi_child
|| /* win2k */
3509 active_child
== mdi_child2
, /* win9x */
3510 "wrong active MDI child %p\n", active_child
);
3511 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3514 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3515 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
3517 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3518 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3520 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3521 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3522 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3525 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3526 ok(GetFocus() == mdi_child2
|| /* win2k */
3527 GetFocus() == 0, /* win9x */
3528 "wrong focus window %p\n", GetFocus());
3533 ShowWindow(mdi_child2
, SW_HIDE
);
3534 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3536 ShowWindow(mdi_child2
, SW_RESTORE
);
3537 ok_sequence(WmRestoreMDIchildInisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
3540 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3541 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3543 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3544 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3545 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3551 ShowWindow(mdi_child2
, SW_HIDE
);
3552 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3554 ShowWindow(mdi_child2
, SW_SHOW
);
3555 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
3557 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3558 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3560 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3561 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
3563 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3564 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3566 ShowWindow(mdi_child2
, SW_RESTORE
);
3567 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
3569 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3570 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3572 ShowWindow(mdi_child2
, SW_MINIMIZE
);
3573 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", TRUE
);
3575 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3576 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3578 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3579 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3580 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3583 ShowWindow(mdi_child2
, SW_RESTORE
);
3584 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
3586 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3587 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
3589 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3590 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3591 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3597 ShowWindow(mdi_child2
, SW_HIDE
);
3598 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3600 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3601 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3603 DestroyWindow(mdi_child2
);
3604 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
3606 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3607 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3609 /* test for maximized MDI children */
3610 trace("creating maximized visible MDI child window 1\n");
3611 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3612 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3613 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3614 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3616 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
3617 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
3619 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3620 ok(GetFocus() == mdi_child
|| /* win2k */
3621 GetFocus() == 0, /* win9x */
3622 "wrong focus window %p\n", GetFocus());
3624 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3625 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3626 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3629 trace("creating maximized visible MDI child window 2\n");
3630 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3631 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3632 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3633 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3635 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
3636 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
3637 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
3639 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3640 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
3642 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3643 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3644 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3647 trace("destroying maximized visible MDI child window 2\n");
3648 DestroyWindow(mdi_child2
);
3649 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3651 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
3653 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3654 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3656 /* Win2k: MDI client still returns a just destroyed child as active
3657 * Win9x: MDI client returns 0
3659 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3660 ok(active_child
== mdi_child2
|| /* win2k */
3661 !active_child
, /* win9x */
3662 "wrong active MDI child %p\n", active_child
);
3665 ShowWindow(mdi_child
, SW_MAXIMIZE
);
3666 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
3669 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3670 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3672 trace("re-creating maximized visible MDI child window 2\n");
3673 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3674 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3675 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3676 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3678 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
3679 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
3680 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
3682 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3683 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
3685 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3686 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3687 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3690 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
3691 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
3692 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
3694 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
3695 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3696 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3698 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3699 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3700 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3703 DestroyWindow(mdi_child
);
3704 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3706 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3707 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3709 /* Win2k: MDI client still returns a just destroyed child as active
3710 * Win9x: MDI client returns 0
3712 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3713 ok(active_child
== mdi_child
|| /* win2k */
3714 !active_child
, /* win9x */
3715 "wrong active MDI child %p\n", active_child
);
3718 trace("creating maximized invisible MDI child window\n");
3719 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3720 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
3721 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3722 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3724 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
3725 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
3726 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
3727 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
3729 /* Win2k: MDI client still returns a just destroyed child as active
3730 * Win9x: MDI client returns 0
3732 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3733 ok(active_child
== mdi_child
|| /* win2k */
3734 !active_child
|| active_child
== mdi_child2
, /* win9x */
3735 "wrong active MDI child %p\n", active_child
);
3738 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
3739 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3740 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
3741 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
3742 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3743 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3745 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3746 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3747 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3750 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
3753 /* end of test for maximized MDI children */
3756 trace("creating maximized visible MDI child window 1(Switch test)\n");
3757 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3758 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3759 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3760 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3762 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
3763 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
3765 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
3766 ok(GetFocus() == mdi_child
|| /* win2k */
3767 GetFocus() == 0, /* win9x */
3768 "wrong focus window %p(Switch test)\n", GetFocus());
3770 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3771 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
3772 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
3775 trace("creating maximized visible MDI child window 2(Switch test)\n");
3776 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3777 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3778 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3779 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3781 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
3783 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
3784 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
3786 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
3787 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
3789 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3790 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
3791 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
3794 trace("Switch child window.\n");
3795 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
3796 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
3797 trace("end of test for switch maximized MDI children\n");
3800 /* Prepare for switching test of not maximized MDI children */
3801 ShowWindow( mdi_child
, SW_NORMAL
);
3802 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
3803 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
3804 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
3805 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
3808 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
3809 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
3810 trace("end of test for switch not maximized MDI children\n");
3813 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
3816 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
3821 /* end of tests for switch maximized/not maximized MDI children */
3823 mdi_cs
.szClass
= "MDI_child_Class";
3824 mdi_cs
.szTitle
= "MDI child";
3825 mdi_cs
.hOwner
= GetModuleHandleA(0);
3828 mdi_cs
.cx
= CW_USEDEFAULT
;
3829 mdi_cs
.cy
= CW_USEDEFAULT
;
3830 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
3832 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
3833 ok(mdi_child
!= 0, "MDI child creation failed\n");
3834 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
3836 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
3838 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3839 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3841 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
3842 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3843 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3845 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3846 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3847 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3850 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
3851 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
3853 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
3854 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3855 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3860 DestroyWindow(mdi_client
);
3861 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
3863 /* test maximization of MDI child with invisible parent */
3864 client_cs
.hWindowMenu
= 0;
3865 mdi_client
= CreateWindowA("MDI_client_class",
3867 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
3869 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
3870 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
3872 ShowWindow(mdi_client
, SW_HIDE
);
3873 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
3875 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3876 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
3878 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3879 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
3881 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
3882 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
3883 zoomed
= IsZoomed(mdi_child
);
3884 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3886 ShowWindow(mdi_client
, SW_SHOW
);
3887 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
3889 DestroyWindow(mdi_child
);
3890 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
3892 /* end of test for maximization of MDI child with invisible parent */
3894 DestroyWindow(mdi_client
);
3895 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
3897 DestroyWindow(mdi_frame
);
3898 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
3900 /************************* End of MDI test **********************************/
3902 static void test_WM_SETREDRAW(HWND hwnd
)
3904 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
3909 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3910 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
3912 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
3913 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
3916 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3917 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
3919 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
3920 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
3922 /* restore original WS_VISIBLE state */
3923 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
3929 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3931 struct recvd_message msg
;
3933 if (ignore_message( message
)) return 0;
3939 case WM_NCMOUSEMOVE
:
3940 case WM_NCMOUSELEAVE
:
3948 msg
.message
= message
;
3949 msg
.flags
= sent
|wparam
|lparam
;
3950 msg
.wParam
= wParam
;
3951 msg
.lParam
= lParam
;
3952 msg
.descr
= "dialog";
3955 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
3956 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
3960 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
3962 DWORD style
, exstyle
;
3966 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
3967 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
3968 /* do not be confused by WS_DLGFRAME set */
3969 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
3971 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
3972 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
3974 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
3975 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
3976 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
3977 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
3979 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
3981 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
3982 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
3983 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
3985 /* a subsequent call should do nothing */
3986 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
3987 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
3988 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
3992 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
3993 ok( ret
, "GetScrollRange(%d) error %d\n", ctl
, GetLastError());
3994 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
3995 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
3996 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
3999 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4001 DWORD style
, exstyle
;
4005 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4006 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4007 /* do not be confused by WS_DLGFRAME set */
4008 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4010 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4011 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4013 si
.cbSize
= sizeof(si
);
4014 si
.fMask
= SIF_RANGE
;
4017 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4018 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4019 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4021 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4023 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4024 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4025 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4027 /* a subsequent call should do nothing */
4028 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4029 if (style
& WS_HSCROLL
)
4030 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4031 else if (style
& WS_VSCROLL
)
4032 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4034 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4036 si
.fMask
= SIF_PAGE
;
4038 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4039 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4043 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4044 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4046 si
.fMask
= SIF_RANGE
;
4047 si
.nMin
= 0xdeadbeef;
4048 si
.nMax
= 0xdeadbeef;
4049 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4050 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4051 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4052 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4053 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4056 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4057 static void test_scroll_messages(HWND hwnd
)
4068 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4069 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4070 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4071 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4072 /* values of min and max are undefined */
4075 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4076 ok( ret
, "SetScrollRange error %d\n", GetLastError());
4077 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4078 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4083 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4084 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4085 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4086 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4087 /* values of min and max are undefined */
4090 si
.cbSize
= sizeof(si
);
4091 si
.fMask
= SIF_RANGE
;
4094 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4095 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4096 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4099 si
.fMask
= SIF_PAGE
;
4101 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4102 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4103 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4108 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4109 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4110 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4113 si
.fMask
= SIF_RANGE
;
4114 si
.nMin
= 0xdeadbeef;
4115 si
.nMax
= 0xdeadbeef;
4116 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
4117 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4118 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
4119 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4120 /* values of min and max are undefined */
4123 /* set WS_HSCROLL */
4124 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4125 /* clear WS_HSCROLL */
4126 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4128 /* set WS_HSCROLL */
4129 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4130 /* clear WS_HSCROLL */
4131 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4133 /* set WS_VSCROLL */
4134 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4135 /* clear WS_VSCROLL */
4136 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4138 /* set WS_VSCROLL */
4139 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4140 /* clear WS_VSCROLL */
4141 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4144 static void test_showwindow(void)
4149 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4150 100, 100, 200, 200, 0, 0, 0, NULL
);
4151 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4152 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4153 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
4154 ok (hchild
!= 0, "Failed to create child\n");
4157 /* ShowWindow( SW_SHOWNA) for invisible top level window */
4158 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
4159 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4160 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
4162 /* ShowWindow( SW_SHOWNA) for now visible top level window */
4163 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
4164 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4165 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
4166 /* back to invisible */
4167 ShowWindow(hchild
, SW_HIDE
);
4168 ShowWindow(hwnd
, SW_HIDE
);
4170 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
4171 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
4172 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4173 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
4174 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
4175 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
4177 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
4178 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4179 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
4180 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
4181 ShowWindow( hwnd
, SW_SHOW
);
4183 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
4184 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4185 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
4187 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
4188 ShowWindow( hchild
, SW_HIDE
);
4190 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
4191 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4192 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
4195 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
4196 DestroyWindow(hchild
);
4197 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
4199 DestroyWindow(hwnd
);
4204 * 1. Create invisible maximized popup window.
4205 * 2. Move and resize it.
4206 * 3. Show it maximized.
4208 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4209 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4210 100, 100, 200, 200, 0, 0, 0, NULL
);
4211 ok (hwnd
!= 0, "Failed to create popup window\n");
4212 ok(IsZoomed(hwnd
), "window should be maximized\n");
4213 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4215 GetWindowRect(hwnd
, &rc
);
4216 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4217 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4218 "Invalid maximized size before ShowWindow (%d,%d)-(%d,%d)\n",
4219 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4220 /* Reset window's size & position */
4221 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4222 ok(IsZoomed(hwnd
), "window should be maximized\n");
4225 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4226 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4227 ok(IsZoomed(hwnd
), "window should be maximized\n");
4228 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
4230 GetWindowRect(hwnd
, &rc
);
4231 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4232 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4233 "Invalid maximized size after ShowWindow (%d,%d)-(%d,%d)\n",
4234 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4235 DestroyWindow(hwnd
);
4239 * 1. Create invisible maximized popup window.
4240 * 2. Show it maximized.
4242 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4243 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4244 100, 100, 200, 200, 0, 0, 0, NULL
);
4245 ok (hwnd
!= 0, "Failed to create popup window\n");
4246 ok(IsZoomed(hwnd
), "window should be maximized\n");
4247 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4249 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4250 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4251 ok(IsZoomed(hwnd
), "window should be maximized\n");
4252 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
4253 DestroyWindow(hwnd
);
4257 * 1. Create visible maximized popup window.
4259 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
4260 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
4261 100, 100, 200, 200, 0, 0, 0, NULL
);
4262 ok (hwnd
!= 0, "Failed to create popup window\n");
4263 ok(IsZoomed(hwnd
), "window should be maximized\n");
4264 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4265 DestroyWindow(hwnd
);
4269 * 1. Create visible popup window.
4272 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
4273 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
4274 100, 100, 200, 200, 0, 0, 0, NULL
);
4275 ok (hwnd
!= 0, "Failed to create popup window\n");
4276 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
4277 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
4279 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
4280 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4281 ok(IsZoomed(hwnd
), "window should be maximized\n");
4282 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
4283 DestroyWindow(hwnd
);
4287 static void test_sys_menu(void)
4293 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4294 100, 100, 200, 200, 0, 0, 0, NULL
);
4295 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4299 /* test existing window without CS_NOCLOSE style */
4300 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4301 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4303 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4304 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4305 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4307 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
4308 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4310 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4311 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4312 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
4314 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
4315 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4317 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4318 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4319 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4321 /* test whether removing WS_SYSMENU destroys a system menu */
4322 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
4323 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
4325 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4326 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4328 DestroyWindow(hwnd
);
4330 /* test new window with CS_NOCLOSE style */
4331 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4332 100, 100, 200, 200, 0, 0, 0, NULL
);
4333 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4335 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4336 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4338 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4339 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4341 DestroyWindow(hwnd
);
4343 /* test new window without WS_SYSMENU style */
4344 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
4345 100, 100, 200, 200, 0, 0, 0, NULL
);
4346 ok(hwnd
!= 0, "Failed to create overlapped window\n");
4348 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4349 ok(!hmenu
, "GetSystemMenu error %d\n", GetLastError());
4351 DestroyWindow(hwnd
);
4354 /* For shown WS_OVERLAPPEDWINDOW */
4355 static const struct message WmSetIcon_1
[] = {
4356 { WM_SETICON
, sent
},
4357 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
4358 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4359 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
4363 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
4364 static const struct message WmSetIcon_2
[] = {
4365 { WM_SETICON
, sent
},
4369 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
4370 static const struct message WmInitEndSession
[] = {
4372 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4376 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
4377 static const struct message WmInitEndSession_2
[] = {
4379 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4383 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
4384 static const struct message WmInitEndSession_3
[] = {
4386 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4390 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
4391 static const struct message WmInitEndSession_4
[] = {
4393 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4397 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
4398 static const struct message WmInitEndSession_5
[] = {
4400 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
4404 static const struct message WmOptionalPaint
[] = {
4405 { WM_PAINT
, sent
|optional
},
4406 { WM_NCPAINT
, sent
|beginpaint
|optional
},
4407 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
4408 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
4412 static const struct message WmZOrder
[] = {
4413 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
4414 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
4415 { HCBT_ACTIVATE
, hook
},
4416 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
4417 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
4418 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
4419 { WM_GETTEXT
, sent
|optional
},
4420 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
4421 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
4422 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
4423 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4424 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4425 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
4426 { HCBT_SETFOCUS
, hook
},
4427 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
4428 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
4429 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
4430 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
4431 { WM_GETTEXT
, sent
|optional
},
4432 { WM_NCCALCSIZE
, sent
|optional
},
4436 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
4441 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
4446 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4447 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4449 PostMessageA(hwnd
, WM_USER
, 0, 0);
4451 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4452 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4454 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4455 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4457 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4458 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4460 PostMessageA(hwnd
, WM_USER
, 0, 0);
4462 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4463 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4465 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
4466 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4468 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
4469 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4470 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4472 PostMessageA(hwnd
, WM_USER
, 0, 0);
4474 /* new incoming message causes it to become signaled again */
4475 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4476 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4478 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4479 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4480 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4481 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4483 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
4484 PostMessageA( hwnd
, WM_USER
, 0, 0 );
4485 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
4486 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4488 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_INPUTAVAILABLE
);
4489 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4491 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4492 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4494 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
4495 ret
= QueueUserAPC( apc_test_proc
, GetCurrentThread(), 0 );
4496 ok(ret
, "QueueUserAPC failed %u\n", GetLastError());
4498 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, 0 );
4499 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4501 /* but even with MWMO_ALERTABLE window events are preferred */
4502 PostMessageA( hwnd
, WM_USER
, 0, 0 );
4504 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
4505 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4507 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4508 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4510 /* the APC call is still queued */
4511 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
4512 ok(ret
== WAIT_IO_COMPLETION
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4515 static DWORD CALLBACK
show_window_thread(LPVOID arg
)
4519 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
4520 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
4525 /* test if we receive the right sequence of messages */
4526 static void test_messages(void)
4530 HWND hwnd
, hparent
, hchild
;
4531 HWND hchild2
, hbutton
;
4540 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4541 100, 100, 200, 200, 0, 0, 0, NULL
);
4542 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4543 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
4545 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
4546 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
4547 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
4549 /* test WM_SETREDRAW on a not visible top level window */
4550 test_WM_SETREDRAW(hwnd
);
4552 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4554 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
4555 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
4557 ok(GetActiveWindow() == hwnd
, "window should be active\n");
4558 ok(GetFocus() == hwnd
, "window should have input focus\n");
4559 ShowWindow(hwnd
, SW_HIDE
);
4561 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
4563 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
4564 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
4566 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
4568 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
4569 hthread
= CreateThread(NULL
, 0, show_window_thread
, hwnd
, 0, &tid
);
4570 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
4571 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
4572 CloseHandle(hthread
);
4574 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
4576 ShowWindow(hwnd
, SW_SHOW
);
4578 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
4580 ShowWindow(hwnd
, SW_HIDE
);
4582 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
4584 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4586 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
4589 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
4591 ShowWindow(hwnd
, SW_RESTORE
);
4593 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
4597 ShowWindow(hwnd
, SW_MINIMIZE
);
4599 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE
);
4602 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
4604 ShowWindow(hwnd
, SW_RESTORE
);
4606 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
4610 ShowWindow(hwnd
, SW_SHOW
);
4612 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
4614 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4615 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
4616 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
4617 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
4619 /* test WM_SETREDRAW on a visible top level window */
4620 ShowWindow(hwnd
, SW_SHOW
);
4622 test_WM_SETREDRAW(hwnd
);
4624 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
4625 test_scroll_messages(hwnd
);
4627 /* test resizing and moving */
4628 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
4629 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
4632 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
4633 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
4636 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
4637 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
4641 /* popups don't get WM_GETMINMAXINFO */
4642 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
4643 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
4645 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
4646 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
4648 DestroyWindow(hwnd
);
4649 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
4651 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
4652 100, 100, 200, 200, 0, 0, 0, NULL
);
4653 ok (hparent
!= 0, "Failed to create parent window\n");
4656 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
4657 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4658 ok (hchild
!= 0, "Failed to create child window\n");
4659 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
4660 DestroyWindow(hchild
);
4663 /* visible child window with a caption */
4664 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
4665 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
4666 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4667 ok (hchild
!= 0, "Failed to create child window\n");
4668 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
4670 trace("testing scroll APIs on a visible child window %p\n", hchild
);
4671 test_scroll_messages(hchild
);
4673 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4674 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
4676 DestroyWindow(hchild
);
4679 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4680 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4681 ok (hchild
!= 0, "Failed to create child window\n");
4682 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
4684 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
4685 100, 100, 50, 50, hparent
, 0, 0, NULL
);
4686 ok (hchild2
!= 0, "Failed to create child2 window\n");
4689 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
4690 0, 100, 50, 50, hchild
, 0, 0, NULL
);
4691 ok (hbutton
!= 0, "Failed to create button window\n");
4693 /* test WM_SETREDRAW on a not visible child window */
4694 test_WM_SETREDRAW(hchild
);
4696 ShowWindow(hchild
, SW_SHOW
);
4697 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
4699 /* check parent messages too */
4700 log_all_parent_messages
++;
4701 ShowWindow(hchild
, SW_HIDE
);
4702 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
4703 log_all_parent_messages
--;
4705 ShowWindow(hchild
, SW_SHOW
);
4706 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
4708 ShowWindow(hchild
, SW_HIDE
);
4709 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
4711 ShowWindow(hchild
, SW_SHOW
);
4712 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
4714 /* test WM_SETREDRAW on a visible child window */
4715 test_WM_SETREDRAW(hchild
);
4717 log_all_parent_messages
++;
4718 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
4719 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
4720 log_all_parent_messages
--;
4722 ShowWindow(hchild
, SW_HIDE
);
4724 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4725 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
4727 ShowWindow(hchild
, SW_HIDE
);
4729 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
4730 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
4732 /* DestroyWindow sequence below expects that a child has focus */
4736 DestroyWindow(hchild
);
4737 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
4738 DestroyWindow(hchild2
);
4739 DestroyWindow(hbutton
);
4742 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
4743 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4744 ok (hchild
!= 0, "Failed to create child popup window\n");
4745 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
4746 DestroyWindow(hchild
);
4748 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
4750 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
4751 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4752 ok (hchild
!= 0, "Failed to create popup window\n");
4753 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
4754 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4755 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
4757 ShowWindow(hchild
, SW_SHOW
);
4758 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
4760 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
4761 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
4763 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
4764 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
4765 DestroyWindow(hchild
);
4767 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
4768 * changes nothing in message sequences.
4771 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
4772 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4773 ok (hchild
!= 0, "Failed to create popup window\n");
4774 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
4775 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4776 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
4778 ShowWindow(hchild
, SW_SHOW
);
4779 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
4781 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
4782 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
4783 DestroyWindow(hchild
);
4786 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
4787 0, 0, 100, 100, hparent
, 0, 0, NULL
);
4788 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
4789 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
4792 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
4793 test_scroll_messages(hwnd
);
4799 SendMessageA(hwnd
, WM_NULL
, 0, 0);
4802 after_end_dialog
= TRUE
;
4803 EndDialog( hwnd
, 0 );
4804 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
4806 DestroyWindow(hwnd
);
4807 after_end_dialog
= FALSE
;
4808 test_def_id
= FALSE
;
4810 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
4811 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
4813 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
4814 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
4815 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
4817 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
4818 ShowWindow(hwnd
, SW_SHOW
);
4819 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
4823 ret
= DrawMenuBar(hwnd
);
4824 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
4826 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
4827 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
4829 DestroyWindow(hwnd
);
4831 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_CHILD
|WS_VISIBLE
,
4832 0, 0, 100, 100, hparent
, 0, GetModuleHandleA(0), NULL
);
4833 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
4836 ret
= DrawMenuBar(hwnd
);
4837 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
4839 ok_sequence(WmEmptySeq
, "DrawMenuBar for a child window", FALSE
);
4841 DestroyWindow(hwnd
);
4844 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
4845 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
4847 DestroyWindow(hparent
);
4850 /* Message sequence for SetMenu */
4851 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
4852 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %d\n", GetLastError());
4853 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
4855 hmenu
= CreateMenu();
4856 ok (hmenu
!= 0, "Failed to create menu\n");
4857 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
4858 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4859 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
4860 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
4861 ok (SetMenu(hwnd
, 0), "SetMenu\n");
4862 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
4863 ok (SetMenu(hwnd
, 0), "SetMenu\n");
4864 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
4865 ShowWindow(hwnd
, SW_SHOW
);
4866 UpdateWindow( hwnd
);
4869 ok (SetMenu(hwnd
, 0), "SetMenu\n");
4870 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
4871 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
4872 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
4874 UpdateWindow( hwnd
);
4877 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
4879 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
4881 DestroyWindow(hwnd
);
4884 /* Message sequence for EnableWindow */
4885 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
4886 100, 100, 200, 200, 0, 0, 0, NULL
);
4887 ok (hparent
!= 0, "Failed to create parent window\n");
4888 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
4889 0, 0, 10, 10, hparent
, 0, 0, NULL
);
4890 ok (hchild
!= 0, "Failed to create child window\n");
4896 EnableWindow(hparent
, FALSE
);
4897 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
4899 EnableWindow(hparent
, TRUE
);
4900 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(TRUE)", FALSE
);
4905 test_MsgWaitForMultipleObjects(hparent
);
4907 /* the following test causes an exception in user.exe under win9x */
4908 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
4910 DestroyWindow(hparent
);
4914 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
4915 /* PeekMessage(NULL) fails, but still removes the message */
4916 SetLastError(0xdeadbeef);
4917 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
4918 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
4919 GetLastError() == 0xdeadbeef, /* NT4 */
4920 "last error is %d\n", GetLastError() );
4921 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
4922 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
4924 DestroyWindow(hchild
);
4925 DestroyWindow(hparent
);
4928 /* Message sequences for WM_SETICON */
4929 trace("testing WM_SETICON\n");
4930 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4931 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
4933 ShowWindow(hwnd
, SW_SHOW
);
4937 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4938 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
4940 ShowWindow(hwnd
, SW_HIDE
);
4943 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4944 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
4945 DestroyWindow(hwnd
);
4948 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
4949 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
4951 ShowWindow(hwnd
, SW_SHOW
);
4955 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4956 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
4958 ShowWindow(hwnd
, SW_HIDE
);
4961 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
4962 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
4965 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
4968 todo_wine
win_skip( "Message 0x3b not supported\n" );
4971 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
4972 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res
);
4973 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
4974 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
4975 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res
);
4976 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
4977 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
4978 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res
);
4981 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
4982 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
4983 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res
);
4984 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
4985 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
4986 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res
);
4988 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
4989 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
4990 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res
);
4992 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
4993 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
4994 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res
);
4997 DestroyWindow(hwnd
);
5001 static void test_setwindowpos(void)
5006 const INT winX
= 100;
5007 const INT winY
= 100;
5008 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
5010 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
5011 0, 0, winX
, winY
, 0,
5014 GetWindowRect(hwnd
, &rc
);
5015 expect(sysX
, rc
.right
);
5016 expect(winY
, rc
.bottom
);
5020 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, winX
, winY
, 0);
5021 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
5022 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %ld\n", res
);
5024 GetWindowRect(hwnd
, &rc
);
5025 expect(sysX
, rc
.right
);
5026 expect(winY
, rc
.bottom
);
5027 DestroyWindow(hwnd
);
5030 static void invisible_parent_tests(void)
5032 HWND hparent
, hchild
;
5034 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
5035 100, 100, 200, 200, 0, 0, 0, NULL
);
5036 ok (hparent
!= 0, "Failed to create parent window\n");
5039 /* test showing child with hidden parent */
5041 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5042 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5043 ok (hchild
!= 0, "Failed to create child window\n");
5044 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5046 ShowWindow( hchild
, SW_MINIMIZE
);
5047 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5048 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5049 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5054 ShowWindow( hchild
, SW_MINIMIZE
);
5055 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5057 DestroyWindow(hchild
);
5058 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5059 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5062 ShowWindow( hchild
, SW_MAXIMIZE
);
5063 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5064 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5065 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5070 ShowWindow( hchild
, SW_MAXIMIZE
);
5071 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5073 DestroyWindow(hchild
);
5074 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5075 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5078 ShowWindow( hchild
, SW_RESTORE
);
5079 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
5080 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5081 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5083 DestroyWindow(hchild
);
5084 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5085 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5088 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5089 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5090 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5091 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5096 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5097 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5099 DestroyWindow(hchild
);
5100 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5101 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5104 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
5105 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
5106 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
5107 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5108 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5110 DestroyWindow(hchild
);
5111 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5112 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5115 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5116 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5117 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5118 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5123 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5124 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5126 DestroyWindow(hchild
);
5127 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5128 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5131 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
5132 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
5133 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
5135 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5137 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5139 DestroyWindow(hchild
);
5140 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5141 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5144 ShowWindow( hchild
, SW_SHOWNA
);
5145 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5146 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5147 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5152 ShowWindow( hchild
, SW_SHOWNA
);
5153 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5155 DestroyWindow(hchild
);
5156 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5157 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5160 ShowWindow( hchild
, SW_SHOW
);
5161 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5162 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5163 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5168 ShowWindow( hchild
, SW_SHOW
);
5169 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5171 ShowWindow( hchild
, SW_HIDE
);
5172 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
5173 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5174 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5176 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5177 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
5178 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5179 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5181 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5182 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
5183 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
5184 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5186 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5188 DestroyWindow(hchild
);
5189 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
5191 DestroyWindow(hparent
);
5195 /****************** button message test *************************/
5196 #define ID_BUTTON 0x000e
5198 static const struct message WmSetFocusButtonSeq
[] =
5200 { HCBT_SETFOCUS
, hook
},
5201 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5202 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5203 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5204 { WM_SETFOCUS
, sent
|wparam
, 0 },
5205 { WM_CTLCOLORBTN
, sent
|parent
},
5206 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5207 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5210 static const struct message WmKillFocusButtonSeq
[] =
5212 { HCBT_SETFOCUS
, hook
},
5213 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5214 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5215 { WM_CTLCOLORBTN
, sent
|parent
},
5216 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5217 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5218 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5219 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5221 { WM_CTLCOLORBTN
, sent
|parent
},
5224 static const struct message WmSetFocusStaticSeq
[] =
5226 { HCBT_SETFOCUS
, hook
},
5227 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5228 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5229 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5230 { WM_SETFOCUS
, sent
|wparam
, 0 },
5231 { WM_CTLCOLORSTATIC
, sent
|parent
},
5232 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5233 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
5234 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5237 static const struct message WmKillFocusStaticSeq
[] =
5239 { HCBT_SETFOCUS
, hook
},
5240 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5241 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5242 { WM_CTLCOLORSTATIC
, sent
|parent
},
5243 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5244 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5245 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5246 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5248 { WM_CTLCOLORSTATIC
, sent
|parent
},
5251 static const struct message WmSetFocusOwnerdrawSeq
[] =
5253 { HCBT_SETFOCUS
, hook
},
5254 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5255 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5256 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5257 { WM_SETFOCUS
, sent
|wparam
, 0 },
5258 { WM_CTLCOLORBTN
, sent
|parent
},
5259 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
5260 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5261 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5264 static const struct message WmKillFocusOwnerdrawSeq
[] =
5266 { HCBT_SETFOCUS
, hook
},
5267 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5268 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5269 { WM_CTLCOLORBTN
, sent
|parent
},
5270 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
5271 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5272 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5273 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5274 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5276 { WM_CTLCOLORBTN
, sent
|parent
},
5277 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
5280 static const struct message WmLButtonDownSeq
[] =
5282 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
5283 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
5284 { HCBT_SETFOCUS
, hook
},
5285 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5286 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5287 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5288 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5289 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5290 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
5291 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5292 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5295 static const struct message WmLButtonUpSeq
[] =
5297 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
5298 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
5299 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5300 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5301 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
5302 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
5305 static const struct message WmSetFontButtonSeq
[] =
5307 { WM_SETFONT
, sent
},
5309 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
5310 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5313 static const struct message WmSetStyleButtonSeq
[] =
5315 { BM_SETSTYLE
, sent
},
5316 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5318 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5319 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5320 { WM_CTLCOLORBTN
, sent
|parent
},
5323 static const struct message WmSetStyleStaticSeq
[] =
5325 { BM_SETSTYLE
, sent
},
5326 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5328 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5329 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5330 { WM_CTLCOLORSTATIC
, sent
|parent
},
5333 static const struct message WmSetStyleUserSeq
[] =
5335 { BM_SETSTYLE
, sent
},
5336 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5338 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5339 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5340 { WM_CTLCOLORBTN
, sent
|parent
},
5341 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
5344 static const struct message WmSetStyleOwnerdrawSeq
[] =
5346 { BM_SETSTYLE
, sent
},
5347 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5349 { WM_NCPAINT
, sent
|optional
}, /* FIXME: Wine sends it */
5350 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5351 { WM_CTLCOLORBTN
, sent
|parent
},
5352 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
5353 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
5356 static const struct message WmSetStateButtonSeq
[] =
5358 { BM_SETSTATE
, sent
},
5359 { WM_CTLCOLORBTN
, sent
|parent
},
5360 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5363 static const struct message WmSetStateStaticSeq
[] =
5365 { BM_SETSTATE
, sent
},
5366 { WM_CTLCOLORSTATIC
, sent
|parent
},
5367 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5370 static const struct message WmSetStateUserSeq
[] =
5372 { BM_SETSTATE
, sent
},
5373 { WM_CTLCOLORBTN
, sent
|parent
},
5374 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
5375 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5378 static const struct message WmSetStateOwnerdrawSeq
[] =
5380 { BM_SETSTATE
, sent
},
5381 { WM_CTLCOLORBTN
, sent
|parent
},
5382 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
5383 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5386 static const struct message WmClearStateButtonSeq
[] =
5388 { BM_SETSTATE
, sent
},
5389 { WM_CTLCOLORBTN
, sent
|parent
},
5390 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
5391 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5394 static const struct message WmClearStateOwnerdrawSeq
[] =
5396 { BM_SETSTATE
, sent
},
5397 { WM_CTLCOLORBTN
, sent
|parent
},
5398 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
5399 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5402 static const struct message WmSetCheckIgnoredSeq
[] =
5404 { BM_SETCHECK
, sent
},
5405 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5408 static const struct message WmSetCheckStaticSeq
[] =
5410 { BM_SETCHECK
, sent
},
5411 { WM_CTLCOLORSTATIC
, sent
|parent
},
5412 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5416 static WNDPROC old_button_proc
;
5418 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5420 static LONG defwndproc_counter
= 0;
5422 struct recvd_message msg
;
5424 if (ignore_message( message
)) return 0;
5432 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
5436 msg
.message
= message
;
5437 msg
.flags
= sent
|wparam
|lparam
;
5438 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
5439 msg
.wParam
= wParam
;
5440 msg
.lParam
= lParam
;
5441 msg
.descr
= "button";
5445 defwndproc_counter
++;
5446 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
5447 defwndproc_counter
--;
5452 static void subclass_button(void)
5456 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
5458 old_button_proc
= cls
.lpfnWndProc
;
5460 cls
.hInstance
= GetModuleHandleA(NULL
);
5461 cls
.lpfnWndProc
= button_hook_proc
;
5462 cls
.lpszClassName
= "my_button_class";
5463 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
5464 if (!RegisterClassA(&cls
)) assert(0);
5467 static void test_button_messages(void)
5473 const struct message
*setfocus
;
5474 const struct message
*killfocus
;
5475 const struct message
*setstyle
;
5476 const struct message
*setstate
;
5477 const struct message
*clearstate
;
5478 const struct message
*setcheck
;
5480 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
5481 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
5482 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
},
5483 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
5484 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
5485 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
},
5486 { BS_CHECKBOX
, DLGC_BUTTON
,
5487 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5488 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5489 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
5490 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5491 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5492 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
5493 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5494 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5495 { BS_3STATE
, DLGC_BUTTON
,
5496 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5497 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5498 { BS_AUTO3STATE
, DLGC_BUTTON
,
5499 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5500 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5501 { BS_GROUPBOX
, DLGC_STATIC
,
5502 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5503 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
},
5504 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
5505 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
5506 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
},
5507 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
5508 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
5509 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
},
5510 { BS_OWNERDRAW
, DLGC_BUTTON
,
5511 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
5512 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
},
5519 /* selection with VK_SPACE should capture button window */
5520 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
5521 0, 0, 50, 14, 0, 0, 0, NULL
);
5522 ok(hwnd
!= 0, "Failed to create button window\n");
5525 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
5526 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
5527 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
5528 DestroyWindow(hwnd
);
5532 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5533 100, 100, 200, 200, 0, 0, 0, NULL
);
5534 ok(parent
!= 0, "Failed to create parent window\n");
5536 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
5541 trace("button style %08x\n", button
[i
].style
);
5543 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
5544 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
5545 ok(hwnd
!= 0, "Failed to create button window\n");
5547 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5548 style
&= ~(WS_CHILD
| BS_NOTIFY
);
5549 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
5550 if (button
[i
].style
== BS_USERBUTTON
)
5551 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %x\n", style
);
5553 ok(style
== button
[i
].style
, "expected style %x got %x\n", button
[i
].style
, style
);
5555 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
5556 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
5558 ShowWindow(hwnd
, SW_SHOW
);
5565 log_all_parent_messages
++;
5567 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
5569 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5570 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5571 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
5574 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5575 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5576 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
5578 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
5580 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
5581 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5582 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5583 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
5585 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5586 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
5587 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
5588 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5590 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
5591 ok(state
== 0, "expected state 0, got %04x\n", state
);
5595 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
5596 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5597 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5598 ok_sequence(button
[i
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
5600 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
5601 ok(state
== 0x0004, "expected state 0x0004, got %04x\n", state
);
5603 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5604 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5605 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5609 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
5610 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5611 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5612 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
5614 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
5615 ok(state
== 0, "expected state 0, got %04x\n", state
);
5617 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5618 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5619 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5621 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
5622 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
5626 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
5627 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5628 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5629 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
5631 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
5632 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
5634 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5635 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5636 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5640 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
5641 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
5642 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
5643 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
5645 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
5646 if (button
[i
].style
== BS_PUSHBUTTON
||
5647 button
[i
].style
== BS_DEFPUSHBUTTON
||
5648 button
[i
].style
== BS_GROUPBOX
||
5649 button
[i
].style
== BS_USERBUTTON
||
5650 button
[i
].style
== BS_OWNERDRAW
)
5651 ok(state
== BST_UNCHECKED
, "expected check 0, got %04x\n", state
);
5653 ok(state
== BST_CHECKED
, "expected check 1, got %04x\n", state
);
5655 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5656 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
5657 if (button
[i
].style
== BS_RADIOBUTTON
||
5658 button
[i
].style
== BS_AUTORADIOBUTTON
)
5659 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04x | WS_TABSTOP got %04x\n", button
[i
].style
, style
);
5661 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
5663 log_all_parent_messages
--;
5665 DestroyWindow(hwnd
);
5668 DestroyWindow(parent
);
5670 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON
| WS_POPUP
| WS_VISIBLE
,
5671 0, 0, 50, 14, 0, 0, 0, NULL
);
5672 ok(hwnd
!= 0, "Failed to create button window\n");
5674 SetForegroundWindow(hwnd
);
5677 SetActiveWindow(hwnd
);
5681 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
5682 ok_sequence(WmLButtonDownSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
5684 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
5685 ok_sequence(WmLButtonUpSeq
, "WM_LBUTTONUP on a button", FALSE
);
5688 zfont
= GetStockObject(SYSTEM_FONT
);
5689 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
5691 ok_sequence(WmSetFontButtonSeq
, "WM_SETFONT on a button", FALSE
);
5693 DestroyWindow(hwnd
);
5696 /****************** static message test *************************/
5697 static const struct message WmSetFontStaticSeq
[] =
5699 { WM_SETFONT
, sent
},
5700 { WM_PAINT
, sent
|defwinproc
|optional
},
5701 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
5702 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
5706 static WNDPROC old_static_proc
;
5708 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5710 static LONG defwndproc_counter
= 0;
5712 struct recvd_message msg
;
5714 if (ignore_message( message
)) return 0;
5717 msg
.message
= message
;
5718 msg
.flags
= sent
|wparam
|lparam
;
5719 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
5720 msg
.wParam
= wParam
;
5721 msg
.lParam
= lParam
;
5722 msg
.descr
= "static";
5725 defwndproc_counter
++;
5726 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
5727 defwndproc_counter
--;
5732 static void subclass_static(void)
5736 if (!GetClassInfoA(0, "static", &cls
)) assert(0);
5738 old_static_proc
= cls
.lpfnWndProc
;
5740 cls
.hInstance
= GetModuleHandleA(NULL
);
5741 cls
.lpfnWndProc
= static_hook_proc
;
5742 cls
.lpszClassName
= "my_static_class";
5743 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
5744 if (!RegisterClassA(&cls
)) assert(0);
5747 static void test_static_messages(void)
5749 /* FIXME: make as comprehensive as the button message test */
5754 const struct message
*setfont
;
5756 { SS_LEFT
, DLGC_STATIC
,
5757 WmSetFontStaticSeq
}
5765 for (i
= 0; i
< sizeof(static_ctrl
)/sizeof(static_ctrl
[0]); i
++)
5767 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
5768 0, 0, 50, 14, 0, 0, 0, NULL
);
5769 ok(hwnd
!= 0, "Failed to create static window\n");
5771 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
5772 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
5774 ShowWindow(hwnd
, SW_SHOW
);
5779 trace("static style %08x\n", static_ctrl
[i
].style
);
5780 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
5781 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
5783 DestroyWindow(hwnd
);
5787 /****************** ComboBox message test *************************/
5788 #define ID_COMBOBOX 0x000f
5790 static const struct message WmKeyDownComboSeq
[] =
5792 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
5793 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
5794 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
5795 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
5796 { WM_CTLCOLOREDIT
, sent
|parent
},
5797 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
5801 static const struct message WmSetPosComboSeq
[] =
5803 { WM_WINDOWPOSCHANGING
, sent
},
5804 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
5805 { WM_CHILDACTIVATE
, sent
},
5806 { WM_WINDOWPOSCHANGED
, sent
},
5807 { WM_MOVE
, sent
|defwinproc
},
5808 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
5809 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
5810 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
5811 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
5812 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
5816 static WNDPROC old_combobox_proc
;
5818 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5820 static LONG defwndproc_counter
= 0;
5822 struct recvd_message msg
;
5824 /* do not log painting messages */
5825 if (message
!= WM_PAINT
&&
5826 message
!= WM_NCPAINT
&&
5827 message
!= WM_SYNCPAINT
&&
5828 message
!= WM_ERASEBKGND
&&
5829 message
!= WM_NCHITTEST
&&
5830 message
!= WM_GETTEXT
&&
5831 !ignore_message( message
))
5834 msg
.message
= message
;
5835 msg
.flags
= sent
|wparam
|lparam
;
5836 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
5837 msg
.wParam
= wParam
;
5838 msg
.lParam
= lParam
;
5839 msg
.descr
= "combo";
5843 defwndproc_counter
++;
5844 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
5845 defwndproc_counter
--;
5850 static void subclass_combobox(void)
5854 if (!GetClassInfoA(0, "ComboBox", &cls
)) assert(0);
5856 old_combobox_proc
= cls
.lpfnWndProc
;
5858 cls
.hInstance
= GetModuleHandleA(NULL
);
5859 cls
.lpfnWndProc
= combobox_hook_proc
;
5860 cls
.lpszClassName
= "my_combobox_class";
5861 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
5862 if (!RegisterClassA(&cls
)) assert(0);
5865 static void test_combobox_messages(void)
5870 subclass_combobox();
5872 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5873 100, 100, 200, 200, 0, 0, 0, NULL
);
5874 ok(parent
!= 0, "Failed to create parent window\n");
5877 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
5878 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
5879 ok(combo
!= 0, "Failed to create combobox window\n");
5881 UpdateWindow(combo
);
5883 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
5884 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", ret
);
5886 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
5887 ok(ret
== 0, "expected 0, got %ld\n", ret
);
5888 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
5889 ok(ret
== 1, "expected 1, got %ld\n", ret
);
5890 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
5891 ok(ret
== 2, "expected 2, got %ld\n", ret
);
5893 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
5897 log_all_parent_messages
++;
5898 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
5899 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
5900 log_all_parent_messages
--;
5901 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
5904 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
5905 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
5907 DestroyWindow(combo
);
5908 DestroyWindow(parent
);
5911 /****************** WM_IME_KEYDOWN message test *******************/
5913 static const struct message WmImeKeydownMsgSeq_0
[] =
5915 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
5916 { WM_CHAR
, wparam
, 'A' },
5920 static const struct message WmImeKeydownMsgSeq_1
[] =
5922 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
5923 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
5927 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5929 struct recvd_message msg
;
5932 msg
.message
= message
;
5933 msg
.flags
= wparam
|lparam
;
5934 msg
.wParam
= wParam
;
5935 msg
.lParam
= lParam
;
5936 msg
.descr
= "wmime_keydown";
5939 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
5942 static void register_wmime_keydown_class(void)
5946 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
5947 cls
.lpfnWndProc
= wmime_keydown_procA
;
5948 cls
.hInstance
= GetModuleHandleA(0);
5949 cls
.lpszClassName
= "wmime_keydown_class";
5950 if (!RegisterClassA(&cls
)) assert(0);
5953 static void test_wmime_keydown_message(void)
5958 trace("Message sequences by WM_IME_KEYDOWN\n");
5960 register_wmime_keydown_class();
5961 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
5962 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5967 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
5968 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
5969 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
5971 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
5973 TranslateMessage(&msg
);
5974 DispatchMessageA(&msg
);
5976 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
5978 DestroyWindow(hwnd
);
5981 /************* painting message test ********************/
5983 void dump_region(HRGN hrgn
)
5986 RGNDATA
*data
= NULL
;
5991 printf( "null region\n" );
5994 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
5995 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
5996 GetRegionData( hrgn
, size
, data
);
5997 printf("%d rects:", data
->rdh
.nCount
);
5998 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
5999 printf( " (%d,%d)-(%d,%d)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
6001 HeapFree( GetProcessHeap(), 0, data
);
6004 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
6008 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
6009 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
6011 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
6012 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
6013 if (ret
== NULLREGION
)
6015 ok( !hrgn
, "Update region shouldn't be empty\n" );
6019 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
6021 ok( 0, "Regions are different\n" );
6022 if (winetest_debug
> 0)
6024 printf( "Update region: " );
6025 dump_region( update
);
6026 printf( "Wanted region: " );
6027 dump_region( hrgn
);
6031 GetRgnBox( update
, &r1
);
6032 GetUpdateRect( hwnd
, &r2
, FALSE
);
6033 ok( r1
.left
== r2
.left
&& r1
.top
== r2
.top
&& r1
.right
== r2
.right
&& r1
.bottom
== r2
.bottom
,
6034 "Rectangles are different: %d,%d-%d,%d / %d,%d-%d,%d\n",
6035 r1
.left
, r1
.top
, r1
.right
, r1
.bottom
, r2
.left
, r2
.top
, r2
.right
, r2
.bottom
);
6037 DeleteObject( tmp
);
6038 DeleteObject( update
);
6041 static const struct message WmInvalidateRgn
[] = {
6042 { WM_NCPAINT
, sent
},
6043 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6047 static const struct message WmGetUpdateRect
[] = {
6048 { WM_NCPAINT
, sent
},
6049 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6054 static const struct message WmInvalidateFull
[] = {
6055 { WM_NCPAINT
, sent
|wparam
, 1 },
6056 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6060 static const struct message WmInvalidateErase
[] = {
6061 { WM_NCPAINT
, sent
|wparam
, 1 },
6062 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6063 { WM_ERASEBKGND
, sent
},
6067 static const struct message WmInvalidatePaint
[] = {
6069 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
6070 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6074 static const struct message WmInvalidateErasePaint
[] = {
6076 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
6077 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6078 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6082 static const struct message WmInvalidateErasePaint2
[] = {
6084 { WM_NCPAINT
, sent
|beginpaint
},
6085 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6086 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6090 static const struct message WmErase
[] = {
6091 { WM_ERASEBKGND
, sent
},
6095 static const struct message WmPaint
[] = {
6100 static const struct message WmParentOnlyPaint
[] = {
6101 { WM_PAINT
, sent
|parent
},
6105 static const struct message WmInvalidateParent
[] = {
6106 { WM_NCPAINT
, sent
|parent
},
6107 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
6108 { WM_ERASEBKGND
, sent
|parent
},
6112 static const struct message WmInvalidateParentChild
[] = {
6113 { WM_NCPAINT
, sent
|parent
},
6114 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
6115 { WM_ERASEBKGND
, sent
|parent
},
6116 { WM_NCPAINT
, sent
},
6117 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6118 { WM_ERASEBKGND
, sent
},
6122 static const struct message WmInvalidateParentChild2
[] = {
6123 { WM_ERASEBKGND
, sent
|parent
},
6124 { WM_NCPAINT
, sent
},
6125 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6126 { WM_ERASEBKGND
, sent
},
6130 static const struct message WmParentPaint
[] = {
6131 { WM_PAINT
, sent
|parent
},
6136 static const struct message WmParentPaintNc
[] = {
6137 { WM_PAINT
, sent
|parent
},
6139 { WM_NCPAINT
, sent
|beginpaint
},
6140 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6141 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6145 static const struct message WmChildPaintNc
[] = {
6147 { WM_NCPAINT
, sent
|beginpaint
},
6148 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6149 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6153 static const struct message WmParentErasePaint
[] = {
6154 { WM_PAINT
, sent
|parent
},
6155 { WM_NCPAINT
, sent
|parent
|beginpaint
},
6156 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
6157 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
6159 { WM_NCPAINT
, sent
|beginpaint
},
6160 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
6161 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
6165 static const struct message WmParentOnlyNcPaint
[] = {
6166 { WM_PAINT
, sent
|parent
},
6167 { WM_NCPAINT
, sent
|parent
|beginpaint
},
6168 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
6172 static const struct message WmSetParentStyle
[] = {
6173 { WM_STYLECHANGING
, sent
|parent
},
6174 { WM_STYLECHANGED
, sent
|parent
},
6178 static void test_paint_messages(void)
6184 HWND hparent
, hchild
;
6185 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
6186 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
6187 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
6188 100, 100, 200, 200, 0, 0, 0, NULL
);
6189 ok (hwnd
!= 0, "Failed to create overlapped window\n");
6191 ShowWindow( hwnd
, SW_SHOW
);
6192 UpdateWindow( hwnd
);
6196 check_update_rgn( hwnd
, 0 );
6197 SetRectRgn( hrgn
, 10, 10, 20, 20 );
6198 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
6199 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6200 check_update_rgn( hwnd
, hrgn
);
6201 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
6202 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
6203 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6204 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
6205 check_update_rgn( hwnd
, hrgn
);
6206 /* validate everything */
6207 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
6208 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6209 check_update_rgn( hwnd
, 0 );
6211 /* test empty region */
6212 SetRectRgn( hrgn
, 10, 10, 10, 15 );
6213 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
6214 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6215 check_update_rgn( hwnd
, 0 );
6216 /* test empty rect */
6217 SetRect( &rect
, 10, 10, 10, 15 );
6218 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
6219 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
6220 check_update_rgn( hwnd
, 0 );
6222 /* flush pending messages */
6226 GetClientRect( hwnd
, &rect
);
6227 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
6228 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
6229 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
6231 trace("testing InvalidateRect(0, NULL, FALSE)\n");
6232 SetRectEmpty( &rect
);
6233 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) should fail\n");
6234 check_update_rgn( hwnd
, hrgn
);
6235 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
6237 ok_sequence( WmPaint
, "Paint", FALSE
);
6238 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
6239 check_update_rgn( hwnd
, 0 );
6241 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
6242 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
6244 trace("testing ValidateRect(0, NULL)\n");
6245 SetRectEmpty( &rect
);
6246 if (ValidateRect(0, &rect
)) /* not supported on Win9x */
6248 check_update_rgn( hwnd
, hrgn
);
6249 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
6251 ok_sequence( WmPaint
, "Paint", FALSE
);
6252 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
6253 check_update_rgn( hwnd
, 0 );
6256 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
6257 SetLastError(0xdeadbeef);
6258 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
6259 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
6260 "wrong error code %d\n", GetLastError());
6261 check_update_rgn( hwnd
, 0 );
6263 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
6265 trace("testing ValidateRgn(0, NULL)\n");
6266 SetLastError(0xdeadbeef);
6267 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
6268 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
6269 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
6270 "wrong error code %d\n", GetLastError());
6271 check_update_rgn( hwnd
, 0 );
6273 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
6275 trace("testing UpdateWindow(NULL)\n");
6276 SetLastError(0xdeadbeef);
6277 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
6278 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
6279 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
6280 "wrong error code %d\n", GetLastError());
6281 check_update_rgn( hwnd
, 0 );
6283 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
6285 /* now with frame */
6286 SetRectRgn( hrgn
, -5, -5, 20, 20 );
6288 /* flush pending messages */
6291 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6292 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
6294 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
6295 check_update_rgn( hwnd
, hrgn
);
6298 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
6299 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
6302 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
6303 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
6305 GetClientRect( hwnd
, &rect
);
6306 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
6307 check_update_rgn( hwnd
, hrgn
);
6310 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
6311 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
6314 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
6315 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
6316 check_update_rgn( hwnd
, 0 );
6319 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
6320 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
6321 check_update_rgn( hwnd
, 0 );
6324 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6325 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
6326 SetRectRgn( hrgn
, 0, 0, 50, 100 );
6327 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
6328 SetRectRgn( hrgn
, 50, 0, 100, 100 );
6329 check_update_rgn( hwnd
, hrgn
);
6330 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
6331 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
6332 check_update_rgn( hwnd
, 0 );
6335 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6336 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
6337 SetRectRgn( hrgn
, 0, 0, 100, 50 );
6338 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
6339 ok_sequence( WmErase
, "Erase", FALSE
);
6340 SetRectRgn( hrgn
, 0, 50, 100, 100 );
6341 check_update_rgn( hwnd
, hrgn
);
6344 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6345 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
6346 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6347 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
6348 ok_sequence( WmPaint
, "Paint", FALSE
);
6351 SetRectRgn( hrgn
, -4, -4, -2, -2 );
6352 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6353 SetRectRgn( hrgn
, -200, -200, -198, -198 );
6354 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
6355 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
6358 SetRectRgn( hrgn
, -4, -4, -2, -2 );
6359 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6360 SetRectRgn( hrgn
, -4, -4, -3, -3 );
6361 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
6362 SetRectRgn( hrgn
, 0, 0, 1, 1 );
6363 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
6364 ok_sequence( WmPaint
, "Paint", FALSE
);
6367 SetRectRgn( hrgn
, -4, -4, -1, -1 );
6368 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6369 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
6370 /* make sure no WM_PAINT was generated */
6372 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
6375 SetRectRgn( hrgn
, -4, -4, -1, -1 );
6376 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
6377 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
6379 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
6381 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
6382 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
6383 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
6384 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
6385 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
6386 /* this will send WM_NCPAINT and validate the non client area */
6387 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
6388 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
6390 DispatchMessageA( &msg
);
6392 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
6394 DestroyWindow( hwnd
);
6396 /* now test with a child window */
6398 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
6399 100, 100, 200, 200, 0, 0, 0, NULL
);
6400 ok (hparent
!= 0, "Failed to create parent window\n");
6402 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
6403 10, 10, 100, 100, hparent
, 0, 0, NULL
);
6404 ok (hchild
!= 0, "Failed to create child window\n");
6406 ShowWindow( hparent
, SW_SHOW
);
6407 UpdateWindow( hparent
);
6408 UpdateWindow( hchild
);
6411 log_all_parent_messages
++;
6413 SetRect( &rect
, 0, 0, 50, 50 );
6414 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6415 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
6416 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
6418 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6420 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
6421 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
6422 check_update_rgn( hchild
, hrgn
);
6423 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6424 check_update_rgn( hparent
, hrgn
);
6425 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6426 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
6427 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
6428 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
6431 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
6433 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
6434 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6435 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
6436 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
6437 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
6439 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
6440 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
6441 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
6443 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
6445 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
6446 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6447 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
6449 /* flush all paint messages */
6453 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
6454 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
6455 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6456 check_update_rgn( hparent
, hrgn
);
6457 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
6458 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6459 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6460 check_update_rgn( hparent
, hrgn
);
6462 /* flush all paint messages */
6464 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
6467 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
6468 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6469 SetRectRgn( hrgn
, 0, 0, 50, 50 );
6470 check_update_rgn( hparent
, hrgn
);
6471 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
6472 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6473 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
6474 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
6475 check_update_rgn( hparent
, hrgn
);
6476 /* flush all paint messages */
6480 /* same as above but parent gets completely validated */
6481 SetRect( &rect
, 20, 20, 30, 30 );
6482 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6483 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6484 check_update_rgn( hparent
, hrgn
);
6485 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
6486 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6487 check_update_rgn( hparent
, 0 ); /* no update region */
6489 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
6491 /* make sure RDW_VALIDATE on child doesn't have the same effect */
6493 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6494 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6495 check_update_rgn( hparent
, hrgn
);
6496 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
6497 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6498 check_update_rgn( hparent
, hrgn
);
6500 /* same as above but normal WM_PAINT doesn't validate parent */
6502 SetRect( &rect
, 20, 20, 30, 30 );
6503 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6504 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6505 check_update_rgn( hparent
, hrgn
);
6506 /* no WM_PAINT in child while parent still pending */
6507 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6508 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
6509 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6510 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
6513 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6514 /* no WM_PAINT in child while parent still pending */
6515 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6516 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
6517 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
6518 /* now that parent is valid child should get WM_PAINT */
6519 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6520 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
6521 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6522 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
6524 /* same thing with WS_CLIPCHILDREN in parent */
6526 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
6527 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
6528 /* changing style invalidates non client area, but we need to invalidate something else to see it */
6529 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
6530 ok_sequence( WmEmptySeq
, "No message", FALSE
);
6531 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
6532 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
6535 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
6536 SetRectRgn( hrgn
, 20, 20, 30, 30 );
6537 check_update_rgn( hparent
, hrgn
);
6538 /* no WM_PAINT in child while parent still pending */
6539 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6540 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
6541 /* WM_PAINT in parent first */
6542 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6543 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
6545 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
6547 SetRect( &rect
, 0, 0, 30, 30 );
6548 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
6549 SetRectRgn( hrgn
, 0, 0, 30, 30 );
6550 check_update_rgn( hparent
, hrgn
);
6552 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
6554 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
6556 SetRect( &rect
, -10, 0, 30, 30 );
6557 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
6558 SetRect( &rect
, 0, 0, 20, 20 );
6559 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
6560 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
6561 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
6563 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
6565 SetRect( &rect
, -10, 0, 30, 30 );
6566 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
6567 SetRect( &rect
, 0, 0, 100, 100 );
6568 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
6569 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
6570 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
6571 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
6572 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
6574 /* test RDW_INTERNALPAINT behavior */
6577 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
6579 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
6581 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
6583 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
6585 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
6587 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
6589 assert( GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
);
6590 UpdateWindow( hparent
);
6593 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
6594 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6595 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
6596 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6598 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
6600 UpdateWindow( hparent
);
6603 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
6604 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6605 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
6606 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6608 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
6610 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
6611 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
6612 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
6614 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
6616 assert( !(GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
) );
6617 UpdateWindow( hparent
);
6620 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
6621 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6622 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
6623 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6625 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
6627 UpdateWindow( hparent
);
6630 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
6631 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
6632 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
6633 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
6635 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
6637 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
6638 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
6640 UpdateWindow( hparent
);
6643 trace("testing SetWindowPos(-10000, -10000) on child\n");
6644 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
6645 check_update_rgn( hchild
, 0 );
6648 #if 0 /* this one doesn't pass under Wine yet */
6649 UpdateWindow( hparent
);
6652 trace("testing ShowWindow(SW_MINIMIZE) on child\n");
6653 ShowWindow( hchild
, SW_MINIMIZE
);
6654 check_update_rgn( hchild
, 0 );
6658 UpdateWindow( hparent
);
6661 trace("testing SetWindowPos(-10000, -10000) on parent\n");
6662 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
6663 check_update_rgn( hparent
, 0 );
6666 log_all_parent_messages
--;
6667 DestroyWindow( hparent
);
6668 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
6670 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
6672 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
6673 100, 100, 200, 200, 0, 0, 0, NULL
);
6674 ok (hparent
!= 0, "Failed to create parent window\n");
6676 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
6677 10, 10, 100, 100, hparent
, 0, 0, NULL
);
6678 ok (hchild
!= 0, "Failed to create child window\n");
6680 ShowWindow( hparent
, SW_SHOW
);
6681 UpdateWindow( hparent
);
6682 UpdateWindow( hchild
);
6686 /* moving child outside of parent boundaries changes update region */
6687 SetRect( &rect
, 0, 0, 40, 40 );
6688 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
6689 SetRectRgn( hrgn
, 0, 0, 40, 40 );
6690 check_update_rgn( hchild
, hrgn
);
6691 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
6692 SetRectRgn( hrgn
, 10, 0, 40, 40 );
6693 check_update_rgn( hchild
, hrgn
);
6694 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
6695 SetRectRgn( hrgn
, 10, 10, 40, 40 );
6696 check_update_rgn( hchild
, hrgn
);
6698 /* moving parent off-screen does too */
6699 SetRect( &rect
, 0, 0, 100, 100 );
6700 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
6701 SetRectRgn( hrgn
, 0, 0, 100, 100 );
6702 check_update_rgn( hparent
, hrgn
);
6703 SetRectRgn( hrgn
, 10, 10, 40, 40 );
6704 check_update_rgn( hchild
, hrgn
);
6705 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
6706 SetRectRgn( hrgn
, 20, 20, 100, 100 );
6707 check_update_rgn( hparent
, hrgn
);
6708 SetRectRgn( hrgn
, 30, 30, 40, 40 );
6709 check_update_rgn( hchild
, hrgn
);
6711 /* invalidated region is cropped by the parent rects */
6712 SetRect( &rect
, 0, 0, 50, 50 );
6713 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
6714 SetRectRgn( hrgn
, 30, 30, 50, 50 );
6715 check_update_rgn( hchild
, hrgn
);
6717 DestroyWindow( hparent
);
6718 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
6721 DeleteObject( hrgn
);
6722 DeleteObject( hrgn2
);
6733 static DWORD WINAPI
thread_proc(void *param
)
6736 struct wnd_event
*wnd_event
= param
;
6738 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
6739 100, 100, 200, 200, 0, 0, 0, NULL
);
6740 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
6742 SetEvent(wnd_event
->start_event
);
6744 while (GetMessageA(&msg
, 0, 0, 0))
6746 TranslateMessage(&msg
);
6747 DispatchMessageA(&msg
);
6750 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
6755 static DWORD CALLBACK
create_grand_child_thread( void *param
)
6757 struct wnd_event
*wnd_event
= param
;
6761 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
6762 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
6763 ok (hchild
!= 0, "Failed to create child window\n");
6766 SetEvent( wnd_event
->start_event
);
6770 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
6771 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
6772 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6777 static DWORD CALLBACK
create_child_thread( void *param
)
6779 struct wnd_event
*wnd_event
= param
;
6780 struct wnd_event child_event
;
6784 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
6785 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
6786 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
6787 SetFocus( child_event
.hwnd
);
6790 child_event
.start_event
= wnd_event
->start_event
;
6791 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
6794 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
6795 if (ret
!= 1) break;
6796 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6798 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
6799 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
6803 static const char manifest_dep
[] =
6804 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
6805 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
6806 " <file name=\"testdep.dll\" />"
6809 static const char manifest_main
[] =
6810 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
6811 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
6813 " <dependentAssembly>"
6814 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
6815 " </dependentAssembly>"
6819 static void create_manifest_file(const char *filename
, const char *manifest
)
6821 WCHAR path
[MAX_PATH
];
6825 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
6826 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
6827 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
6828 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
6832 static HANDLE
test_create(const char *file
)
6834 WCHAR path
[MAX_PATH
];
6838 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
6839 memset(&actctx
, 0, sizeof(ACTCTXW
));
6840 actctx
.cbSize
= sizeof(ACTCTXW
);
6841 actctx
.lpSource
= path
;
6843 handle
= pCreateActCtxW(&actctx
);
6844 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %u\n", GetLastError());
6846 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%d\n", actctx
.cbSize
);
6847 ok(actctx
.dwFlags
== 0, "dwFlags=%d\n", actctx
.dwFlags
);
6848 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
6849 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
6850 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
6851 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
6852 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
6853 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
6854 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
6859 static void test_interthread_messages(void)
6861 HANDLE hThread
, context
, handle
, event
;
6867 int len
, expected_len
;
6868 struct wnd_event wnd_event
;
6871 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
6872 if (!wnd_event
.start_event
)
6874 win_skip("skipping interthread message test under win9x\n");
6878 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
6879 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
6881 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
6883 CloseHandle(wnd_event
.start_event
);
6885 SetLastError(0xdeadbeef);
6886 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
6887 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
6888 "wrong error code %d\n", GetLastError());
6890 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
6891 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
6893 expected_len
= lstrlenA("window caption text");
6894 memset(buf
, 0, sizeof(buf
));
6895 SetLastError(0xdeadbeef);
6896 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
6897 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
6898 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
6900 msg
.hwnd
= wnd_event
.hwnd
;
6901 msg
.message
= WM_GETTEXT
;
6902 msg
.wParam
= sizeof(buf
);
6903 msg
.lParam
= (LPARAM
)buf
;
6904 memset(buf
, 0, sizeof(buf
));
6905 SetLastError(0xdeadbeef);
6906 len
= DispatchMessageA(&msg
);
6907 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
6908 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len
, GetLastError());
6910 /* the following test causes an exception in user.exe under win9x */
6911 msg
.hwnd
= wnd_event
.hwnd
;
6912 msg
.message
= WM_TIMER
;
6914 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
6915 SetLastError(0xdeadbeef);
6916 len
= DispatchMessageA(&msg
);
6917 ok(!len
&& GetLastError() == 0xdeadbeef,
6918 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len
, GetLastError());
6920 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
6921 ok( ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
6923 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
6924 CloseHandle(hThread
);
6926 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
6928 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6929 100, 100, 200, 200, 0, 0, 0, NULL
);
6930 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
6933 log_all_parent_messages
++;
6934 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
6935 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
6936 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
6939 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
6940 if (ret
!= 1) break;
6941 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6943 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
6944 /* now wait for the thread without processing messages; this shouldn't deadlock */
6945 SetEvent( wnd_event
.stop_event
);
6946 ret
= WaitForSingleObject( hThread
, 5000 );
6947 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
6948 CloseHandle( hThread
);
6950 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
6951 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
6952 CloseHandle( wnd_event
.grand_child
);
6954 CloseHandle( wnd_event
.start_event
);
6955 CloseHandle( wnd_event
.stop_event
);
6957 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
6958 log_all_parent_messages
--;
6959 DestroyWindow( wnd_event
.hwnd
);
6961 /* activation context tests */
6962 if (!pActivateActCtx
)
6964 win_skip("Activation contexts are not supported, skipping\n");
6968 create_manifest_file("testdep1.manifest", manifest_dep
);
6969 create_manifest_file("main.manifest", manifest_main
);
6971 context
= test_create("main.manifest");
6972 DeleteFileA("testdep1.manifest");
6973 DeleteFileA("main.manifest");
6975 handle
= (void*)0xdeadbeef;
6976 ret
= pGetCurrentActCtx(&handle
);
6977 ok(ret
, "GetCurentActCtx failed: %u\n", GetLastError());
6978 ok(handle
== 0, "active context %p\n", handle
);
6980 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
6981 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
6982 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
6983 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
6984 CloseHandle(wnd_event
.start_event
);
6986 /* context is activated after thread creation, so it doesn't inherit it by default */
6987 ret
= pActivateActCtx(context
, &cookie
);
6988 ok(ret
, "activation failed: %u\n", GetLastError());
6991 ret
= pGetCurrentActCtx(&handle
);
6992 ok(ret
, "GetCurentActCtx failed: %u\n", GetLastError());
6993 ok(handle
!= 0, "active context %p\n", handle
);
6994 pReleaseActCtx(handle
);
6996 /* destination window will test for active context */
6997 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
6998 ok(ret
, "thread window returned %d\n", ret
);
7000 event
= CreateEventW(NULL
, 0, 0, NULL
);
7001 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
7002 ok(ret
, "thread window returned %d\n", ret
);
7003 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7006 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
7007 ok(ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
7009 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7010 CloseHandle(hThread
);
7012 ret
= pDeactivateActCtx(0, cookie
);
7013 ok(ret
, "DeactivateActCtx failed: %u\n", GetLastError());
7014 pReleaseActCtx(context
);
7018 static const struct message WmVkN
[] = {
7019 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7020 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7021 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7022 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
7023 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
7024 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7025 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7026 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7029 static const struct message WmShiftVkN
[] = {
7030 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7031 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7032 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
7033 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7034 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7035 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7036 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
7037 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
7038 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7039 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7040 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7041 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
7042 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7043 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7046 static const struct message WmCtrlVkN
[] = {
7047 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7048 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7049 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7050 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7051 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7052 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7053 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
7054 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
7055 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7056 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7057 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7058 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7059 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7060 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7063 static const struct message WmCtrlVkN_2
[] = {
7064 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7065 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7066 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7067 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7068 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7069 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
7070 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7071 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7072 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7073 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7074 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7075 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7078 static const struct message WmAltVkN
[] = {
7079 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7080 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7081 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7082 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
7083 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
7084 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
7085 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
7086 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
7087 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
7088 { HCBT_SYSCOMMAND
, hook
},
7089 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7090 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
7091 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
7092 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
7093 { WM_INITMENU
, sent
|defwinproc
},
7094 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7095 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
7096 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
7097 { WM_CAPTURECHANGED
, sent
|defwinproc
},
7098 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
7099 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7100 { WM_EXITMENULOOP
, sent
|defwinproc
},
7101 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
7102 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
7103 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7104 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7105 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7106 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7107 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7108 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7111 static const struct message WmAltVkN_2
[] = {
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_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
7118 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7119 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7120 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7121 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7122 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7123 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7126 static const struct message WmCtrlAltVkN
[] = {
7127 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7128 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7129 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7130 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7131 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7132 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7133 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
7134 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
7135 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
7136 { WM_CHAR
, optional
},
7137 { WM_CHAR
, sent
|optional
},
7138 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7139 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7140 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7141 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7142 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7143 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7144 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7145 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7146 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7149 static const struct message WmCtrlShiftVkN
[] = {
7150 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7151 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7152 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7153 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7154 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7155 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
7156 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7157 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7158 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
7159 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7160 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7161 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7162 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
7163 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7164 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7165 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7166 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7167 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7170 static const struct message WmCtrlAltShiftVkN
[] = {
7171 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
7172 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
7173 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
7174 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7175 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7176 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7177 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
7178 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
7179 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
7180 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
7181 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
7182 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
7183 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
7184 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
7185 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
7186 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
7187 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
7188 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
7189 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7190 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7191 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7192 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
7193 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7194 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
7197 static const struct message WmAltPressRelease
[] = {
7198 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
7199 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
7200 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
7201 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7202 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7203 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7204 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
7205 { HCBT_SYSCOMMAND
, hook
},
7206 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7207 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
7208 { WM_INITMENU
, sent
|defwinproc
},
7209 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7210 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
) },
7211 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
7213 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
7215 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7216 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
7217 { WM_CAPTURECHANGED
, sent
|defwinproc
},
7218 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
7219 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7220 { WM_EXITMENULOOP
, sent
|defwinproc
},
7221 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
7222 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
7223 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
7226 static const struct message WmShiftMouseButton
[] = {
7227 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7228 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7229 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
7230 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
7231 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
7232 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
7233 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
7234 { WM_LBUTTONUP
, wparam
, MK_SHIFT
, 0 },
7235 { WM_LBUTTONUP
, sent
|wparam
, MK_SHIFT
, 0 },
7236 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
7237 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7238 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
7241 static const struct message WmF1Seq
[] = {
7242 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
7243 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
7244 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
7245 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
7246 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
7247 { WM_HELP
, sent
|defwinproc
},
7248 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
7249 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
7250 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
7253 static const struct message WmVkAppsSeq
[] = {
7254 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
7255 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
7256 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
7257 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
7258 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
7259 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
7260 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
7261 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
7264 static const struct message WmVkF10Seq
[] = {
7265 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
7266 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
7267 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
7268 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
7269 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
7270 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
7271 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
7272 { HCBT_SYSCOMMAND
, hook
},
7273 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7274 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
7275 { WM_INITMENU
, sent
|defwinproc
},
7276 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7277 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
) },
7278 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
7280 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
7282 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
7283 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7284 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
7285 { WM_CAPTURECHANGED
, sent
|defwinproc
},
7286 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
7287 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
7288 { WM_EXITMENULOOP
, sent
|defwinproc
},
7289 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
7290 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
7291 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
7294 static const struct message WmShiftF10Seq
[] = {
7295 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7296 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7297 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
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 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
7302 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
7303 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
7304 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
7305 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
7306 { HCBT_SYSCOMMAND
, hook
},
7307 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7308 { WM_INITMENU
, sent
|defwinproc
},
7309 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
) },
7310 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
7311 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
7312 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7313 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
7314 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7315 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
7316 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
7317 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
7321 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
7325 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
7327 struct recvd_message log_msg
;
7329 /* ignore some unwanted messages */
7330 if (msg
.message
== WM_MOUSEMOVE
||
7331 msg
.message
== WM_TIMER
||
7332 ignore_message( msg
.message
))
7335 log_msg
.hwnd
= msg
.hwnd
;
7336 log_msg
.message
= msg
.message
;
7337 log_msg
.flags
= wparam
|lparam
;
7338 log_msg
.wParam
= msg
.wParam
;
7339 log_msg
.lParam
= msg
.lParam
;
7340 log_msg
.descr
= "accel";
7341 add_message(&log_msg
);
7343 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
7345 TranslateMessage(&msg
);
7346 DispatchMessageA(&msg
);
7351 static void test_accelerators(void)
7357 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7358 100, 100, 200, 200, 0, 0, 0, NULL
);
7367 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
7369 state
= GetKeyState(VK_SHIFT
);
7370 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
7371 state
= GetKeyState(VK_CAPITAL
);
7372 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
7374 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
7375 assert(hAccel
!= 0);
7378 pump_msg_loop(hwnd
, 0);
7381 trace("testing VK_N press/release\n");
7383 keybd_event('N', 0, 0, 0);
7384 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7385 pump_msg_loop(hwnd
, hAccel
);
7386 if (!sequence_cnt
) /* we didn't get any message */
7388 skip( "queuing key events not supported\n" );
7391 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
7393 trace("testing Shift+VK_N press/release\n");
7395 keybd_event(VK_SHIFT
, 0, 0, 0);
7396 keybd_event('N', 0, 0, 0);
7397 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7398 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7399 pump_msg_loop(hwnd
, hAccel
);
7400 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
7402 trace("testing Ctrl+VK_N press/release\n");
7404 keybd_event(VK_CONTROL
, 0, 0, 0);
7405 keybd_event('N', 0, 0, 0);
7406 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7407 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7408 pump_msg_loop(hwnd
, hAccel
);
7409 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
7411 trace("testing Alt+VK_N press/release\n");
7413 keybd_event(VK_MENU
, 0, 0, 0);
7414 keybd_event('N', 0, 0, 0);
7415 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7416 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7417 pump_msg_loop(hwnd
, hAccel
);
7418 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
7420 trace("testing Ctrl+Alt+VK_N press/release 1\n");
7422 keybd_event(VK_CONTROL
, 0, 0, 0);
7423 keybd_event(VK_MENU
, 0, 0, 0);
7424 keybd_event('N', 0, 0, 0);
7425 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7426 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7427 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7428 pump_msg_loop(hwnd
, hAccel
);
7429 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
7431 ret
= DestroyAcceleratorTable(hAccel
);
7432 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
7434 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
7435 assert(hAccel
!= 0);
7437 trace("testing VK_N press/release\n");
7439 keybd_event('N', 0, 0, 0);
7440 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7441 pump_msg_loop(hwnd
, hAccel
);
7442 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
7444 trace("testing Shift+VK_N press/release\n");
7446 keybd_event(VK_SHIFT
, 0, 0, 0);
7447 keybd_event('N', 0, 0, 0);
7448 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7449 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7450 pump_msg_loop(hwnd
, hAccel
);
7451 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
7453 trace("testing Ctrl+VK_N press/release 2\n");
7455 keybd_event(VK_CONTROL
, 0, 0, 0);
7456 keybd_event('N', 0, 0, 0);
7457 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7458 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7459 pump_msg_loop(hwnd
, hAccel
);
7460 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
7462 trace("testing Alt+VK_N press/release 2\n");
7464 keybd_event(VK_MENU
, 0, 0, 0);
7465 keybd_event('N', 0, 0, 0);
7466 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7467 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7468 pump_msg_loop(hwnd
, hAccel
);
7469 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
7471 trace("testing Ctrl+Alt+VK_N press/release 2\n");
7473 keybd_event(VK_CONTROL
, 0, 0, 0);
7474 keybd_event(VK_MENU
, 0, 0, 0);
7475 keybd_event('N', 0, 0, 0);
7476 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7477 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7478 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7479 pump_msg_loop(hwnd
, hAccel
);
7480 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
7482 trace("testing Ctrl+Shift+VK_N press/release\n");
7484 keybd_event(VK_CONTROL
, 0, 0, 0);
7485 keybd_event(VK_SHIFT
, 0, 0, 0);
7486 keybd_event('N', 0, 0, 0);
7487 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7488 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7489 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7490 pump_msg_loop(hwnd
, hAccel
);
7491 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
7493 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
7495 keybd_event(VK_CONTROL
, 0, 0, 0);
7496 keybd_event(VK_MENU
, 0, 0, 0);
7497 keybd_event(VK_SHIFT
, 0, 0, 0);
7498 keybd_event('N', 0, 0, 0);
7499 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
7500 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7501 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7502 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
7503 pump_msg_loop(hwnd
, hAccel
);
7504 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
7506 ret
= DestroyAcceleratorTable(hAccel
);
7507 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
7510 trace("testing Alt press/release\n");
7512 keybd_event(VK_MENU
, 0, 0, 0);
7513 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7514 keybd_event(VK_MENU
, 0, 0, 0);
7515 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
7516 pump_msg_loop(hwnd
, 0);
7517 /* this test doesn't pass in Wine for managed windows */
7518 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
7520 trace("testing VK_F1 press/release\n");
7521 keybd_event(VK_F1
, 0, 0, 0);
7522 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
7523 pump_msg_loop(hwnd
, 0);
7524 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
7526 trace("testing VK_APPS press/release\n");
7527 keybd_event(VK_APPS
, 0, 0, 0);
7528 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
7529 pump_msg_loop(hwnd
, 0);
7530 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
7532 trace("testing VK_F10 press/release\n");
7533 keybd_event(VK_F10
, 0, 0, 0);
7534 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
7535 keybd_event(VK_F10
, 0, 0, 0);
7536 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
7537 pump_msg_loop(hwnd
, 0);
7538 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", TRUE
);
7540 trace("testing SHIFT+F10 press/release\n");
7541 keybd_event(VK_SHIFT
, 0, 0, 0);
7542 keybd_event(VK_F10
, 0, 0, 0);
7543 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
7544 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7545 keybd_event(VK_ESCAPE
, 0, 0, 0);
7546 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
7547 pump_msg_loop(hwnd
, 0);
7548 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
7550 trace("testing Shift+MouseButton press/release\n");
7551 /* first, move mouse pointer inside of the window client area */
7552 GetClientRect(hwnd
, &rc
);
7553 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
7554 rc
.left
+= (rc
.right
- rc
.left
)/2;
7555 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
7556 SetCursorPos(rc
.left
, rc
.top
);
7557 SetActiveWindow(hwnd
);
7562 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
7565 keybd_event(VK_SHIFT
, 0, 0, 0);
7566 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
7567 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
7568 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
7569 pump_msg_loop(hwnd
, 0);
7570 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
7571 if (i
< sequence_cnt
)
7572 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
7574 skip( "Shift+MouseButton event didn't get to the window\n" );
7578 if (hAccel
) DestroyAcceleratorTable(hAccel
);
7579 DestroyWindow(hwnd
);
7582 /************* window procedures ********************/
7584 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
7585 WPARAM wParam
, LPARAM lParam
)
7587 static LONG defwndproc_counter
= 0;
7588 static LONG beginpaint_counter
= 0;
7590 struct recvd_message msg
;
7592 if (ignore_message( message
)) return 0;
7598 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7599 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
7600 "wrong WS_DISABLED state: %ld != %d\n", wParam
, !(style
& WS_DISABLED
));
7604 case WM_CAPTURECHANGED
:
7605 if (test_DestroyWindow_flag
)
7607 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7608 if (style
& WS_CHILD
)
7609 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
7610 else if (style
& WS_POPUP
)
7611 lParam
= WND_POPUP_ID
;
7613 lParam
= WND_PARENT_ID
;
7621 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
7622 capture
= GetCapture();
7625 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
7626 trace("current capture %p, releasing...\n", capture
);
7633 ok(pGetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
7634 if (test_DestroyWindow_flag
)
7636 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7637 if (style
& WS_CHILD
)
7638 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
7639 else if (style
& WS_POPUP
)
7640 lParam
= WND_POPUP_ID
;
7642 lParam
= WND_PARENT_ID
;
7646 /* test_accelerators() depends on this */
7652 HANDLE handle
, event
= (HANDLE
)lParam
;
7655 handle
= (void*)0xdeadbeef;
7656 ret
= pGetCurrentActCtx(&handle
);
7657 ok(ret
, "failed to get current context, %u\n", GetLastError());
7658 ok(handle
== 0, "got active context %p\n", handle
);
7659 if (event
) SetEvent(event
);
7665 case WM_MOUSEACTIVATE
:
7666 case WM_NCMOUSEMOVE
:
7673 msg
.message
= message
;
7674 msg
.flags
= sent
|wparam
|lparam
;
7675 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7676 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
7677 msg
.wParam
= wParam
;
7678 msg
.lParam
= lParam
;
7679 msg
.descr
= "MsgCheckProc";
7682 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
7684 HWND parent
= GetParent(hwnd
);
7686 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
7688 GetClientRect(parent
, &rc
);
7689 trace("parent %p client size = (%d x %d)\n", parent
, rc
.right
, rc
.bottom
);
7690 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
7691 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
7692 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
7693 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
7694 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
7695 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
7697 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %d != %d\n",
7698 minmax
->ptMaxSize
.x
, rc
.right
);
7699 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %d != %d\n",
7700 minmax
->ptMaxSize
.y
, rc
.bottom
);
7703 if (message
== WM_PAINT
)
7706 beginpaint_counter
++;
7707 BeginPaint( hwnd
, &ps
);
7708 beginpaint_counter
--;
7709 EndPaint( hwnd
, &ps
);
7713 defwndproc_counter
++;
7714 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
7715 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7716 defwndproc_counter
--;
7721 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7723 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
7726 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7728 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
7731 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7733 static LONG defwndproc_counter
= 0;
7735 struct recvd_message msg
;
7737 if (ignore_message( message
)) return 0;
7741 case WM_QUERYENDSESSION
:
7743 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
7748 msg
.message
= message
;
7749 msg
.flags
= sent
|wparam
|lparam
;
7750 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7751 msg
.wParam
= wParam
;
7752 msg
.lParam
= lParam
;
7753 msg
.descr
= "popup";
7756 if (message
== WM_CREATE
)
7758 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
7759 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
7762 defwndproc_counter
++;
7763 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7764 defwndproc_counter
--;
7769 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7771 static LONG defwndproc_counter
= 0;
7772 static LONG beginpaint_counter
= 0;
7774 struct recvd_message msg
;
7776 if (ignore_message( message
)) return 0;
7778 if (log_all_parent_messages
||
7779 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
7780 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
7781 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
7782 message
== WM_DRAWITEM
|| message
== WM_COMMAND
||
7783 message
== WM_IME_SETCONTEXT
)
7792 case WM_NCMOUSEMOVE
:
7798 INT ret
= GetClipBox((HDC
)wParam
, &rc
);
7800 trace("WM_ERASEBKGND: GetClipBox()=%d, (%d,%d-%d,%d)\n",
7801 ret
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
7807 msg
.message
= message
;
7808 msg
.flags
= sent
|parent
|wparam
|lparam
;
7809 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7810 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
7811 msg
.wParam
= wParam
;
7812 msg
.lParam
= lParam
;
7813 msg
.descr
= "parent";
7817 if (message
== WM_PAINT
)
7820 beginpaint_counter
++;
7821 BeginPaint( hwnd
, &ps
);
7822 beginpaint_counter
--;
7823 EndPaint( hwnd
, &ps
);
7827 defwndproc_counter
++;
7828 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7829 defwndproc_counter
--;
7834 static INT_PTR CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
7836 if (message
== WM_CREATE
)
7837 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
7838 else if (message
== WM_CLOSE
)
7840 /* Only the first WM_QUIT will survive the window destruction */
7841 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
7842 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
7843 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
7846 return DefWindowProcA(hwnd
, message
, wp
, lp
);
7849 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7851 static LONG defwndproc_counter
= 0;
7853 struct recvd_message msg
;
7855 if (ignore_message( message
)) return 0;
7859 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
7860 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
7861 if (after_end_dialog
)
7862 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
7864 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
7868 msg
.message
= message
;
7869 msg
.flags
= sent
|wparam
|lparam
;
7870 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7871 msg
.wParam
= wParam
;
7872 msg
.lParam
= lParam
;
7873 msg
.descr
= "dialog";
7876 defwndproc_counter
++;
7877 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
7878 defwndproc_counter
--;
7883 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7885 static LONG defwndproc_counter
= 0;
7887 struct recvd_message msg
;
7889 /* log only specific messages we are interested in */
7892 #if 0 /* probably log these as well */
7900 case WM_GETMINMAXINFO
:
7901 case WM_WINDOWPOSCHANGING
:
7902 case WM_WINDOWPOSCHANGED
:
7905 default: /* ignore */
7906 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
7907 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7911 msg
.message
= message
;
7912 msg
.flags
= sent
|wparam
|lparam
;
7913 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7914 msg
.wParam
= wParam
;
7915 msg
.lParam
= lParam
;
7919 defwndproc_counter
++;
7920 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7921 defwndproc_counter
--;
7926 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
7930 case WM_CREATE
: return 0;
7939 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
7941 TranslateMessage(&msg2
);
7942 DispatchMessageA(&msg2
);
7946 else ok(broken(1), "infinite loop\n");
7948 paint_loop_done
= TRUE
;
7949 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
7952 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
7955 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7957 static LONG defwndproc_counter
= 0;
7959 struct recvd_message msg
;
7962 if (ignore_message( message
)) return 0;
7964 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
7965 message
== WM_HOTKEY
|| message
>= WM_APP
)
7968 msg
.message
= message
;
7969 msg
.flags
= sent
|wparam
|lparam
;
7970 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7971 msg
.wParam
= wParam
;
7972 msg
.lParam
= lParam
;
7973 msg
.descr
= "HotkeyMsgCheckProcA";
7977 defwndproc_counter
++;
7978 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
7979 defwndproc_counter
--;
7981 if (message
== WM_APP
)
7983 queue_status
= GetQueueStatus(QS_HOTKEY
);
7984 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
7985 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
7986 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
7987 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
7989 else if (message
== WM_APP
+1)
7991 queue_status
= GetQueueStatus(QS_HOTKEY
);
7992 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
7998 static BOOL
RegisterWindowClasses(void)
8004 cls
.lpfnWndProc
= MsgCheckProcA
;
8007 cls
.hInstance
= GetModuleHandleA(0);
8009 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
8010 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
8011 cls
.lpszMenuName
= NULL
;
8012 cls
.lpszClassName
= "TestWindowClass";
8013 if(!RegisterClassA(&cls
)) return FALSE
;
8015 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
8016 cls
.lpszClassName
= "HotkeyWindowClass";
8017 if(!RegisterClassA(&cls
)) return FALSE
;
8019 cls
.lpfnWndProc
= ShowWindowProcA
;
8020 cls
.lpszClassName
= "ShowWindowClass";
8021 if(!RegisterClassA(&cls
)) return FALSE
;
8023 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
8024 cls
.lpszClassName
= "TestPopupClass";
8025 if(!RegisterClassA(&cls
)) return FALSE
;
8027 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
8028 cls
.lpszClassName
= "TestParentClass";
8029 if(!RegisterClassA(&cls
)) return FALSE
;
8031 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
8032 cls
.lpszClassName
= "StopQuitClass";
8033 if(!RegisterClassA(&cls
)) return FALSE
;
8035 cls
.lpfnWndProc
= DefWindowProcA
;
8036 cls
.lpszClassName
= "SimpleWindowClass";
8037 if(!RegisterClassA(&cls
)) return FALSE
;
8039 cls
.lpfnWndProc
= PaintLoopProcA
;
8040 cls
.lpszClassName
= "PaintLoopWindowClass";
8041 if(!RegisterClassA(&cls
)) return FALSE
;
8043 cls
.style
= CS_NOCLOSE
;
8044 cls
.lpszClassName
= "NoCloseWindowClass";
8045 if(!RegisterClassA(&cls
)) return FALSE
;
8047 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
8049 cls
.hInstance
= GetModuleHandleA(0);
8050 cls
.hbrBackground
= 0;
8051 cls
.lpfnWndProc
= TestDlgProcA
;
8052 cls
.lpszClassName
= "TestDialogClass";
8053 if(!RegisterClassA(&cls
)) return FALSE
;
8056 clsW
.lpfnWndProc
= MsgCheckProcW
;
8057 clsW
.cbClsExtra
= 0;
8058 clsW
.cbWndExtra
= 0;
8059 clsW
.hInstance
= GetModuleHandleW(0);
8061 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
8062 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
8063 clsW
.lpszMenuName
= NULL
;
8064 clsW
.lpszClassName
= testWindowClassW
;
8065 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
8070 static BOOL
is_our_logged_class(HWND hwnd
)
8074 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
8076 if (!lstrcmpiA(buf
, "TestWindowClass") ||
8077 !lstrcmpiA(buf
, "ShowWindowClass") ||
8078 !lstrcmpiA(buf
, "TestParentClass") ||
8079 !lstrcmpiA(buf
, "TestPopupClass") ||
8080 !lstrcmpiA(buf
, "SimpleWindowClass") ||
8081 !lstrcmpiA(buf
, "TestDialogClass") ||
8082 !lstrcmpiA(buf
, "MDI_frame_class") ||
8083 !lstrcmpiA(buf
, "MDI_client_class") ||
8084 !lstrcmpiA(buf
, "MDI_child_class") ||
8085 !lstrcmpiA(buf
, "my_button_class") ||
8086 !lstrcmpiA(buf
, "my_edit_class") ||
8087 !lstrcmpiA(buf
, "static") ||
8088 !lstrcmpiA(buf
, "ListBox") ||
8089 !lstrcmpiA(buf
, "ComboBox") ||
8090 !lstrcmpiA(buf
, "MyDialogClass") ||
8091 !lstrcmpiA(buf
, "#32770") ||
8092 !lstrcmpiA(buf
, "#32768"))
8098 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
8102 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
8104 if (nCode
== HCBT_CLICKSKIPPED
)
8106 /* ignore this event, XP sends it a lot when switching focus between windows */
8107 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
8110 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
8112 struct recvd_message msg
;
8115 msg
.message
= nCode
;
8116 msg
.flags
= hook
|wparam
|lparam
;
8117 msg
.wParam
= wParam
;
8118 msg
.lParam
= lParam
;
8122 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
8125 if (nCode
== HCBT_DESTROYWND
)
8127 if (test_DestroyWindow_flag
)
8129 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
8130 if (style
& WS_CHILD
)
8131 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
8132 else if (style
& WS_POPUP
)
8133 lParam
= WND_POPUP_ID
;
8135 lParam
= WND_PARENT_ID
;
8139 /* Log also SetFocus(0) calls */
8140 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
8142 if (is_our_logged_class(hwnd
))
8144 struct recvd_message msg
;
8147 msg
.message
= nCode
;
8148 msg
.flags
= hook
|wparam
|lparam
;
8149 msg
.wParam
= wParam
;
8150 msg
.lParam
= lParam
;
8154 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
8157 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
8165 ok(thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
8167 /* ignore mouse cursor events */
8168 if (object_id
== OBJID_CURSOR
) return;
8170 if (!hwnd
|| is_our_logged_class(hwnd
))
8172 struct recvd_message msg
;
8175 msg
.message
= event
;
8176 msg
.flags
= winevent_hook
|wparam
|lparam
;
8177 msg
.wParam
= object_id
;
8178 msg
.lParam
= child_id
;
8184 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
8185 static const WCHAR wszAnsi
[] = {'U',0};
8187 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
8191 case CB_FINDSTRINGEXACT
:
8192 trace("String: %p\n", (LPCWSTR
)lParam
);
8193 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
8195 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
8199 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
8202 static const struct message WmGetTextLengthAfromW
[] = {
8203 { WM_GETTEXTLENGTH
, sent
},
8204 { WM_GETTEXT
, sent
|optional
},
8208 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
8210 /* dummy window proc for WM_GETTEXTLENGTH test */
8211 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
8215 case WM_GETTEXTLENGTH
:
8216 return lstrlenW(dummy_window_text
) + 37; /* some random length */
8218 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
8219 return lstrlenW( (LPWSTR
)lp
);
8221 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
8225 static void test_message_conversion(void)
8227 static const WCHAR wszMsgConversionClass
[] =
8228 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
8232 WNDPROC wndproc
, newproc
;
8236 cls
.lpfnWndProc
= MsgConversionProcW
;
8239 cls
.hInstance
= GetModuleHandleW(NULL
);
8241 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
8242 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
8243 cls
.lpszMenuName
= NULL
;
8244 cls
.lpszClassName
= wszMsgConversionClass
;
8245 /* this call will fail on Win9x, but that doesn't matter as this test is
8246 * meaningless on those platforms */
8247 if(!RegisterClassW(&cls
)) return;
8249 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
8250 100, 100, 200, 200, 0, 0, 0, NULL
);
8251 ok(hwnd
!= NULL
, "Window creation failed\n");
8255 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
8256 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8257 ok(lRes
== 0, "String should have been converted\n");
8258 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8259 ok(lRes
== 1, "String shouldn't have been converted\n");
8263 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
8264 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8265 ok(lRes
== 1, "String shouldn't have been converted\n");
8266 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8267 ok(lRes
== 1, "String shouldn't have been converted\n");
8269 /* Synchronous messages */
8271 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8272 ok(lRes
== 0, "String should have been converted\n");
8273 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8274 ok(lRes
== 1, "String shouldn't have been converted\n");
8276 /* Asynchronous messages */
8279 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8280 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8281 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8283 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8284 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8285 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8287 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8288 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8289 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8291 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8292 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8293 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8295 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8296 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8297 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8299 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
8300 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8301 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8303 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
8304 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8305 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8307 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
8308 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
8309 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
8311 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
8313 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
8314 WS_OVERLAPPEDWINDOW
,
8315 100, 100, 200, 200, 0, 0, 0, NULL
);
8318 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
8319 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
8320 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
8321 "got bad length %ld\n", lRes
);
8324 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
8325 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
8326 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
8327 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
8328 "got bad length %ld\n", lRes
);
8330 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
8331 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
8332 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
8333 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
8334 NULL
, 0, NULL
, NULL
) ||
8335 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
8336 "got bad length %ld\n", lRes
);
8338 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
8339 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
8340 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
8341 NULL
, 0, NULL
, NULL
) ||
8342 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
8343 "got bad length %ld\n", lRes
);
8345 ret
= DestroyWindow(hwnd
);
8346 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
8356 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
8360 #define TIMER_ID 0x19
8361 #define TIMER_COUNT_EXPECTED 100
8362 #define TIMER_COUNT_TOLERANCE 10
8364 static int count
= 0;
8365 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
8370 static DWORD exception
;
8371 static void CALLBACK
callback_exception(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
8374 RaiseException(exception
, 0, 0, NULL
);
8377 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
8379 struct timer_info
*info
= x
;
8382 r
= KillTimer(info
->hWnd
, 0x19);
8383 ok(r
,"KillTimer failed in thread\n");
8384 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
8385 ok(r
,"SetTimer failed in thread\n");
8386 ok(r
==TIMER_ID
,"SetTimer id different\n");
8387 r
= SetEvent(info
->handles
[0]);
8388 ok(r
,"SetEvent failed in thread\n");
8392 static void test_timers(void)
8394 struct timer_info info
;
8399 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
8400 WS_OVERLAPPEDWINDOW
,
8401 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
8404 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
8405 ok(info
.id
, "SetTimer failed\n");
8406 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
8407 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
8408 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
8410 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
8412 WaitForSingleObject(info
.handles
[1], INFINITE
);
8414 CloseHandle(info
.handles
[0]);
8415 CloseHandle(info
.handles
[1]);
8417 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
8419 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
8420 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
8421 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
8422 * ±9 counts (~4 ms) around the expected value.
8425 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
8426 ok(id
!= 0, "did not get id from SetTimer.\n");
8427 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
8428 start
= GetTickCount();
8429 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
8430 DispatchMessageA(&msg
);
8431 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
8432 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
8433 || broken(abs(count
-43) < TIMER_COUNT_TOLERANCE
) /* w2k3, win8 */,
8434 "did not get expected count for minimum timeout (%d != ~%d).\n",
8435 count
, TIMER_COUNT_EXPECTED
);
8436 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
8437 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
8438 if (pSetSystemTimer
)
8443 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
8444 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
8445 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
8446 start
= GetTickCount();
8447 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
8449 if (msg
.message
== WM_SYSTIMER
)
8451 DispatchMessageA(&msg
);
8453 ok(abs(syscount
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
8454 || broken(abs(syscount
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
8455 || broken(syscount
> 4000 && syscount
< 12000) /* win2k3sp0 */,
8456 "did not get expected count for minimum timeout (%d != ~%d).\n",
8457 syscount
, TIMER_COUNT_EXPECTED
);
8458 todo_wine
ok(count
== 0, "did not get expected count for callback timeout (%d != 0).\n",
8460 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
8463 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
8466 static void test_timers_no_wnd(void)
8473 id
= SetTimer(NULL
, 0, 100, callback_count
);
8474 ok(id
!= 0, "did not get id from SetTimer.\n");
8475 id2
= SetTimer(NULL
, id
, 200, callback_count
);
8476 ok(id2
== id
, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2
, id
);
8478 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8479 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
8481 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8482 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
8483 KillTimer(NULL
, id
);
8485 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
8486 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
8488 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
8489 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
8490 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
8491 * ±9 counts (~4 ms) around the expected value.
8494 id
= SetTimer(NULL
, 0, 0, callback_count
);
8495 ok(id
!= 0, "did not get id from SetTimer.\n");
8496 start
= GetTickCount();
8497 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, NULL
, 0, 0))
8498 DispatchMessageA(&msg
);
8499 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
8500 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */,
8501 "did not get expected count for minimum timeout (%d != ~%d).\n",
8502 count
, TIMER_COUNT_EXPECTED
);
8503 KillTimer(NULL
, id
);
8504 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
8507 static void test_timers_exception(DWORD code
)
8513 id
= SetTimer(NULL
, 0, 1000, callback_exception
);
8514 ok(id
!= 0, "did not get id from SetTimer.\n");
8516 memset(&msg
, 0, sizeof(msg
));
8517 msg
.message
= WM_TIMER
;
8519 msg
.lParam
= (LPARAM
)callback_exception
;
8522 DispatchMessageA(&msg
);
8523 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
8525 KillTimer(NULL
, id
);
8528 static void test_timers_exceptions(void)
8530 test_timers_exception(EXCEPTION_ACCESS_VIOLATION
);
8531 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT
);
8532 test_timers_exception(EXCEPTION_BREAKPOINT
);
8533 test_timers_exception(EXCEPTION_SINGLE_STEP
);
8534 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED
);
8535 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND
);
8536 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO
);
8537 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT
);
8538 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION
);
8539 test_timers_exception(0xE000BEEF); /* customer exception */
8542 /* Various win events with arbitrary parameters */
8543 static const struct message WmWinEventsSeq
[] = {
8544 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
8545 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8546 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
8547 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
8548 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
8549 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
8550 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
8551 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
8552 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
8553 /* our win event hook ignores OBJID_CURSOR events */
8554 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
8555 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
8556 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
8557 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
8558 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
8559 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
8560 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8561 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
8562 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
8563 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
8564 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
8565 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
8566 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
8567 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
8570 static const struct message WmWinEventCaretSeq
[] = {
8571 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
8572 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
8573 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
8574 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
8577 static const struct message WmWinEventCaretSeq_2
[] = {
8578 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
8579 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
8580 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
8583 static const struct message WmWinEventAlertSeq
[] = {
8584 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
8587 static const struct message WmWinEventAlertSeq_2
[] = {
8588 /* create window in the thread proc */
8589 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
8590 /* our test event */
8591 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
8594 static const struct message WmGlobalHookSeq_1
[] = {
8595 /* create window in the thread proc */
8596 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
8597 /* our test events */
8598 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
8599 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
8602 static const struct message WmGlobalHookSeq_2
[] = {
8603 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
8604 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
8605 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
8606 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
8610 static const struct message WmMouseLLHookSeq
[] = {
8611 { WM_MOUSEMOVE
, hook
},
8612 { WM_LBUTTONUP
, hook
},
8613 { WM_MOUSEMOVE
, hook
},
8617 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
8627 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
8629 if (!lstrcmpiA(buf
, "TestWindowClass") ||
8630 !lstrcmpiA(buf
, "static"))
8632 struct recvd_message msg
;
8635 msg
.message
= event
;
8636 msg
.flags
= winevent_hook
|wparam
|lparam
;
8637 msg
.wParam
= object_id
;
8638 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
8639 msg
.descr
= "WEH_2";
8645 static HHOOK hCBT_global_hook
;
8646 static DWORD cbt_global_hook_thread_id
;
8648 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
8653 if (nCode
== HCBT_SYSCOMMAND
)
8655 struct recvd_message msg
;
8658 msg
.message
= nCode
;
8659 msg
.flags
= hook
|wparam
|lparam
;
8660 msg
.wParam
= wParam
;
8661 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
8662 msg
.descr
= "CBT_2";
8665 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
8667 /* WH_MOUSE_LL hook */
8668 if (nCode
== HC_ACTION
)
8670 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
8672 /* we can't test for real mouse events */
8673 if (mhll
->flags
& LLMHF_INJECTED
)
8675 struct recvd_message msg
;
8677 memset (&msg
, 0, sizeof (msg
));
8678 msg
.message
= wParam
;
8680 msg
.descr
= "CBT_2";
8683 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
8686 /* Log also SetFocus(0) calls */
8687 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
8689 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
8691 if (!lstrcmpiA(buf
, "TestWindowClass") ||
8692 !lstrcmpiA(buf
, "static"))
8694 struct recvd_message msg
;
8697 msg
.message
= nCode
;
8698 msg
.flags
= hook
|wparam
|lparam
;
8699 msg
.wParam
= wParam
;
8700 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
8701 msg
.descr
= "CBT_2";
8705 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
8708 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
8712 HANDLE hevent
= *(HANDLE
*)param
;
8714 assert(pNotifyWinEvent
);
8716 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
8718 trace("created thread window %p\n", hwnd
);
8720 *(HWND
*)param
= hwnd
;
8723 /* this event should be received only by our new hook proc,
8724 * an old one does not expect an event from another thread.
8726 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
8729 while (GetMessageA(&msg
, 0, 0, 0))
8731 TranslateMessage(&msg
);
8732 DispatchMessageA(&msg
);
8737 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
8741 HANDLE hevent
= *(HANDLE
*)param
;
8744 /* these events should be received only by our new hook proc,
8745 * an old one does not expect an event from another thread.
8748 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
8750 trace("created thread window %p\n", hwnd
);
8752 *(HWND
*)param
= hwnd
;
8754 /* Windows doesn't like when a thread plays games with the focus,
8755 that leads to all kinds of misbehaviours and failures to activate
8756 a window. So, better keep next lines commented out.
8760 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
8761 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
8765 while (GetMessageA(&msg
, 0, 0, 0))
8767 TranslateMessage(&msg
);
8768 DispatchMessageA(&msg
);
8773 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
8777 HANDLE hevent
= *(HANDLE
*)param
;
8779 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
8781 trace("created thread window %p\n", hwnd
);
8783 *(HWND
*)param
= hwnd
;
8787 /* Windows doesn't like when a thread plays games with the focus,
8788 * that leads to all kinds of misbehaviours and failures to activate
8789 * a window. So, better don't generate a mouse click message below.
8791 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
8792 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
8793 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
8796 while (GetMessageA(&msg
, 0, 0, 0))
8798 TranslateMessage(&msg
);
8799 DispatchMessageA(&msg
);
8804 static void test_winevents(void)
8810 HANDLE hthread
, hevent
;
8812 HWINEVENTHOOK hhook
;
8813 const struct message
*events
= WmWinEventsSeq
;
8815 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
8816 WS_OVERLAPPEDWINDOW
,
8817 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
8821 /****** start of global hook test *************/
8822 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
8823 if (!hCBT_global_hook
)
8825 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
8826 skip( "cannot set global hook\n" );
8830 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8834 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
8835 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8837 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8839 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
8842 /* this one should be received only by old hook proc */
8843 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
8844 /* this one should be received only by old hook proc */
8845 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
8847 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
8849 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
8850 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
8852 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8853 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8854 CloseHandle(hthread
);
8855 CloseHandle(hevent
);
8856 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
8857 /****** end of global hook test *************/
8859 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
8861 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
8869 /* this test doesn't pass under Win9x */
8870 /* win2k ignores events with hwnd == 0 */
8871 SetLastError(0xdeadbeef);
8872 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
8873 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
8874 GetLastError() == 0xdeadbeef, /* Win9x */
8875 "unexpected error %d\n", GetLastError());
8876 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
8879 for (i
= 0; i
< sizeof(WmWinEventsSeq
)/sizeof(WmWinEventsSeq
[0]); i
++)
8880 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
8882 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
8884 /****** start of event filtering test *************/
8885 hhook
= pSetWinEventHook(
8886 EVENT_OBJECT_SHOW
, /* 0x8002 */
8887 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
8888 GetModuleHandleA(0), win_event_global_hook_proc
,
8889 GetCurrentProcessId(), 0,
8890 WINEVENT_INCONTEXT
);
8891 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
8893 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8897 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
8898 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8900 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8902 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
8905 /* this one should be received only by old hook proc */
8906 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
8907 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
8908 /* this one should be received only by old hook proc */
8909 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
8911 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
8913 ret
= pUnhookWinEvent(hhook
);
8914 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
8916 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8917 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8918 CloseHandle(hthread
);
8919 CloseHandle(hevent
);
8920 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
8921 /****** end of event filtering test *************/
8923 /****** start of out of context event test *************/
8924 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
8925 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
8926 WINEVENT_OUTOFCONTEXT
);
8927 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
8929 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8935 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
8936 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8938 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8940 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
8941 /* process pending winevent messages */
8942 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
8943 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
8946 /* this one should be received only by old hook proc */
8947 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
8948 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
8949 /* this one should be received only by old hook proc */
8950 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
8952 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
8953 /* process pending winevent messages */
8954 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
8955 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
8957 ret
= pUnhookWinEvent(hhook
);
8958 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
8960 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8961 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
8962 CloseHandle(hthread
);
8963 CloseHandle(hevent
);
8964 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
8965 /****** end of out of context event test *************/
8967 /****** start of MOUSE_LL hook test *************/
8968 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
8969 /* WH_MOUSE_LL is not supported on Win9x platforms */
8970 if (!hCBT_global_hook
)
8972 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
8973 goto skip_mouse_ll_hook_test
;
8976 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
8980 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
8981 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
8983 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
8984 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8986 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
8989 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
8990 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
8991 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
8993 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
8995 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
8996 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
8998 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
8999 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9000 CloseHandle(hthread
);
9001 CloseHandle(hevent
);
9002 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
9003 /****** end of MOUSE_LL hook test *************/
9004 skip_mouse_ll_hook_test
:
9006 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
9009 static void test_set_hook(void)
9013 HWINEVENTHOOK hwinevent_hook
;
9015 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
9016 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
9017 UnhookWindowsHookEx(hhook
);
9021 /* this test doesn't pass under Win9x: BUG! */
9022 SetLastError(0xdeadbeef);
9023 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
9024 ok(!hhook
, "global hook requires hModule != 0\n");
9025 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %d\n", GetLastError());
9028 SetLastError(0xdeadbeef);
9029 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
9030 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
9031 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
|| /* Win2k */
9032 GetLastError() == 0xdeadbeef, /* Win9x */
9033 "unexpected error %d\n", GetLastError());
9035 SetLastError(0xdeadbeef);
9036 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
9037 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
|| /* Win2k */
9038 GetLastError() == 0xdeadbeef, /* Win9x */
9039 "unexpected error %d\n", GetLastError());
9041 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
9043 /* even process local incontext hooks require hmodule */
9044 SetLastError(0xdeadbeef);
9045 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9046 GetCurrentProcessId(), 0, 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());
9052 /* even thread local incontext hooks require hmodule */
9053 SetLastError(0xdeadbeef);
9054 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9055 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
9056 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
9057 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
9058 GetLastError() == 0xdeadbeef, /* Win9x */
9059 "unexpected error %d\n", GetLastError());
9063 /* these 3 tests don't pass under Win9x */
9064 SetLastError(0xdeadbeef);
9065 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
9066 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
9067 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
9068 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
9070 SetLastError(0xdeadbeef);
9071 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
9072 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
9073 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
9074 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
9076 SetLastError(0xdeadbeef);
9077 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9078 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
9079 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
9080 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %d\n", GetLastError());
9083 SetLastError(0xdeadbeef);
9084 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
9085 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
9086 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
9087 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
9088 ret
= pUnhookWinEvent(hwinevent_hook
);
9089 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
9092 /* This call succeeds under win2k SP4, but fails under Wine.
9093 Does win2k test/use passed process id? */
9094 SetLastError(0xdeadbeef);
9095 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
9096 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
9097 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
9098 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
9099 ret
= pUnhookWinEvent(hwinevent_hook
);
9100 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
9103 SetLastError(0xdeadbeef);
9104 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
9105 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
9106 GetLastError() == 0xdeadbeef, /* Win9x */
9107 "unexpected error %d\n", GetLastError());
9110 static const struct message ScrollWindowPaint1
[] = {
9112 { WM_ERASEBKGND
, sent
|beginpaint
},
9113 { WM_GETTEXTLENGTH
, sent
|optional
},
9114 { WM_PAINT
, sent
|optional
},
9115 { WM_NCPAINT
, sent
|beginpaint
|optional
},
9116 { WM_GETTEXT
, sent
|beginpaint
|optional
},
9117 { WM_GETTEXT
, sent
|beginpaint
|optional
},
9118 { WM_GETTEXT
, sent
|beginpaint
|optional
},
9119 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
9120 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
9124 static const struct message ScrollWindowPaint2
[] = {
9129 static void test_scrollwindowex(void)
9132 RECT rect
={0,0,130,130};
9134 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
9135 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
9136 100, 100, 200, 200, 0, 0, 0, NULL
);
9137 ok (hwnd
!= 0, "Failed to create overlapped window\n");
9138 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
9139 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
9140 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
9141 ok (hchild
!= 0, "Failed to create child\n");
9146 /* scroll without the child window */
9147 trace("start scroll\n");
9148 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
9149 SW_ERASE
|SW_INVALIDATE
);
9150 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
9151 trace("end scroll\n");
9154 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
9158 /* Now without the SW_ERASE flag */
9159 trace("start scroll\n");
9160 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
9161 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
9162 trace("end scroll\n");
9165 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
9169 /* now scroll the child window as well */
9170 trace("start scroll\n");
9171 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
9172 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
9173 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
9174 /* windows sometimes a WM_MOVE */
9175 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
9176 trace("end scroll\n");
9179 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
9183 /* now scroll with ScrollWindow() */
9184 trace("start scroll with ScrollWindow\n");
9185 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
9186 trace("end scroll\n");
9189 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
9191 ok(DestroyWindow(hchild
), "failed to destroy window\n");
9192 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
9196 static const struct message destroy_window_with_children
[] = {
9197 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
9198 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
9199 { 0x0090, sent
|optional
},
9200 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9201 { 0x0090, sent
|optional
},
9202 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
9203 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9204 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9205 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
9206 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* parent */
9207 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
9208 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
9209 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
9210 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
9211 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
9212 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
9213 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
9214 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
9218 static void test_DestroyWindow(void)
9221 HWND parent
, child1
, child2
, child3
, child4
, test
;
9222 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
9224 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9225 100, 100, 200, 200, 0, 0, 0, NULL
);
9226 assert(parent
!= 0);
9227 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
9228 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
9229 assert(child1
!= 0);
9230 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
9231 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
9232 assert(child2
!= 0);
9233 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
9234 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
9235 assert(child3
!= 0);
9236 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
9237 0, 0, 50, 50, parent
, 0, 0, NULL
);
9238 assert(child4
!= 0);
9240 /* test owner/parent of child2 */
9241 test
= GetParent(child2
);
9242 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9243 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
9245 test
= pGetAncestor(child2
, GA_PARENT
);
9246 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9248 test
= GetWindow(child2
, GW_OWNER
);
9249 ok(!test
, "wrong owner %p\n", test
);
9251 test
= SetParent(child2
, parent
);
9252 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
9254 /* test owner/parent of the parent */
9255 test
= GetParent(parent
);
9256 ok(!test
, "wrong parent %p\n", test
);
9257 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
9259 test
= pGetAncestor(parent
, GA_PARENT
);
9260 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9262 test
= GetWindow(parent
, GW_OWNER
);
9263 ok(!test
, "wrong owner %p\n", test
);
9265 /* test owner/parent of child1 */
9266 test
= GetParent(child1
);
9267 ok(test
== parent
, "wrong parent %p\n", test
);
9268 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
9270 test
= pGetAncestor(child1
, GA_PARENT
);
9271 ok(test
== parent
, "wrong parent %p\n", test
);
9273 test
= GetWindow(child1
, GW_OWNER
);
9274 ok(!test
, "wrong owner %p\n", test
);
9276 /* test owner/parent of child2 */
9277 test
= GetParent(child2
);
9278 ok(test
== parent
, "wrong parent %p\n", test
);
9279 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
9281 test
= pGetAncestor(child2
, GA_PARENT
);
9282 ok(test
== parent
, "wrong parent %p\n", test
);
9284 test
= GetWindow(child2
, GW_OWNER
);
9285 ok(!test
, "wrong owner %p\n", test
);
9287 /* test owner/parent of child3 */
9288 test
= GetParent(child3
);
9289 ok(test
== child1
, "wrong parent %p\n", test
);
9290 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
9292 test
= pGetAncestor(child3
, GA_PARENT
);
9293 ok(test
== child1
, "wrong parent %p\n", test
);
9295 test
= GetWindow(child3
, GW_OWNER
);
9296 ok(!test
, "wrong owner %p\n", test
);
9298 /* test owner/parent of child4 */
9299 test
= GetParent(child4
);
9300 ok(test
== parent
, "wrong parent %p\n", test
);
9301 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
9303 test
= pGetAncestor(child4
, GA_PARENT
);
9304 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
9306 test
= GetWindow(child4
, GW_OWNER
);
9307 ok(test
== parent
, "wrong owner %p\n", test
);
9311 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
9312 parent
, child1
, child2
, child3
, child4
);
9315 test
= GetCapture();
9316 ok(test
== child4
, "wrong capture window %p\n", test
);
9318 test_DestroyWindow_flag
= TRUE
;
9319 ret
= DestroyWindow(parent
);
9320 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
9321 test_DestroyWindow_flag
= FALSE
;
9322 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
9324 ok(!IsWindow(parent
), "parent still exists\n");
9325 ok(!IsWindow(child1
), "child1 still exists\n");
9326 ok(!IsWindow(child2
), "child2 still exists\n");
9327 ok(!IsWindow(child3
), "child3 still exists\n");
9328 ok(!IsWindow(child4
), "child4 still exists\n");
9330 test
= GetCapture();
9331 ok(!test
, "wrong capture window %p\n", test
);
9335 static const struct message WmDispatchPaint
[] = {
9336 { WM_NCPAINT
, sent
},
9337 { WM_GETTEXT
, sent
|defwinproc
|optional
},
9338 { WM_GETTEXT
, sent
|defwinproc
|optional
},
9339 { WM_ERASEBKGND
, sent
},
9343 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9345 if (message
== WM_PAINT
) return 0;
9346 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
9349 static void test_DispatchMessage(void)
9354 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9355 100, 100, 200, 200, 0, 0, 0, NULL
);
9356 ShowWindow( hwnd
, SW_SHOW
);
9357 UpdateWindow( hwnd
);
9360 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
9362 SetRect( &rect
, -5, -5, 5, 5 );
9363 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9365 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9367 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
9371 DispatchMessageA( &msg
);
9372 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
9373 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
9374 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
9375 if (++count
> 10) break;
9378 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
9380 trace("now without DispatchMessage\n");
9382 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9384 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9386 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
9389 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
9391 /* this will send WM_NCCPAINT just like DispatchMessage does */
9392 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
9393 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
9394 DeleteObject( hrgn
);
9395 GetClientRect( hwnd
, &rect
);
9396 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
9397 ok( !count
, "Got multiple WM_PAINTs\n" );
9398 if (++count
> 10) break;
9403 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9405 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9407 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
9413 hdc
= BeginPaint( hwnd
, NULL
);
9414 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
9415 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
9416 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
9417 ok( !count
, "Got multiple WM_PAINTs\n" );
9418 if (++count
> 10) break;
9421 DestroyWindow(hwnd
);
9425 static const struct message WmUser
[] = {
9437 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
9439 struct sendmsg_info
*info
= arg
;
9440 SetLastError( 0xdeadbeef );
9441 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
9442 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
9443 broken(GetLastError() == 0), /* win9x */
9444 "unexpected error %d\n", GetLastError());
9448 static void wait_for_thread( HANDLE thread
)
9450 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
9453 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9457 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9459 if (message
== WM_USER
) Sleep(200);
9460 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
9463 static void test_SendMessageTimeout(void)
9466 struct sendmsg_info info
;
9470 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9471 100, 100, 200, 200, 0, 0, 0, NULL
);
9475 info
.timeout
= 1000;
9476 info
.ret
= 0xdeadbeef;
9477 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9478 wait_for_thread( thread
);
9479 CloseHandle( thread
);
9480 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
9481 ok_sequence( WmUser
, "WmUser", FALSE
);
9484 info
.ret
= 0xdeadbeef;
9485 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9486 Sleep(100); /* SendMessageTimeout should time out here */
9487 wait_for_thread( thread
);
9488 CloseHandle( thread
);
9489 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
9490 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
9492 /* 0 means infinite timeout (but not on win9x) */
9494 info
.ret
= 0xdeadbeef;
9495 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9497 wait_for_thread( thread
);
9498 CloseHandle( thread
);
9499 is_win9x
= !info
.ret
;
9500 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
9501 else ok_sequence( WmUser
, "WmUser", FALSE
);
9503 /* timeout is treated as signed despite the prototype (but not on win9x) */
9504 info
.timeout
= 0x7fffffff;
9505 info
.ret
= 0xdeadbeef;
9506 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9508 wait_for_thread( thread
);
9509 CloseHandle( thread
);
9510 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
9511 ok_sequence( WmUser
, "WmUser", FALSE
);
9513 info
.timeout
= 0x80000000;
9514 info
.ret
= 0xdeadbeef;
9515 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9517 wait_for_thread( thread
);
9518 CloseHandle( thread
);
9521 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
9522 ok_sequence( WmUser
, "WmUser", FALSE
);
9526 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
9527 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
9530 /* now check for timeout during message processing */
9531 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
9533 info
.ret
= 0xdeadbeef;
9534 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
9535 wait_for_thread( thread
);
9536 CloseHandle( thread
);
9537 /* we should time out but still get the message */
9538 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
9539 ok_sequence( WmUser
, "WmUser", FALSE
);
9541 DestroyWindow( info
.hwnd
);
9545 /****************** edit message test *************************/
9546 #define ID_EDIT 0x1234
9547 static const struct message sl_edit_setfocus
[] =
9549 { HCBT_SETFOCUS
, hook
},
9550 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
9551 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9552 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9553 { WM_SETFOCUS
, sent
|wparam
, 0 },
9554 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9555 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
9556 { WM_CTLCOLOREDIT
, sent
|parent
},
9557 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9558 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9559 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9560 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9563 static const struct message sl_edit_invisible
[] =
9565 { HCBT_SETFOCUS
, hook
},
9566 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
9567 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9568 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9569 { WM_KILLFOCUS
, sent
|parent
},
9570 { WM_SETFOCUS
, sent
},
9571 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9574 static const struct message ml_edit_setfocus
[] =
9576 { HCBT_SETFOCUS
, hook
},
9577 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
9578 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9579 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9580 { WM_SETFOCUS
, sent
|wparam
, 0 },
9581 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9582 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9583 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9584 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9585 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9588 static const struct message sl_edit_killfocus
[] =
9590 { HCBT_SETFOCUS
, hook
},
9591 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9592 { WM_KILLFOCUS
, sent
|wparam
, 0 },
9593 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9594 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9595 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
9596 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
9597 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
9600 static const struct message sl_edit_lbutton_dblclk
[] =
9602 { WM_LBUTTONDBLCLK
, sent
},
9603 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
9606 static const struct message sl_edit_lbutton_down
[] =
9608 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
9609 { HCBT_SETFOCUS
, hook
},
9610 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
9611 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9612 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9613 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
9614 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9615 { WM_CTLCOLOREDIT
, sent
|parent
},
9616 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9617 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9618 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9619 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9620 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9621 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
9622 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9623 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
9624 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9625 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9626 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9629 static const struct message ml_edit_lbutton_down
[] =
9631 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
9632 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
9633 { HCBT_SETFOCUS
, hook
},
9634 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
9635 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
9636 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
9637 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
9638 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
9639 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
9640 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9641 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9642 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
9645 static const struct message sl_edit_lbutton_up
[] =
9647 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
9648 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9649 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
9650 { WM_CAPTURECHANGED
, sent
|defwinproc
},
9651 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
9654 static const struct message ml_edit_lbutton_up
[] =
9656 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
9657 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
9658 { WM_CAPTURECHANGED
, sent
|defwinproc
},
9662 static WNDPROC old_edit_proc
;
9664 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
9666 static LONG defwndproc_counter
= 0;
9668 struct recvd_message msg
;
9670 if (ignore_message( message
)) return 0;
9673 msg
.message
= message
;
9674 msg
.flags
= sent
|wparam
|lparam
;
9675 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
9676 msg
.wParam
= wParam
;
9677 msg
.lParam
= lParam
;
9681 defwndproc_counter
++;
9682 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
9683 defwndproc_counter
--;
9688 static void subclass_edit(void)
9692 if (!GetClassInfoA(0, "edit", &cls
)) assert(0);
9694 old_edit_proc
= cls
.lpfnWndProc
;
9696 cls
.hInstance
= GetModuleHandleA(NULL
);
9697 cls
.lpfnWndProc
= edit_hook_proc
;
9698 cls
.lpszClassName
= "my_edit_class";
9699 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
9700 if (!RegisterClassA(&cls
)) assert(0);
9703 static void test_edit_messages(void)
9709 log_all_parent_messages
++;
9711 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9712 100, 100, 200, 200, 0, 0, 0, NULL
);
9713 ok (parent
!= 0, "Failed to create parent window\n");
9715 /* test single line edit */
9716 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
9717 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
9718 ok(hwnd
!= 0, "Failed to create edit window\n");
9720 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
9721 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08x\n", dlg_code
);
9725 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
9727 ShowWindow(hwnd
, SW_SHOW
);
9733 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
9736 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
9742 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
9743 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
9749 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
9750 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
9752 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
9753 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
9755 DestroyWindow(hwnd
);
9757 /* test multiline edit */
9758 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
9759 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
9760 ok(hwnd
!= 0, "Failed to create edit window\n");
9762 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
9763 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
9764 "wrong dlg_code %08x\n", dlg_code
);
9766 ShowWindow(hwnd
, SW_SHOW
);
9772 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
9775 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
9781 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
9782 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
9788 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
9789 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
9791 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
9792 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
9794 DestroyWindow(hwnd
);
9795 DestroyWindow(parent
);
9797 log_all_parent_messages
--;
9800 /**************************** End of Edit test ******************************/
9802 static const struct message WmKeyDownSkippedSeq
[] =
9804 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
9807 static const struct message WmKeyDownWasDownSkippedSeq
[] =
9809 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
9812 static const struct message WmKeyUpSkippedSeq
[] =
9814 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9817 static const struct message WmUserKeyUpSkippedSeq
[] =
9820 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
9825 #define EV_SENDMSG 1
9831 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
9834 static DWORD CALLBACK
send_msg_thread_2(void *param
)
9837 struct peekmsg_info
*info
= param
;
9839 trace("thread: looping\n");
9840 SetEvent(info
->hevent
[EV_ACK
]);
9844 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
9848 case WAIT_OBJECT_0
+ EV_STOP
:
9849 trace("thread: exiting\n");
9852 case WAIT_OBJECT_0
+ EV_SENDMSG
:
9853 trace("thread: sending message\n");
9854 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
9855 ok(ret
, "SendNotifyMessageA failed error %u\n", GetLastError());
9856 SetEvent(info
->hevent
[EV_ACK
]);
9860 trace("unexpected return: %04x\n", ret
);
9868 static void test_PeekMessage(void)
9873 UINT qs_all_input
= QS_ALLINPUT
;
9874 UINT qs_input
= QS_INPUT
;
9876 struct peekmsg_info info
;
9878 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
9879 100, 100, 200, 200, 0, 0, 0, NULL
);
9881 ShowWindow(info
.hwnd
, SW_SHOW
);
9882 UpdateWindow(info
.hwnd
);
9883 SetFocus(info
.hwnd
);
9885 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
9886 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
9887 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
9889 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
9890 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
9895 SetLastError(0xdeadbeef);
9896 qstatus
= GetQueueStatus(qs_all_input
);
9897 if (GetLastError() == ERROR_INVALID_FLAGS
)
9899 trace("QS_RAWINPUT not supported on this platform\n");
9900 qs_all_input
&= ~QS_RAWINPUT
;
9901 qs_input
&= ~QS_RAWINPUT
;
9903 if (qstatus
& QS_POSTMESSAGE
)
9905 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
9906 qstatus
= GetQueueStatus(qs_all_input
);
9908 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
9910 trace("signalling to send message\n");
9911 SetEvent(info
.hevent
[EV_SENDMSG
]);
9912 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
9914 /* pass invalid QS_xxxx flags */
9915 SetLastError(0xdeadbeef);
9916 qstatus
= GetQueueStatus(0xffffffff);
9917 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus
);
9920 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %d\n", GetLastError());
9921 qstatus
= GetQueueStatus(qs_all_input
);
9923 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
9924 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
),
9925 "wrong qstatus %08x\n", qstatus
);
9928 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
9930 "PeekMessageA should have returned FALSE instead of msg %04x\n",
9932 ok_sequence(WmUser
, "WmUser", FALSE
);
9934 qstatus
= GetQueueStatus(qs_all_input
);
9935 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
9937 keybd_event('N', 0, 0, 0);
9938 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
9939 qstatus
= GetQueueStatus(qs_all_input
);
9940 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
9942 skip( "queuing key events not supported\n" );
9945 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
9946 /* keybd_event seems to trigger a sent message on NT4 */
9947 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
9948 "wrong qstatus %08x\n", qstatus
);
9950 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
9951 qstatus
= GetQueueStatus(qs_all_input
);
9952 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
9953 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
9954 "wrong qstatus %08x\n", qstatus
);
9956 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
9957 qstatus
= GetQueueStatus(qs_all_input
);
9958 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
9959 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
9960 "wrong qstatus %08x\n", qstatus
);
9962 trace("signalling to send message\n");
9963 SetEvent(info
.hevent
[EV_SENDMSG
]);
9964 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
9966 qstatus
= GetQueueStatus(qs_all_input
);
9967 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
9968 "wrong qstatus %08x\n", qstatus
);
9971 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
9972 if (ret
&& msg
.message
== WM_CHAR
)
9974 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
9978 "PeekMessageA should have returned FALSE instead of msg %04x\n",
9980 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
9982 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
9985 ok_sequence(WmUser
, "WmUser", FALSE
);
9987 qstatus
= GetQueueStatus(qs_all_input
);
9988 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
9989 "wrong qstatus %08x\n", qstatus
);
9991 trace("signalling to send message\n");
9992 SetEvent(info
.hevent
[EV_SENDMSG
]);
9993 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
9995 qstatus
= GetQueueStatus(qs_all_input
);
9996 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
9997 "wrong qstatus %08x\n", qstatus
);
10000 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
10002 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10004 ok_sequence(WmUser
, "WmUser", FALSE
);
10006 qstatus
= GetQueueStatus(qs_all_input
);
10007 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
10008 "wrong qstatus %08x\n", qstatus
);
10011 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
10012 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10013 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10014 ret
, msg
.message
, msg
.wParam
);
10015 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10017 qstatus
= GetQueueStatus(qs_all_input
);
10018 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
10019 "wrong qstatus %08x\n", qstatus
);
10022 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
10024 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10026 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10028 qstatus
= GetQueueStatus(qs_all_input
);
10029 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
10030 "wrong qstatus %08x\n", qstatus
);
10033 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
10034 ok(ret
&& msg
.message
== WM_PAINT
,
10035 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
10036 DispatchMessageA(&msg
);
10037 ok_sequence(WmPaint
, "WmPaint", FALSE
);
10039 qstatus
= GetQueueStatus(qs_all_input
);
10040 ok(qstatus
== MAKELONG(0, QS_KEY
),
10041 "wrong qstatus %08x\n", qstatus
);
10044 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
10046 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10048 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10050 qstatus
= GetQueueStatus(qs_all_input
);
10051 ok(qstatus
== MAKELONG(0, QS_KEY
),
10052 "wrong qstatus %08x\n", qstatus
);
10054 trace("signalling to send message\n");
10055 SetEvent(info
.hevent
[EV_SENDMSG
]);
10056 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
10058 qstatus
= GetQueueStatus(qs_all_input
);
10059 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
10060 "wrong qstatus %08x\n", qstatus
);
10062 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10064 qstatus
= GetQueueStatus(qs_all_input
);
10065 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
10066 "wrong qstatus %08x\n", qstatus
);
10069 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
10070 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10071 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10072 ret
, msg
.message
, msg
.wParam
);
10073 ok_sequence(WmUser
, "WmUser", FALSE
);
10075 qstatus
= GetQueueStatus(qs_all_input
);
10076 ok(qstatus
== MAKELONG(0, QS_KEY
),
10077 "wrong qstatus %08x\n", qstatus
);
10080 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
10082 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10084 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10086 qstatus
= GetQueueStatus(qs_all_input
);
10087 ok(qstatus
== MAKELONG(0, QS_KEY
),
10088 "wrong qstatus %08x\n", qstatus
);
10090 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10092 qstatus
= GetQueueStatus(qs_all_input
);
10093 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
10094 "wrong qstatus %08x\n", qstatus
);
10096 trace("signalling to send message\n");
10097 SetEvent(info
.hevent
[EV_SENDMSG
]);
10098 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
10100 qstatus
= GetQueueStatus(qs_all_input
);
10101 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
10102 "wrong qstatus %08x\n", qstatus
);
10105 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
10107 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10109 ok_sequence(WmUser
, "WmUser", FALSE
);
10111 qstatus
= GetQueueStatus(qs_all_input
);
10112 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
10113 "wrong qstatus %08x\n", qstatus
);
10116 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
10117 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
10118 else /* workaround for a missing QS_RAWINPUT support */
10119 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
10120 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
10121 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10122 ret
, msg
.message
, msg
.wParam
);
10123 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
10125 qstatus
= GetQueueStatus(qs_all_input
);
10126 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
10127 "wrong qstatus %08x\n", qstatus
);
10130 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
10131 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
10132 else /* workaround for a missing QS_RAWINPUT support */
10133 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
10134 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
10135 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n",
10136 ret
, msg
.message
, msg
.wParam
);
10137 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
10139 qstatus
= GetQueueStatus(qs_all_input
);
10140 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10141 "wrong qstatus %08x\n", qstatus
);
10144 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
10146 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10148 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10150 qstatus
= GetQueueStatus(qs_all_input
);
10151 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10152 "wrong qstatus %08x\n", qstatus
);
10155 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10156 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10157 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10158 ret
, msg
.message
, msg
.wParam
);
10159 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10161 qstatus
= GetQueueStatus(qs_all_input
);
10163 "wrong qstatus %08x\n", qstatus
);
10166 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10168 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10170 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10172 qstatus
= GetQueueStatus(qs_all_input
);
10174 "wrong qstatus %08x\n", qstatus
);
10176 /* test whether presence of the quit flag in the queue affects
10179 PostQuitMessage(0x1234abcd);
10181 qstatus
= GetQueueStatus(qs_all_input
);
10182 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
10183 "wrong qstatus %08x\n", qstatus
);
10185 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
10187 qstatus
= GetQueueStatus(qs_all_input
);
10188 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
10189 "wrong qstatus %08x\n", qstatus
);
10192 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10193 ok(ret
&& msg
.message
== WM_USER
,
10194 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
10195 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10197 qstatus
= GetQueueStatus(qs_all_input
);
10198 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10199 "wrong qstatus %08x\n", qstatus
);
10202 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10203 ok(ret
&& msg
.message
== WM_QUIT
,
10204 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
10205 ok(msg
.wParam
== 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg
.wParam
);
10206 ok(msg
.lParam
== 0, "got lParam %08lx instead of 0\n", msg
.lParam
);
10207 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10209 qstatus
= GetQueueStatus(qs_all_input
);
10211 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
10212 "wrong qstatus %08x\n", qstatus
);
10216 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10218 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10220 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
10222 qstatus
= GetQueueStatus(qs_all_input
);
10224 "wrong qstatus %08x\n", qstatus
);
10226 /* some GetMessage tests */
10228 keybd_event('N', 0, 0, 0);
10229 qstatus
= GetQueueStatus(qs_all_input
);
10230 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10232 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10233 qstatus
= GetQueueStatus(qs_all_input
);
10234 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10238 ret
= GetMessageA( &msg
, 0, 0, 0 );
10239 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10240 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10241 ret
, msg
.message
, msg
.wParam
);
10242 qstatus
= GetQueueStatus(qs_all_input
);
10243 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10248 ret
= GetMessageA( &msg
, 0, 0, 0 );
10249 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
10250 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10251 ret
, msg
.message
, msg
.wParam
);
10252 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
10253 qstatus
= GetQueueStatus(qs_all_input
);
10254 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10257 keybd_event('N', 0, 0, 0);
10258 qstatus
= GetQueueStatus(qs_all_input
);
10259 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10261 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10262 qstatus
= GetQueueStatus(qs_all_input
);
10263 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10265 if (qstatus
& (QS_KEY
<< 16))
10267 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
10268 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
10269 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10270 ret
, msg
.message
, msg
.wParam
);
10271 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
10272 qstatus
= GetQueueStatus(qs_all_input
);
10273 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
10278 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
10279 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10280 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10281 ret
, msg
.message
, msg
.wParam
);
10282 qstatus
= GetQueueStatus(qs_all_input
);
10283 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10286 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10287 qstatus
= GetQueueStatus(qs_all_input
);
10288 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10290 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
10291 qstatus
= GetQueueStatus(qs_all_input
);
10292 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
10294 trace("signalling to send message\n");
10295 SetEvent(info
.hevent
[EV_SENDMSG
]);
10296 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
10297 qstatus
= GetQueueStatus(qs_all_input
);
10298 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
10299 "wrong qstatus %08x\n", qstatus
);
10301 if (qstatus
& (QS_KEY
<< 16))
10303 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
10304 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
10305 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
10306 ret
, msg
.message
, msg
.wParam
);
10307 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
10308 qstatus
= GetQueueStatus(qs_all_input
);
10309 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
10314 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
10315 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
10316 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
10317 ret
, msg
.message
, msg
.wParam
);
10318 qstatus
= GetQueueStatus(qs_all_input
);
10319 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10322 trace("signalling to exit\n");
10323 SetEvent(info
.hevent
[EV_STOP
]);
10325 WaitForSingleObject(hthread
, INFINITE
);
10327 CloseHandle(hthread
);
10328 CloseHandle(info
.hevent
[0]);
10329 CloseHandle(info
.hevent
[1]);
10330 CloseHandle(info
.hevent
[2]);
10332 DestroyWindow(info
.hwnd
);
10335 static void wait_move_event(HWND hwnd
, int x
, int y
)
10339 BOOL ret
, go
= FALSE
;
10341 time
= GetTickCount();
10342 while (GetTickCount() - time
< 200 && !go
) {
10343 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10344 go
= ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
;
10345 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, GetTickCount() - time
, QS_ALLINPUT
);
10350 static void test_PeekMessage2(void)
10356 DWORD time1
, time2
, time3
;
10357 int x1
, y1
, x2
, y2
, x3
, y3
;
10360 time1
= time2
= time3
= 0;
10361 x1
= y1
= x2
= y2
= x3
= y3
= 0;
10363 /* Initialise window and make sure it is ready for events */
10364 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
10365 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
10367 trace("Window for test_PeekMessage2 %p\n", hwnd
);
10368 ShowWindow(hwnd
, SW_SHOW
);
10369 UpdateWindow(hwnd
);
10371 GetCursorPos(&pos
);
10372 SetCursorPos(100, 100);
10373 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
10376 /* Do initial mousemove, wait until we can see it
10377 and then do our test peek with PM_NOREMOVE. */
10378 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
10379 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
10381 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10384 skip( "queuing mouse events not supported\n" );
10389 trace("1st move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
10390 message
= msg
.message
;
10394 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
10397 /* Allow time to advance a bit, and then simulate the user moving their
10398 * mouse around. After that we peek again with PM_NOREMOVE.
10399 * Although the previous mousemove message was never removed, the
10400 * mousemove we now peek should reflect the recent mouse movements
10401 * because the input queue will merge the move events. */
10403 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
10404 wait_move_event(hwnd
, x1
, y1
);
10406 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10407 ok(ret
, "no message available\n");
10409 trace("2nd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
10410 message
= msg
.message
;
10414 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
10415 ok(time2
> time1
, "message time not advanced: %x %x\n", time1
, time2
);
10416 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
10419 /* Have another go, to drive the point home */
10421 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
10422 wait_move_event(hwnd
, x2
, y2
);
10424 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
10425 ok(ret
, "no message available\n");
10427 trace("3rd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
10428 message
= msg
.message
;
10432 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
10433 ok(time3
> time2
, "message time not advanced: %x %x\n", time2
, time3
);
10434 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
10438 DestroyWindow(hwnd
);
10439 SetCursorPos(pos
.x
, pos
.y
);
10443 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
10445 struct recvd_message msg
;
10447 if (ignore_message( message
)) return 0;
10450 msg
.message
= message
;
10451 msg
.flags
= sent
|wparam
|lparam
;
10454 msg
.descr
= "dialog";
10459 case WM_INITDIALOG
:
10460 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
10461 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
10464 case WM_GETDLGCODE
:
10468 EndDialog(hwnd
, 0);
10475 static const struct message WmQuitDialogSeq
[] = {
10476 { HCBT_CREATEWND
, hook
},
10477 { WM_SETFONT
, sent
},
10478 { WM_INITDIALOG
, sent
},
10479 { WM_CHANGEUISTATE
, sent
|optional
},
10480 { HCBT_DESTROYWND
, hook
},
10481 { 0x0090, sent
|optional
}, /* Vista */
10482 { WM_DESTROY
, sent
},
10483 { WM_NCDESTROY
, sent
},
10487 static const struct message WmStopQuitSeq
[] = {
10488 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
10489 { WM_CLOSE
, posted
},
10490 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
10494 static void test_quit_message(void)
10499 /* test using PostQuitMessage */
10501 PostQuitMessage(0xbeef);
10503 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
10504 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
10505 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10506 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
10508 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
10509 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
10511 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10512 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
10513 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
10515 /* note: WM_QUIT message received after WM_USER message */
10516 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10517 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
10518 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10519 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
10521 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
10522 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
10524 /* now test with PostThreadMessage - different behaviour! */
10525 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
10527 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
10528 ok(ret
, "PeekMessage failed with error %d\n", 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
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
10533 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
10535 /* note: we receive the WM_QUIT message first this time */
10536 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10537 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
10538 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10539 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
10541 ret
= GetMessageA(&msg
, NULL
, 0, 0);
10542 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
10543 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
10547 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
10548 ok(ret
== 1, "expected 1, got %d\n", ret
);
10549 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
10550 memset(&msg
, 0xab, sizeof(msg
));
10551 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
10552 ok(ret
, "PeekMessage failed\n");
10553 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
10554 ok(msg
.wParam
== 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg
.wParam
);
10555 ok(msg
.lParam
== 0, "lParam was 0x%lx instead of 0\n", msg
.lParam
);
10557 /* Check what happens to a WM_QUIT message posted to a window that gets
10560 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
10561 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
10563 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
10565 struct recvd_message rmsg
;
10566 rmsg
.hwnd
= msg
.hwnd
;
10567 rmsg
.message
= msg
.message
;
10568 rmsg
.flags
= posted
|wparam
|lparam
;
10569 rmsg
.wParam
= msg
.wParam
;
10570 rmsg
.lParam
= msg
.lParam
;
10571 rmsg
.descr
= "stop/quit";
10572 if (msg
.message
== WM_QUIT
)
10573 /* The hwnd can only be checked here */
10574 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
10575 add_message(&rmsg
);
10576 DispatchMessageA(&msg
);
10578 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
10581 static const struct message WmMouseHoverSeq
[] = {
10582 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
10583 { WM_MOUSEACTIVATE
, sent
|optional
},
10584 { WM_TIMER
, sent
|optional
}, /* XP sends it */
10585 { WM_SYSTIMER
, sent
},
10586 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
10590 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
10593 DWORD start_ticks
, end_ticks
;
10595 start_ticks
= GetTickCount();
10596 /* add some deviation (50%) to cover not expected delays */
10597 start_ticks
+= timeout
/ 2;
10601 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
10603 /* Timer proc messages are not dispatched to the window proc,
10604 * and therefore not logged.
10606 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
10608 struct recvd_message s_msg
;
10610 s_msg
.hwnd
= msg
.hwnd
;
10611 s_msg
.message
= msg
.message
;
10612 s_msg
.flags
= sent
|wparam
|lparam
;
10613 s_msg
.wParam
= msg
.wParam
;
10614 s_msg
.lParam
= msg
.lParam
;
10615 s_msg
.descr
= "msg_loop";
10616 add_message(&s_msg
);
10618 DispatchMessageA(&msg
);
10621 end_ticks
= GetTickCount();
10623 /* inject WM_MOUSEMOVE to see how it changes tracking */
10624 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
10626 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10627 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10629 inject_mouse_move
= FALSE
;
10631 } while (start_ticks
+ timeout
>= end_ticks
);
10634 static void test_TrackMouseEvent(void)
10636 TRACKMOUSEEVENT tme
;
10639 RECT rc_parent
, rc_child
;
10640 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
10642 #define track_hover(track_hwnd, track_hover_time) \
10643 tme.cbSize = sizeof(tme); \
10644 tme.dwFlags = TME_HOVER; \
10645 tme.hwndTrack = track_hwnd; \
10646 tme.dwHoverTime = track_hover_time; \
10647 SetLastError(0xdeadbeef); \
10648 ret = pTrackMouseEvent(&tme); \
10649 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError())
10651 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
10652 tme.cbSize = sizeof(tme); \
10653 tme.dwFlags = TME_QUERY; \
10654 tme.hwndTrack = (HWND)0xdeadbeef; \
10655 tme.dwHoverTime = 0xdeadbeef; \
10656 SetLastError(0xdeadbeef); \
10657 ret = pTrackMouseEvent(&tme); \
10658 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\
10659 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \
10660 ok(tme.dwFlags == (expected_track_flags), \
10661 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
10662 ok(tme.hwndTrack == (expected_track_hwnd), \
10663 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
10664 ok(tme.dwHoverTime == (expected_hover_time), \
10665 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time))
10667 #define track_hover_cancel(track_hwnd) \
10668 tme.cbSize = sizeof(tme); \
10669 tme.dwFlags = TME_HOVER | TME_CANCEL; \
10670 tme.hwndTrack = track_hwnd; \
10671 tme.dwHoverTime = 0xdeadbeef; \
10672 SetLastError(0xdeadbeef); \
10673 ret = pTrackMouseEvent(&tme); \
10674 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError())
10676 default_hover_time
= 0xdeadbeef;
10677 SetLastError(0xdeadbeef);
10678 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
10679 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
10680 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError());
10681 if (!ret
) default_hover_time
= 400;
10682 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
10684 SetLastError(0xdeadbeef);
10685 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
10686 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
10687 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError());
10688 if (!ret
) hover_width
= 4;
10689 SetLastError(0xdeadbeef);
10690 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
10691 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
10692 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError());
10693 if (!ret
) hover_height
= 4;
10694 trace("hover rect is %u x %d\n", hover_width
, hover_height
);
10696 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
10697 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
10698 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
10702 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
10703 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
10704 50, 50, 200, 200, hwnd
,
10708 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
10713 tme
.dwFlags
= TME_QUERY
;
10714 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10715 tme
.dwHoverTime
= 0xdeadbeef;
10716 SetLastError(0xdeadbeef);
10717 ret
= pTrackMouseEvent(&tme
);
10718 ok(!ret
, "TrackMouseEvent should fail\n");
10719 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
10720 "not expected error %u\n", GetLastError());
10722 tme
.cbSize
= sizeof(tme
);
10723 tme
.dwFlags
= TME_HOVER
;
10724 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10725 tme
.dwHoverTime
= 0xdeadbeef;
10726 SetLastError(0xdeadbeef);
10727 ret
= pTrackMouseEvent(&tme
);
10728 ok(!ret
, "TrackMouseEvent should fail\n");
10729 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
10730 "not expected error %u\n", GetLastError());
10732 tme
.cbSize
= sizeof(tme
);
10733 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
10734 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10735 tme
.dwHoverTime
= 0xdeadbeef;
10736 SetLastError(0xdeadbeef);
10737 ret
= pTrackMouseEvent(&tme
);
10738 ok(!ret
, "TrackMouseEvent should fail\n");
10739 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
10740 "not expected error %u\n", GetLastError());
10742 GetWindowRect(hwnd
, &rc_parent
);
10743 GetWindowRect(hchild
, &rc_child
);
10744 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
10746 /* Process messages so that the system updates its internal current
10747 * window and hittest, otherwise TrackMouseEvent calls don't have any
10753 track_query(0, NULL
, 0);
10754 track_hover(hchild
, 0);
10755 track_query(0, NULL
, 0);
10760 track_hover(hwnd
, 0);
10761 tme
.cbSize
= sizeof(tme
);
10762 tme
.dwFlags
= TME_QUERY
;
10763 tme
.hwndTrack
= (HWND
)0xdeadbeef;
10764 tme
.dwHoverTime
= 0xdeadbeef;
10765 SetLastError(0xdeadbeef);
10766 ret
= pTrackMouseEvent(&tme
);
10767 ok(ret
, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());
10768 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %u\n", tme
.cbSize
);
10771 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
10772 DestroyWindow( hwnd
);
10775 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme
.dwFlags
);
10776 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
10777 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %u, expected %u\n",
10778 tme
.dwHoverTime
, default_hover_time
);
10780 pump_msg_loop_timeout(default_hover_time
, FALSE
);
10781 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
10783 track_query(0, NULL
, 0);
10785 track_hover(hwnd
, HOVER_DEFAULT
);
10786 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10788 Sleep(default_hover_time
/ 2);
10789 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
10790 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
10792 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10794 pump_msg_loop_timeout(default_hover_time
, FALSE
);
10795 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
10797 track_query(0, NULL
, 0);
10799 track_hover(hwnd
, HOVER_DEFAULT
);
10800 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10802 pump_msg_loop_timeout(default_hover_time
, TRUE
);
10803 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
10805 track_query(0, NULL
, 0);
10807 track_hover(hwnd
, HOVER_DEFAULT
);
10808 track_query(TME_HOVER
, hwnd
, default_hover_time
);
10809 track_hover_cancel(hwnd
);
10811 DestroyWindow(hwnd
);
10815 #undef track_hover_cancel
10819 static const struct message WmSetWindowRgn
[] = {
10820 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10821 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
10822 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
10823 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10824 { WM_ERASEBKGND
, sent
|optional
},
10825 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10826 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10830 static const struct message WmSetWindowRgn_no_redraw
[] = {
10831 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
10832 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
10833 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
10834 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10838 static const struct message WmSetWindowRgn_clear
[] = {
10839 { WM_WINDOWPOSCHANGING
, sent
/*|wparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ },
10840 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
10841 { WM_NCPAINT
, sent
|optional
},
10842 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10843 { WM_ERASEBKGND
, sent
|optional
}, /* FIXME: remove optional once Wine is fixed */
10844 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10845 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
10846 { WM_NCPAINT
, sent
|optional
},
10847 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10848 { WM_ERASEBKGND
, sent
|optional
},
10849 { WM_WINDOWPOSCHANGING
, sent
|optional
},
10850 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
10851 { WM_NCPAINT
, sent
|optional
},
10852 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10853 { WM_ERASEBKGND
, sent
|optional
},
10854 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
10855 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
10856 { WM_NCPAINT
, sent
|optional
},
10857 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10858 { WM_ERASEBKGND
, sent
|optional
},
10859 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10860 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
10864 static void test_SetWindowRgn(void)
10867 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
10868 100, 100, 200, 200, 0, 0, 0, NULL
);
10869 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
10871 ShowWindow( hwnd
, SW_SHOW
);
10872 UpdateWindow( hwnd
);
10876 trace("testing SetWindowRgn\n");
10877 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
10878 SetWindowRgn( hwnd
, hrgn
, TRUE
);
10879 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
10881 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
10882 SetWindowRgn( hwnd
, hrgn
, FALSE
);
10883 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
10885 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
10886 SetWindowRgn( hwnd
, hrgn
, TRUE
);
10887 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
10889 SetWindowRgn( hwnd
, 0, TRUE
);
10890 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
10892 DestroyWindow( hwnd
);
10895 /*************************** ShowWindow() test ******************************/
10896 static const struct message WmShowNormal
[] = {
10897 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10898 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
10899 { HCBT_ACTIVATE
, hook
},
10900 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
10901 { HCBT_SETFOCUS
, hook
},
10902 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10905 static const struct message WmShow
[] = {
10906 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10907 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
10908 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
10909 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
10910 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
10911 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10914 static const struct message WmShowNoActivate_1
[] = {
10915 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
10916 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10917 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10918 { WM_MOVE
, sent
|defwinproc
|optional
},
10919 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
10922 static const struct message WmShowNoActivate_2
[] = {
10923 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
10924 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
10925 { HCBT_ACTIVATE
, hook
|optional
},
10926 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
10927 { HCBT_SETFOCUS
, hook
|optional
},
10928 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
10929 { WM_MOVE
, sent
|defwinproc
},
10930 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
10931 { HCBT_SETFOCUS
, hook
|optional
},
10932 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
10933 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
10934 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10935 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
10938 static const struct message WmShowNA_1
[] = {
10939 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10940 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
10941 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10944 static const struct message WmShowNA_2
[] = {
10945 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10946 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
10947 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10950 static const struct message WmRestore_1
[] = {
10951 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
10952 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10953 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
10954 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
10955 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
10956 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10957 { WM_MOVE
, sent
|defwinproc
},
10958 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
10959 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
10962 static const struct message WmRestore_2
[] = {
10963 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
10964 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
10965 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
10966 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
10967 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
10968 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
10971 static const struct message WmRestore_3
[] = {
10972 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
10973 { WM_GETMINMAXINFO
, sent
},
10974 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10975 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
10976 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
10977 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
10978 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
10979 { WM_MOVE
, sent
|defwinproc
},
10980 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
10981 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
10984 static const struct message WmRestore_4
[] = {
10985 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
10986 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10987 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10988 { WM_MOVE
, sent
|defwinproc
|optional
},
10989 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
10992 static const struct message WmRestore_5
[] = {
10993 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
10994 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10995 { HCBT_ACTIVATE
, hook
|optional
},
10996 { HCBT_SETFOCUS
, hook
|optional
},
10997 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
10998 { WM_MOVE
, sent
|defwinproc
|optional
},
10999 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
11002 static const struct message WmHide_1
[] = {
11003 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
11004 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
11005 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
11006 { HCBT_ACTIVATE
, hook
|optional
},
11007 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
11010 static const struct message WmHide_2
[] = {
11011 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
11012 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
11013 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
11014 { HCBT_ACTIVATE
, hook
|optional
},
11017 static const struct message WmHide_3
[] = {
11018 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
11019 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
11020 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11021 { HCBT_SETFOCUS
, hook
|optional
},
11022 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11025 static const struct message WmShowMinimized_1
[] = {
11026 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
11027 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11028 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
11029 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
11030 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11031 { WM_MOVE
, sent
|defwinproc
},
11032 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11035 static const struct message WmMinimize_1
[] = {
11036 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11037 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
11038 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11039 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11040 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11041 { WM_MOVE
, sent
|defwinproc
},
11042 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11045 static const struct message WmMinimize_2
[] = {
11046 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11047 { HCBT_SETFOCUS
, hook
|optional
},
11048 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11049 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11050 { WM_MOVE
, sent
|defwinproc
},
11051 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11054 static const struct message WmMinimize_3
[] = {
11055 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11056 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11057 { HCBT_ACTIVATE
, hook
|optional
},
11058 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11059 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
11060 { WM_MOVE
, sent
|defwinproc
},
11061 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
11064 static const struct message WmShowMinNoActivate
[] = {
11065 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
11066 { WM_WINDOWPOSCHANGING
, sent
},
11067 { WM_WINDOWPOSCHANGED
, sent
},
11068 { WM_MOVE
, sent
|defwinproc
|optional
},
11069 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
11072 static const struct message WmMinMax_1
[] = {
11073 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
11076 static const struct message WmMinMax_2
[] = {
11077 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11078 { WM_GETMINMAXINFO
, sent
|optional
},
11079 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
11080 { HCBT_ACTIVATE
, hook
|optional
},
11081 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11082 { HCBT_SETFOCUS
, hook
|optional
},
11083 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11084 { WM_MOVE
, sent
|defwinproc
|optional
},
11085 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
11086 { HCBT_SETFOCUS
, hook
|optional
},
11089 static const struct message WmMinMax_3
[] = {
11090 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
11091 { HCBT_SETFOCUS
, hook
|optional
},
11092 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11093 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11094 { WM_MOVE
, sent
|defwinproc
|optional
},
11095 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
11098 static const struct message WmMinMax_4
[] = {
11099 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
11102 static const struct message WmShowMaximized_1
[] = {
11103 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11104 { WM_GETMINMAXINFO
, sent
},
11105 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11106 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
11107 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
11108 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
11109 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11110 { WM_MOVE
, sent
|defwinproc
},
11111 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
11112 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
11115 static const struct message WmShowMaximized_2
[] = {
11116 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11117 { WM_GETMINMAXINFO
, sent
},
11118 { WM_WINDOWPOSCHANGING
, sent
|optional
},
11119 { HCBT_ACTIVATE
, hook
|optional
},
11120 { WM_WINDOWPOSCHANGED
, sent
|optional
},
11121 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
11122 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
11123 { WM_WINDOWPOSCHANGING
, sent
|optional
},
11124 { HCBT_SETFOCUS
, hook
|optional
},
11125 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
11126 { WM_MOVE
, sent
|defwinproc
},
11127 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
11128 { HCBT_SETFOCUS
, hook
|optional
},
11131 static const struct message WmShowMaximized_3
[] = {
11132 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
11133 { WM_GETMINMAXINFO
, sent
|optional
},
11134 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
11135 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
11136 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
11137 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
11138 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
11139 { WM_MOVE
, sent
|defwinproc
|optional
},
11140 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
11144 static void test_ShowWindow(void)
11146 /* ShowWindow commands in random order */
11147 static const struct
11149 INT cmd
; /* ShowWindow command */
11150 LPARAM ret
; /* ShowWindow return value */
11151 DWORD style
; /* window style after the command */
11152 const struct message
*msg
; /* message sequence the command produces */
11153 INT wp_cmd
, wp_flags
; /* window placement after the command */
11154 POINT wp_min
, wp_max
; /* window placement after the command */
11155 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
11158 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
11159 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11160 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11161 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11162 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
11163 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11164 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11165 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
11166 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
11167 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11168 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
11169 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11170 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
11171 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11172 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
11173 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11174 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
11175 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11176 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
11177 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11178 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
11179 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11180 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
11181 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11182 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
11183 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11184 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11185 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11186 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
11187 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11188 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11189 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11190 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
11191 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11192 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11193 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11194 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
11195 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11196 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
11197 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11198 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11199 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11200 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
11201 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
11202 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
11203 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11204 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11205 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11206 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
11207 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11208 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
11209 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11210 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
11211 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11212 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11213 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11214 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
11215 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11216 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
11217 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11218 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11219 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11220 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
11221 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11222 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11223 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11224 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
11225 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11226 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
11227 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11228 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11229 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11230 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
11231 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11232 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11233 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11234 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11235 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11236 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
11237 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11238 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
11239 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11240 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
11241 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11242 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
11243 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11244 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
11245 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11246 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
11247 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11248 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
11249 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11250 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
11251 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11252 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
11253 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11254 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
11255 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11256 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
11257 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11258 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
11259 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11260 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
11261 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11262 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
11263 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
11264 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
11265 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11266 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
11267 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11268 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
11269 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
11270 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
11271 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
11277 WINDOWPLACEMENT wp
;
11278 RECT win_rc
, work_rc
= {0, 0, 0, 0};
11280 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
11281 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
11286 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
11287 ok(style
== 0, "expected style 0, got %08x\n", style
);
11292 if (pGetMonitorInfoA
&& pMonitorFromPoint
)
11298 SetLastError(0xdeadbeef);
11299 hmon
= pMonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
11300 ok(hmon
!= 0, "MonitorFromPoint error %u\n", GetLastError());
11302 mi
.cbSize
= sizeof(mi
);
11303 SetLastError(0xdeadbeef);
11304 ret
= pGetMonitorInfoA(hmon
, &mi
);
11305 ok(ret
, "GetMonitorInfo error %u\n", GetLastError());
11306 trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n",
11307 mi
.rcMonitor
.left
, mi
.rcMonitor
.top
, mi
.rcMonitor
.right
, mi
.rcMonitor
.bottom
,
11308 mi
.rcWork
.left
, mi
.rcWork
.top
, mi
.rcWork
.right
, mi
.rcWork
.bottom
);
11309 work_rc
= mi
.rcWork
;
11312 GetWindowRect(hwnd
, &win_rc
);
11313 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
11315 wp
.length
= sizeof(wp
);
11316 SetLastError(0xdeadbeaf);
11317 ret
= GetWindowPlacement(hwnd
, &wp
);
11318 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
11319 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
11320 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
11321 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
11322 "expected -1,-1 got %d,%d\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
11323 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
11324 "expected -1,-1 got %d,%d\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
11325 if (work_rc
.left
|| work_rc
.top
) todo_wine
/* FIXME: remove once Wine is fixed */
11326 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
),
11327 "expected %d,%d-%d,%d got %d,%d-%d,%d\n",
11328 win_rc
.left
, win_rc
.top
, win_rc
.right
, win_rc
.bottom
,
11329 wp
.rcNormalPosition
.left
, wp
.rcNormalPosition
.top
,
11330 wp
.rcNormalPosition
.right
, wp
.rcNormalPosition
.bottom
);
11332 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
),
11333 "expected %d,%d-%d,%d got %d,%d-%d,%d\n",
11334 win_rc
.left
, win_rc
.top
, win_rc
.right
, win_rc
.bottom
,
11335 wp
.rcNormalPosition
.left
, wp
.rcNormalPosition
.top
,
11336 wp
.rcNormalPosition
.right
, wp
.rcNormalPosition
.bottom
);
11338 for (i
= 0; i
< sizeof(sw
)/sizeof(sw
[0]); i
++)
11340 static const char * const sw_cmd_name
[13] =
11342 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
11343 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
11344 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
11345 "SW_NORMALNA" /* 0xCC */
11348 INT idx
; /* index into the above array of names */
11350 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
11352 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
11353 trace("%d: sending %s, current window style %08x\n", i
+1, sw_cmd_name
[idx
], style
);
11354 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
11355 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %lu, got %lu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
11356 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
11357 ok(style
== sw
[i
].style
, "%d: expected style %08x, got %08x\n", i
+1, sw
[i
].style
, style
);
11359 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
11360 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
11362 wp
.length
= sizeof(wp
);
11363 SetLastError(0xdeadbeaf);
11364 ret
= GetWindowPlacement(hwnd
, &wp
);
11365 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
11366 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
11367 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
11369 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
11370 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
11371 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
11373 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
11374 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
11375 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
11379 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
11380 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
11383 if (wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
11385 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
11386 "expected %d,%d got %d,%d\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
11388 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
11389 "expected %d,%d got %d,%d\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
11391 if (0) /* FIXME: Wine behaves completely different here */
11392 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
),
11393 "expected %d,%d-%d,%d got %d,%d-%d,%d\n",
11394 win_rc
.left
, win_rc
.top
, win_rc
.right
, win_rc
.bottom
,
11395 wp
.rcNormalPosition
.left
, wp
.rcNormalPosition
.top
,
11396 wp
.rcNormalPosition
.right
, wp
.rcNormalPosition
.bottom
);
11398 DestroyWindow(hwnd
);
11402 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11404 struct recvd_message msg
;
11406 if (ignore_message( message
)) return 0;
11409 msg
.message
= message
;
11410 msg
.flags
= sent
|wparam
|lparam
;
11411 msg
.wParam
= wParam
;
11412 msg
.lParam
= lParam
;
11413 msg
.descr
= "dialog";
11416 /* calling DefDlgProc leads to a recursion under XP */
11420 case WM_INITDIALOG
:
11421 case WM_GETDLGCODE
:
11427 static const struct message WmDefDlgSetFocus_1
[] = {
11428 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
11429 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
11430 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
11431 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
11432 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
11433 { HCBT_SETFOCUS
, hook
},
11434 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
11435 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11436 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
11437 { WM_SETFOCUS
, sent
|wparam
, 0 },
11438 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
11439 { WM_CTLCOLOREDIT
, sent
},
11440 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
11441 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11442 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11443 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11444 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
11447 static const struct message WmDefDlgSetFocus_2
[] = {
11448 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
11449 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
11450 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
11451 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
11452 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
11453 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11454 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
11455 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
11458 /* Creation of a dialog */
11459 static const struct message WmCreateDialogParamSeq_1
[] = {
11460 { HCBT_CREATEWND
, hook
},
11461 { WM_NCCREATE
, sent
},
11462 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
11463 { WM_CREATE
, sent
},
11464 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
11465 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
11467 { WM_SETFONT
, sent
},
11468 { WM_INITDIALOG
, sent
},
11469 { WM_CHANGEUISTATE
, sent
|optional
},
11472 /* Creation of a dialog */
11473 static const struct message WmCreateDialogParamSeq_2
[] = {
11474 { HCBT_CREATEWND
, hook
},
11475 { WM_NCCREATE
, sent
},
11476 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
11477 { WM_CREATE
, sent
},
11478 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
11479 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
11481 { WM_CHANGEUISTATE
, sent
|optional
},
11485 static void test_dialog_messages(void)
11488 HWND hdlg
, hedit1
, hedit2
, hfocus
;
11491 #define set_selection(hctl, start, end) \
11492 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
11493 ok(ret == 1, "EM_SETSEL returned %ld\n", ret);
11495 #define check_selection(hctl, start, end) \
11496 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
11497 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
11501 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
11502 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
11503 0, 0, 100, 100, 0, 0, 0, NULL
);
11504 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
11506 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
11507 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
11508 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
11509 ok(hedit1
!= 0, "Failed to create edit control\n");
11510 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
11511 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
11512 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
11513 ok(hedit2
!= 0, "Failed to create edit control\n");
11515 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
11516 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
11518 hfocus
= GetFocus();
11519 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
11522 hfocus
= GetFocus();
11523 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
11525 check_selection(hedit1
, 0, 0);
11526 check_selection(hedit2
, 0, 0);
11528 set_selection(hedit2
, 0, -1);
11529 check_selection(hedit2
, 0, 3);
11532 hfocus
= GetFocus();
11533 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
11536 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
11537 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
11538 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
11540 hfocus
= GetFocus();
11541 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
11543 check_selection(hedit1
, 0, 5);
11544 check_selection(hedit2
, 0, 3);
11547 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
11548 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
11549 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
11551 hfocus
= GetFocus();
11552 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
11554 check_selection(hedit1
, 0, 5);
11555 check_selection(hedit2
, 0, 3);
11557 EndDialog(hdlg
, 0);
11558 DestroyWindow(hedit1
);
11559 DestroyWindow(hedit2
);
11560 DestroyWindow(hdlg
);
11563 #undef set_selection
11564 #undef check_selection
11566 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
11567 cls
.lpszClassName
= "MyDialogClass";
11568 cls
.hInstance
= GetModuleHandleA(NULL
);
11569 /* need a cast since a dlgproc is used as a wndproc */
11570 cls
.lpfnWndProc
= test_dlg_proc
;
11571 if (!RegisterClassA(&cls
)) assert(0);
11573 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
11574 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
11575 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
11576 EndDialog(hdlg
, 0);
11577 DestroyWindow(hdlg
);
11580 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
11581 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
11582 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
11583 EndDialog(hdlg
, 0);
11584 DestroyWindow(hdlg
);
11587 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
11590 static void test_EndDialog(void)
11592 HWND hparent
, hother
, hactive
, hdlg
;
11595 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
11596 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
11597 100, 100, 200, 200, 0, 0, 0, NULL
);
11598 ok (hparent
!= 0, "Failed to create parent window\n");
11600 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
11601 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11602 100, 100, 200, 200, 0, 0, 0, NULL
);
11603 ok (hother
!= 0, "Failed to create parent window\n");
11605 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
11606 cls
.lpszClassName
= "MyDialogClass";
11607 cls
.hInstance
= GetModuleHandleA(NULL
);
11608 cls
.lpfnWndProc
= test_dlg_proc
;
11609 if (!RegisterClassA(&cls
)) assert(0);
11612 SetForegroundWindow(hother
);
11613 hactive
= GetForegroundWindow();
11614 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
11616 /* create a dialog where the parent is disabled, this parent should still
11617 receive the focus when the dialog exits (even though "normally" a
11618 disabled window should not receive the focus) */
11619 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
11620 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
11621 SetForegroundWindow(hdlg
);
11622 hactive
= GetForegroundWindow();
11623 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
11624 EndDialog(hdlg
, 0);
11625 hactive
= GetForegroundWindow();
11626 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
11627 DestroyWindow(hdlg
);
11630 DestroyWindow( hother
);
11631 DestroyWindow( hparent
);
11632 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
11635 static void test_nullCallback(void)
11639 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
11640 100, 100, 200, 200, 0, 0, 0, NULL
);
11641 ok (hwnd
!= 0, "Failed to create overlapped window\n");
11643 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
11645 DestroyWindow(hwnd
);
11648 /* SetActiveWindow( 0 ) hwnd visible */
11649 static const struct message SetActiveWindowSeq0
[] =
11651 { HCBT_ACTIVATE
, hook
|optional
},
11652 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11653 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11654 { WM_ACTIVATE
, sent
|wparam
, 0 },
11655 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
11656 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
11657 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11658 { WM_KILLFOCUS
, sent
|optional
},
11659 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11660 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11661 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
11662 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11663 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
11664 { HCBT_SETFOCUS
, hook
|optional
},
11665 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
11666 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
11667 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
11668 { WM_IME_SETCONTEXT
, sent
|optional
},
11669 { WM_IME_SETCONTEXT
, sent
|optional
},
11670 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11671 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11672 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
11673 { WM_GETTEXT
, sent
|optional
},
11676 /* SetActiveWindow( hwnd ) hwnd visible */
11677 static const struct message SetActiveWindowSeq1
[] =
11679 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11682 /* SetActiveWindow( popup ) hwnd visible, popup visible */
11683 static const struct message SetActiveWindowSeq2
[] =
11685 { HCBT_ACTIVATE
, hook
},
11686 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11687 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11688 { WM_ACTIVATE
, sent
|wparam
, 0 },
11689 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11690 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
11691 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11692 { WM_NCPAINT
, sent
|optional
},
11693 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11694 { WM_ERASEBKGND
, sent
|optional
},
11695 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11696 { WM_NCACTIVATE
, sent
|wparam
, 1 },
11697 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11698 { WM_ACTIVATE
, sent
|wparam
, 1 },
11699 { HCBT_SETFOCUS
, hook
},
11700 { WM_KILLFOCUS
, sent
|defwinproc
},
11701 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
11702 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11703 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11704 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11705 { WM_SETFOCUS
, sent
|defwinproc
},
11706 { WM_GETTEXT
, sent
|optional
},
11710 /* SetActiveWindow( hwnd ) hwnd not visible */
11711 static const struct message SetActiveWindowSeq3
[] =
11713 { HCBT_ACTIVATE
, hook
},
11714 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11715 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11716 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
11717 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11718 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11719 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
11720 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
11721 { WM_NCACTIVATE
, sent
|wparam
, 1 },
11722 { WM_ACTIVATE
, sent
|wparam
, 1 },
11723 { HCBT_SETFOCUS
, hook
},
11724 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11725 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11726 { WM_SETFOCUS
, sent
|defwinproc
},
11729 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
11730 static const struct message SetActiveWindowSeq4
[] =
11732 { HCBT_ACTIVATE
, hook
},
11733 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11734 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11735 { WM_ACTIVATE
, sent
|wparam
, 0 },
11736 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
11737 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
11738 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
11739 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11740 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
11741 { WM_NCACTIVATE
, sent
|wparam
, 1 },
11742 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11743 { WM_ACTIVATE
, sent
|wparam
, 1 },
11744 { HCBT_SETFOCUS
, hook
},
11745 { WM_KILLFOCUS
, sent
|defwinproc
},
11746 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
11747 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
11748 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
11749 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
11750 { WM_SETFOCUS
, sent
|defwinproc
},
11755 static void test_SetActiveWindow(void)
11757 HWND hwnd
, popup
, ret
;
11759 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
11760 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11761 100, 100, 200, 200, 0, 0, 0, NULL
);
11763 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
11764 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
11765 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
11767 ok(hwnd
!= 0, "Failed to create overlapped window\n");
11768 ok(popup
!= 0, "Failed to create popup window\n");
11769 SetForegroundWindow( popup
);
11772 trace("SetActiveWindow(0)\n");
11773 ret
= SetActiveWindow(0);
11774 ok( ret
== popup
, "Failed to SetActiveWindow(0)\n");
11775 ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
11778 trace("SetActiveWindow(hwnd), hwnd visible\n");
11779 ret
= SetActiveWindow(hwnd
);
11780 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
11783 trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
11784 ret
= SetActiveWindow(popup
);
11785 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
11786 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
11789 ShowWindow(hwnd
, SW_HIDE
);
11790 ShowWindow(popup
, SW_HIDE
);
11793 trace("SetActiveWindow(hwnd), hwnd not visible\n");
11794 ret
= SetActiveWindow(hwnd
);
11795 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
11796 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
11799 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
11800 ret
= SetActiveWindow(popup
);
11801 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
11802 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
11807 DestroyWindow(hwnd
);
11810 static const struct message SetForegroundWindowSeq
[] =
11812 { WM_NCACTIVATE
, sent
|wparam
, 0 },
11813 { WM_GETTEXT
, sent
|defwinproc
|optional
},
11814 { WM_ACTIVATE
, sent
|wparam
, 0 },
11815 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
11816 { WM_KILLFOCUS
, sent
},
11817 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
11818 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
11822 static void test_SetForegroundWindow(void)
11826 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
11827 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11828 100, 100, 200, 200, 0, 0, 0, NULL
);
11829 ok (hwnd
!= 0, "Failed to create overlapped window\n");
11830 SetForegroundWindow( hwnd
);
11833 trace("SetForegroundWindow( 0 )\n");
11834 SetForegroundWindow( 0 );
11835 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
11836 trace("SetForegroundWindow( GetDesktopWindow() )\n");
11837 SetForegroundWindow( GetDesktopWindow() );
11838 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
11839 "foreground top level window", FALSE
);
11842 DestroyWindow(hwnd
);
11845 static void test_dbcs_wm_char(void)
11848 WCHAR wch
, bad_wch
;
11856 struct message wmCharSeq
[2];
11859 if (!pGetCPInfoExA
)
11861 win_skip("GetCPInfoExA is not available\n");
11865 pGetCPInfoExA( CP_ACP
, 0, &cpinfo
);
11866 if (cpinfo
.MaxCharSize
!= 2)
11868 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
11872 dbch
[0] = dbch
[1] = 0;
11874 bad_wch
= cpinfo
.UnicodeDefaultChar
;
11875 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
11876 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
11877 for (k
= 128; k
<= 255; k
++)
11883 if (MultiByteToWideChar( CP_ACP
, 0, str
, 2, wstr
, 2 ) == 1 &&
11884 WideCharToMultiByte( CP_ACP
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
11885 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
11886 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
11897 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
11900 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
11901 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
11903 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
11904 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
11905 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
11906 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
11907 ok (hwnd
!= 0, "Failed to create overlapped window\n");
11908 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
11911 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
11912 wmCharSeq
[0].message
= WM_CHAR
;
11913 wmCharSeq
[0].flags
= sent
|wparam
;
11914 wmCharSeq
[0].wParam
= wch
;
11916 /* posted message */
11917 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
11918 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11919 ok( !ret
, "got message %x\n", msg
.message
);
11920 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
11921 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11922 ok( ret
, "no message\n" );
11923 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
11924 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
11925 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11926 ok( !ret
, "got message %x\n", msg
.message
);
11928 /* posted thread message */
11929 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
11930 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11931 ok( !ret
, "got message %x\n", msg
.message
);
11932 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
11933 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11934 ok( ret
, "no message\n" );
11935 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
11936 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
11937 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11938 ok( !ret
, "got message %x\n", msg
.message
);
11942 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
11943 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11944 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
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 */
11951 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
11952 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11953 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
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 timeout and callback */
11960 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
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 /* sent message with callback */
11969 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
11970 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11971 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
11972 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11973 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
11974 ok( !ret
, "got message %x\n", msg
.message
);
11976 /* direct window proc call */
11978 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
11979 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11980 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
11981 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11983 /* dispatch message */
11985 msg
.message
= WM_CHAR
;
11986 msg
.wParam
= dbch
[0];
11988 DispatchMessageA( &msg
);
11989 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11990 msg
.wParam
= dbch
[1];
11991 DispatchMessageA( &msg
);
11992 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
11994 /* window handle is irrelevant */
11996 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
11997 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
11998 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
11999 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12000 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12001 ok( !ret
, "got message %x\n", msg
.message
);
12003 /* interleaved post and send */
12005 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
12006 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
12007 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12008 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12009 ok( !ret
, "got message %x\n", msg
.message
);
12010 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12011 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12012 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12013 ok( ret
, "no message\n" );
12014 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12015 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
12016 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12017 ok( !ret
, "got message %x\n", msg
.message
);
12018 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12019 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12020 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12021 ok( !ret
, "got message %x\n", msg
.message
);
12023 /* interleaved sent message and winproc */
12025 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
12026 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
12027 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12028 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12029 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12030 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
12031 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12033 /* interleaved winproc and dispatch */
12035 msg
.message
= WM_CHAR
;
12036 msg
.wParam
= dbch
[0];
12038 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
12039 DispatchMessageA( &msg
);
12040 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12041 msg
.wParam
= dbch
[1];
12042 DispatchMessageA( &msg
);
12043 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12044 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
12045 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12047 /* interleaved sends */
12049 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
12050 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
12051 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
12052 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
12053 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12054 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
12055 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12059 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
12060 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
12061 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12062 ok( !ret
, "got message %x\n", msg
.message
);
12064 /* other char messages are not magic */
12065 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
12066 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12067 ok( ret
, "no message\n" );
12068 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
12069 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
12070 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12071 ok( !ret
, "got message %x\n", msg
.message
);
12072 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
12073 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12074 ok( ret
, "no message\n" );
12075 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
12076 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
12077 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12078 ok( !ret
, "got message %x\n", msg
.message
);
12080 /* test retrieving messages */
12082 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
12083 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12084 ok( ret
, "no message\n" );
12085 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12086 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12087 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12088 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12089 ok( ret
, "no message\n" );
12090 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12091 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12092 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12093 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12094 ok( !ret
, "got message %x\n", msg
.message
);
12096 /* message filters */
12097 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
12098 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12099 ok( ret
, "no message\n" );
12100 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12101 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12102 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12103 /* message id is filtered, hwnd is not */
12104 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
12105 ok( !ret
, "no message\n" );
12106 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
12107 ok( ret
, "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
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12111 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12112 ok( !ret
, "got message %x\n", msg
.message
);
12114 /* mixing GetMessage and PostMessage */
12115 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
12116 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "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
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12120 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
12123 ok( time
- GetTickCount() <= 100, "bad time %x\n", msg
.time
);
12124 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
12125 ok( ret
, "no message\n" );
12126 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12127 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12128 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12129 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
12130 ok( msg
.time
== time
, "bad time %x/%x\n", msg
.time
, time
);
12131 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
);
12132 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12133 ok( !ret
, "got message %x\n", msg
.message
);
12135 /* without PM_REMOVE */
12136 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
12137 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
12138 ok( ret
, "no message\n" );
12139 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12140 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12141 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12142 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
12143 ok( ret
, "no message\n" );
12144 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12145 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12146 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12147 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
12148 ok( ret
, "no message\n" );
12149 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12150 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12151 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12152 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
12153 ok( ret
, "no message\n" );
12154 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12155 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12156 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
12157 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
12158 ok( !ret
, "got message %x\n", msg
.message
);
12160 DestroyWindow(hwnd
);
12161 DestroyWindow(hwnd2
);
12164 static void test_unicode_wm_char(void)
12168 struct message seq
[2];
12169 HKL hkl_orig
, hkl_greek
;
12171 LCID thread_locale
;
12173 hkl_orig
= GetKeyboardLayout( 0 );
12174 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
12177 skip( "Default codepage %d\n", cp
);
12181 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
12182 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
12184 skip( "Unable to load Greek keyboard layout\n" );
12188 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
12189 100, 100, 200, 200, 0, 0, 0, NULL
);
12192 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
12194 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
12196 if (!ignore_message( msg
.message
)) break;
12199 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12200 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12201 ok( msg
.wParam
== 0x3b1, "bad wparam %lx\n", msg
.wParam
);
12202 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
12204 DispatchMessageW( &msg
);
12206 memset( seq
, 0, sizeof(seq
) );
12207 seq
[0].message
= WM_CHAR
;
12208 seq
[0].flags
= sent
|wparam
;
12209 seq
[0].wParam
= 0x3b1;
12211 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
12215 /* greek alpha -> 'a' in cp1252 */
12216 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
12218 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
12219 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12220 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12221 ok( msg
.wParam
== 0x61, "bad wparam %lx\n", msg
.wParam
);
12222 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
12224 DispatchMessageA( &msg
);
12226 seq
[0].wParam
= 0x61;
12227 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
12229 thread_locale
= GetThreadLocale();
12230 ActivateKeyboardLayout( hkl_greek
, 0 );
12231 ok( GetThreadLocale() == thread_locale
, "locale changed from %08x to %08x\n",
12232 thread_locale
, GetThreadLocale() );
12236 /* greek alpha -> 0xe1 in cp1253 */
12237 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
12239 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
12240 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
12241 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
12242 ok( msg
.wParam
== 0xe1, "bad wparam %lx\n", msg
.wParam
);
12243 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
12245 DispatchMessageA( &msg
);
12247 seq
[0].wParam
= 0x3b1;
12248 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
12250 DestroyWindow( hwnd
);
12251 ActivateKeyboardLayout( hkl_orig
, 0 );
12252 UnloadKeyboardLayout( hkl_greek
);
12255 #define ID_LISTBOX 0x000f
12257 static const struct message wm_lb_setcursel_0
[] =
12259 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
12260 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12261 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
12262 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12263 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12266 static const struct message wm_lb_setcursel_1
[] =
12268 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
12269 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12270 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
12271 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12272 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
12273 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
12274 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
12277 static const struct message wm_lb_setcursel_2
[] =
12279 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
12280 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12281 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
12282 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12283 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
12284 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
12285 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
12288 static const struct message wm_lb_click_0
[] =
12290 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
12291 { HCBT_SETFOCUS
, hook
},
12292 { WM_KILLFOCUS
, sent
|parent
},
12293 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
12294 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
12295 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12296 { WM_SETFOCUS
, sent
|defwinproc
},
12298 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
12299 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
12300 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
12301 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
12302 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
12304 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
12305 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12306 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
12307 { WM_CTLCOLORLISTBOX
, sent
|parent
},
12308 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
12309 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
12311 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12312 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
12314 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
12315 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
12316 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
12317 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
12320 static const struct message wm_lb_deletestring
[] =
12322 { LB_DELETESTRING
, sent
|wparam
|lparam
, 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
},
12328 static const struct message wm_lb_deletestring_reset
[] =
12330 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
12331 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
12332 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
12333 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
12334 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
12338 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
12340 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
12342 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12344 static LONG defwndproc_counter
= 0;
12346 struct recvd_message msg
;
12348 /* do not log painting messages */
12349 if (message
!= WM_PAINT
&&
12350 message
!= WM_NCPAINT
&&
12351 message
!= WM_SYNCPAINT
&&
12352 message
!= WM_ERASEBKGND
&&
12353 message
!= WM_NCHITTEST
&&
12354 message
!= WM_GETTEXT
&&
12355 !ignore_message( message
))
12358 msg
.message
= message
;
12359 msg
.flags
= sent
|wparam
|lparam
;
12360 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
12363 msg
.descr
= "listbox";
12367 defwndproc_counter
++;
12368 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
12369 defwndproc_counter
--;
12374 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
12375 int caret_index
, int top_index
, int line
)
12379 /* calling an orig proc helps to avoid unnecessary message logging */
12380 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
12381 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %ld\n", count
, ret
);
12382 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
12383 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %ld\n", cur_sel
, ret
);
12384 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
12385 ok_(__FILE__
, line
)(ret
== caret_index
||
12386 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
12387 "expected caret index %d, got %ld\n", caret_index
, ret
);
12388 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
12389 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %ld\n", top_index
, ret
);
12392 static void test_listbox_messages(void)
12394 HWND parent
, listbox
;
12397 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12398 100, 100, 200, 200, 0, 0, 0, NULL
);
12399 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
12400 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
12401 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
12402 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
12404 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
12406 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
12407 ok(ret
== 0, "expected 0, got %ld\n", ret
);
12408 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
12409 ok(ret
== 1, "expected 1, got %ld\n", ret
);
12410 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
12411 ok(ret
== 2, "expected 2, got %ld\n", ret
);
12413 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
12417 log_all_parent_messages
++;
12419 trace("selecting item 0\n");
12420 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
12421 ok(ret
== 0, "expected 0, got %ld\n", ret
);
12422 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
12423 check_lb_state(listbox
, 3, 0, 0, 0);
12426 trace("selecting item 1\n");
12427 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
12428 ok(ret
== 1, "expected 1, got %ld\n", ret
);
12429 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
12430 check_lb_state(listbox
, 3, 1, 1, 0);
12432 trace("selecting item 2\n");
12433 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
12434 ok(ret
== 2, "expected 2, got %ld\n", ret
);
12435 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
12436 check_lb_state(listbox
, 3, 2, 2, 0);
12438 trace("clicking on item 0\n");
12439 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
12440 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
12441 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
12442 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
12443 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
12444 check_lb_state(listbox
, 3, 0, 0, 0);
12447 trace("deleting item 0\n");
12448 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12449 ok(ret
== 2, "expected 2, got %ld\n", ret
);
12450 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
12451 check_lb_state(listbox
, 2, -1, 0, 0);
12454 trace("deleting item 0\n");
12455 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12456 ok(ret
== 1, "expected 1, got %ld\n", ret
);
12457 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
12458 check_lb_state(listbox
, 1, -1, 0, 0);
12461 trace("deleting item 0\n");
12462 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12463 ok(ret
== 0, "expected 0, got %ld\n", ret
);
12464 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
12465 check_lb_state(listbox
, 0, -1, 0, 0);
12468 trace("deleting item 0\n");
12469 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
12470 ok(ret
== LB_ERR
, "expected LB_ERR, got %ld\n", ret
);
12471 check_lb_state(listbox
, 0, -1, 0, 0);
12474 log_all_parent_messages
--;
12476 DestroyWindow(listbox
);
12477 DestroyWindow(parent
);
12480 /*************************** Menu test ******************************/
12481 static const struct message wm_popup_menu_1
[] =
12483 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12484 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12485 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
12486 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
12487 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
12488 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
12489 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12490 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12491 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
12492 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
12493 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
12494 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
12495 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
12496 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
12497 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
12498 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
12499 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12500 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12501 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12502 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
12503 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
12504 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
12507 static const struct message wm_popup_menu_2
[] =
12509 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12510 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12511 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
12512 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
12513 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
12514 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
12515 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12516 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12517 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
12518 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
12519 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
12520 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
12521 { HCBT_CREATEWND
, hook
},
12522 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
12523 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
12524 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
12525 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
12526 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
12527 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
12528 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
12529 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
12530 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
12531 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
12532 { HCBT_DESTROYWND
, hook
},
12533 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12534 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
12535 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12536 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12537 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12538 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
12539 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
12540 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
12543 static const struct message wm_popup_menu_3
[] =
12545 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12546 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12547 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
12548 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
12549 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
12550 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
12551 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12552 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12553 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
12554 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
12555 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
12556 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
12557 { HCBT_CREATEWND
, hook
},
12558 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
12559 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
12560 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
12561 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
12562 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
12563 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
12564 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
12565 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
12566 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
12567 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
12568 { HCBT_DESTROYWND
, hook
},
12569 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12570 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
12571 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
12572 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12573 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12574 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
12575 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
12576 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
12580 static const struct message wm_single_menu_item
[] =
12582 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
12583 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
12584 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
12585 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
12586 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
12587 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
12588 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12589 { WM_INITMENU
, sent
|lparam
, 0, 0 },
12590 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
12591 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
12592 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
12593 { WM_MENUCOMMAND
, sent
},
12594 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
12595 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
12596 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
12597 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
12599 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
12600 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
12601 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
12602 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
12603 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
12607 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12609 if (message
== WM_ENTERIDLE
||
12610 message
== WM_INITMENU
||
12611 message
== WM_INITMENUPOPUP
||
12612 message
== WM_MENUSELECT
||
12613 message
== WM_PARENTNOTIFY
||
12614 message
== WM_ENTERMENULOOP
||
12615 message
== WM_EXITMENULOOP
||
12616 message
== WM_UNINITMENUPOPUP
||
12617 message
== WM_KEYDOWN
||
12618 message
== WM_KEYUP
||
12619 message
== WM_CHAR
||
12620 message
== WM_SYSKEYDOWN
||
12621 message
== WM_SYSKEYUP
||
12622 message
== WM_SYSCHAR
||
12623 message
== WM_COMMAND
||
12624 message
== WM_MENUCOMMAND
)
12626 struct recvd_message msg
;
12629 msg
.message
= message
;
12630 msg
.flags
= sent
|wparam
|lparam
;
12633 msg
.descr
= "parent_menu_proc";
12637 return DefWindowProcA(hwnd
, message
, wp
, lp
);
12640 static void set_menu_style(HMENU hmenu
, DWORD style
)
12645 mi
.cbSize
= sizeof(mi
);
12646 mi
.fMask
= MIM_STYLE
;
12647 mi
.dwStyle
= style
;
12648 SetLastError(0xdeadbeef);
12649 ret
= pSetMenuInfo(hmenu
, &mi
);
12650 ok(ret
, "SetMenuInfo error %u\n", GetLastError());
12653 static DWORD
get_menu_style(HMENU hmenu
)
12658 mi
.cbSize
= sizeof(mi
);
12659 mi
.fMask
= MIM_STYLE
;
12661 SetLastError(0xdeadbeef);
12662 ret
= pGetMenuInfo(hmenu
, &mi
);
12663 ok(ret
, "GetMenuInfo error %u\n", GetLastError());
12668 static void test_menu_messages(void)
12672 HMENU hmenu
, hmenu_popup
;
12676 if (!pGetMenuInfo
|| !pSetMenuInfo
)
12678 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n");
12682 cls
.lpfnWndProc
= parent_menu_proc
;
12683 cls
.cbClsExtra
= 0;
12684 cls
.cbWndExtra
= 0;
12685 cls
.hInstance
= GetModuleHandleA(0);
12687 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
12688 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
12689 cls
.lpszMenuName
= NULL
;
12690 cls
.lpszClassName
= "TestMenuClass";
12691 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
12692 if (!RegisterClassA(&cls
)) assert(0);
12694 SetLastError(0xdeadbeef);
12695 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12696 100, 100, 200, 200, 0, 0, 0, NULL
);
12697 ok(hwnd
!= 0, "LoadMenuA error %u\n", GetLastError());
12699 SetLastError(0xdeadbeef);
12700 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
12701 ok(hmenu
!= 0, "LoadMenuA error %u\n", GetLastError());
12703 SetMenu(hwnd
, hmenu
);
12704 SetForegroundWindow( hwnd
);
12707 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
12708 style
= get_menu_style(hmenu
);
12709 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
12711 hmenu_popup
= GetSubMenu(hmenu
, 0);
12712 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12713 style
= get_menu_style(hmenu_popup
);
12714 ok(style
== 0, "expected 0, got %u\n", style
);
12716 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
12717 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12718 style
= get_menu_style(hmenu_popup
);
12719 ok(style
== 0, "expected 0, got %u\n", style
);
12722 trace("testing a popup menu command\n");
12724 keybd_event(VK_MENU
, 0, 0, 0);
12725 keybd_event('E', 0, 0, 0);
12726 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
12727 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12728 keybd_event(VK_RETURN
, 0, 0, 0);
12729 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
12730 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12732 TranslateMessage(&msg
);
12733 DispatchMessageA(&msg
);
12735 if (!sequence_cnt
) /* we didn't get any message */
12737 skip( "queuing key events not supported\n" );
12740 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
12741 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
12743 win_skip( "menu tracking through VK_MENU not supported\n" );
12746 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
12748 /* Alt+F, Right, Enter */
12749 trace("testing submenu of a popup menu command\n");
12751 keybd_event(VK_MENU
, 0, 0, 0);
12752 keybd_event('F', 0, 0, 0);
12753 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
12754 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12755 keybd_event(VK_RIGHT
, 0, 0, 0);
12756 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
12757 keybd_event(VK_RETURN
, 0, 0, 0);
12758 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
12759 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12761 TranslateMessage(&msg
);
12762 DispatchMessageA(&msg
);
12764 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
12766 trace("testing single menu item command\n");
12768 keybd_event(VK_MENU
, 0, 0, 0);
12769 keybd_event('Q', 0, 0, 0);
12770 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
12771 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12772 keybd_event(VK_ESCAPE
, 0, 0, 0);
12773 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
12774 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12776 TranslateMessage(&msg
);
12777 DispatchMessageA(&msg
);
12779 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
12781 set_menu_style(hmenu
, 0);
12782 style
= get_menu_style(hmenu
);
12783 ok(style
== 0, "expected 0, got %u\n", style
);
12785 hmenu_popup
= GetSubMenu(hmenu
, 0);
12786 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12787 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
12788 style
= get_menu_style(hmenu_popup
);
12789 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
12791 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
12792 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
12793 style
= get_menu_style(hmenu_popup
);
12794 ok(style
== 0, "expected 0, got %u\n", style
);
12796 /* Alt+F, Right, Enter */
12797 trace("testing submenu of a popup menu command\n");
12799 keybd_event(VK_MENU
, 0, 0, 0);
12800 keybd_event('F', 0, 0, 0);
12801 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
12802 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
12803 keybd_event(VK_RIGHT
, 0, 0, 0);
12804 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
12805 keybd_event(VK_RETURN
, 0, 0, 0);
12806 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
12807 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
12809 TranslateMessage(&msg
);
12810 DispatchMessageA(&msg
);
12812 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
12815 DestroyWindow(hwnd
);
12816 DestroyMenu(hmenu
);
12820 static void test_paintingloop(void)
12824 paint_loop_done
= FALSE
;
12825 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
12826 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
12827 100, 100, 100, 100, 0, 0, 0, NULL
);
12828 ok(hwnd
!= 0, "PaintLoop window error %u\n", GetLastError());
12829 ShowWindow(hwnd
,SW_NORMAL
);
12832 while (!paint_loop_done
)
12835 if (PeekMessageA(&msg
, 0, 0, 0, 1))
12837 TranslateMessage(&msg
);
12838 DispatchMessageA(&msg
);
12841 DestroyWindow(hwnd
);
12844 static void test_defwinproc(void)
12848 BOOL gotwmquit
= FALSE
;
12849 hwnd
= CreateWindowExA(0, "static", "test_defwndproc", WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
12851 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
12852 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
12853 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
12854 DispatchMessageA( &msg
);
12856 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
12857 DestroyWindow( hwnd
);
12860 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
12861 static void clear_clipboard_(int line
, HWND hWnd
)
12864 succ
= OpenClipboard(hWnd
);
12865 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%u\n", GetLastError());
12866 succ
= EmptyClipboard();
12867 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%u\n", GetLastError());
12868 succ
= CloseClipboard();
12869 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%u\n", GetLastError());
12872 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
12873 static void expect_HWND_(int line
, HWND expected
, HWND got
)
12875 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
12878 static WNDPROC pOldViewerProc
;
12880 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12882 static BOOL recursion_guard
;
12884 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
12886 recursion_guard
= TRUE
;
12887 clear_clipboard(hWnd
);
12888 recursion_guard
= FALSE
;
12890 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
12893 static void test_clipboard_viewers(void)
12895 static struct message wm_change_cb_chain
[] =
12897 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
12900 static const struct message wm_clipboard_destroyed
[] =
12902 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12905 static struct message wm_clipboard_changed
[] =
12907 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12910 static struct message wm_clipboard_changed_and_owned
[] =
12912 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12913 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
12917 HINSTANCE hInst
= GetModuleHandleA(NULL
);
12918 HWND hWnd1
, hWnd2
, hWnd3
;
12922 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
12923 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
12924 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
12925 GetDesktopWindow(), NULL
, hInst
, NULL
);
12926 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
12927 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
12928 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
12929 GetDesktopWindow(), NULL
, hInst
, NULL
);
12930 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
12931 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
12932 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
12933 GetDesktopWindow(), NULL
, hInst
, NULL
);
12934 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
12935 assert(hWnd1
&& hWnd2
&& hWnd3
);
12939 /* Test getting the clipboard viewer and setting the viewer to NULL. */
12940 hOrigViewer
= GetClipboardViewer();
12941 hRet
= SetClipboardViewer(NULL
);
12942 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
12943 expect_HWND(hOrigViewer
, hRet
);
12944 expect_HWND(NULL
, GetClipboardViewer());
12946 /* Test registering hWnd1 as a viewer. */
12947 hRet
= SetClipboardViewer(hWnd1
);
12948 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
12949 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
12950 expect_HWND(NULL
, hRet
);
12951 expect_HWND(hWnd1
, GetClipboardViewer());
12953 /* Test that changing the clipboard actually refreshes the registered viewer. */
12954 clear_clipboard(hWnd1
);
12955 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
12956 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
12958 /* Again, but with different owner. */
12959 clear_clipboard(hWnd2
);
12960 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
12961 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
12963 /* Test re-registering same window. */
12964 hRet
= SetClipboardViewer(hWnd1
);
12965 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
12966 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
12967 expect_HWND(hWnd1
, hRet
);
12968 expect_HWND(hWnd1
, GetClipboardViewer());
12970 /* Test ChangeClipboardChain. */
12971 ChangeClipboardChain(hWnd2
, hWnd3
);
12972 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
12973 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
12974 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
12975 expect_HWND(hWnd1
, GetClipboardViewer());
12977 ChangeClipboardChain(hWnd2
, NULL
);
12978 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
12979 wm_change_cb_chain
[0].lParam
= 0;
12980 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
12981 expect_HWND(hWnd1
, GetClipboardViewer());
12983 ChangeClipboardChain(NULL
, hWnd2
);
12984 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", TRUE
);
12985 expect_HWND(hWnd1
, GetClipboardViewer());
12987 /* Actually change clipboard viewer with ChangeClipboardChain. */
12988 ChangeClipboardChain(hWnd1
, hWnd2
);
12989 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
12990 expect_HWND(hWnd2
, GetClipboardViewer());
12992 /* Test that no refresh messages are sent when viewer has unregistered. */
12993 clear_clipboard(hWnd2
);
12994 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
12996 /* Register hWnd1 again. */
12997 ChangeClipboardChain(hWnd2
, hWnd1
);
12998 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
12999 expect_HWND(hWnd1
, GetClipboardViewer());
13001 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
13002 * changes the clipboard. When this happens, the system shouldn't send
13003 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
13005 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
13006 clear_clipboard(hWnd2
);
13007 /* The clipboard owner is changed in recursive_viewer_proc: */
13008 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
13009 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
13011 /* Test unregistering. */
13012 ChangeClipboardChain(hWnd1
, NULL
);
13013 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
13014 expect_HWND(NULL
, GetClipboardViewer());
13016 clear_clipboard(hWnd1
);
13017 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
13019 DestroyWindow(hWnd1
);
13020 DestroyWindow(hWnd2
);
13021 DestroyWindow(hWnd3
);
13022 SetClipboardViewer(hOrigViewer
);
13025 static void test_PostMessage(void)
13027 static const struct
13033 { HWND_TOP
/* 0 */, TRUE
},
13034 { HWND_BROADCAST
, TRUE
},
13035 { HWND_BOTTOM
, TRUE
},
13036 { HWND_TOPMOST
, TRUE
},
13037 { HWND_NOTOPMOST
, FALSE
},
13038 { HWND_MESSAGE
, FALSE
},
13039 { (HWND
)0xdeadbeef, FALSE
}
13045 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
13047 SetLastError(0xdeadbeef);
13048 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
13049 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
13051 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
13058 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
13059 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
13061 for (i
= 0; i
< sizeof(data
)/sizeof(data
[0]); i
++)
13063 memset(&msg
, 0xab, sizeof(msg
));
13064 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
13065 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
13069 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
13070 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
13071 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
13072 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
13074 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
13075 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
13076 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
13077 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
13081 DestroyWindow(hwnd
);
13085 static const struct
13089 } wait_idle_expect
[] =
13091 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13092 { WAIT_TIMEOUT
, 0, FALSE
},
13093 { WAIT_TIMEOUT
, 0, FALSE
},
13094 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13095 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13096 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
13097 { WAIT_TIMEOUT
, 0, FALSE
},
13098 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
13101 /* 10 */ { 0, 0, FALSE
},
13103 { 0, WAIT_TIMEOUT
, FALSE
},
13106 /* 15 */ { 0, 0, FALSE
},
13107 { WAIT_TIMEOUT
, 0, FALSE
},
13108 { WAIT_TIMEOUT
, 0, FALSE
},
13109 { WAIT_TIMEOUT
, 0, FALSE
},
13110 { WAIT_TIMEOUT
, 0, FALSE
},
13111 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
13114 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
13118 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13120 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
13124 static void do_wait_idle_child( int arg
)
13131 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
13132 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
13134 memset( &cls
, 0, sizeof(cls
) );
13135 cls
.lpfnWndProc
= DefWindowProcA
;
13136 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
13137 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
13138 cls
.lpszClassName
= "TestClass";
13139 RegisterClassA( &cls
);
13141 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
13143 ok( start_event
!= 0, "failed to create start event, error %u\n", GetLastError() );
13144 ok( end_event
!= 0, "failed to create end event, error %u\n", GetLastError() );
13149 SetEvent( start_event
);
13152 SetEvent( start_event
);
13154 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
13157 SetEvent( start_event
);
13159 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13160 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
13161 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
13164 SetEvent( start_event
);
13166 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
13169 SetEvent( start_event
);
13171 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13172 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
13175 SetEvent( start_event
);
13177 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13178 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
13181 SetEvent( start_event
);
13183 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13184 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
13186 GetMessageA( &msg
, 0, 0, 0 );
13187 DispatchMessageA( &msg
);
13191 SetEvent( start_event
);
13193 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13194 SetTimer( hwnd
, 3, 1, NULL
);
13196 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
13199 SetEvent( start_event
);
13201 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13202 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
13205 SetEvent( start_event
);
13207 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13208 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
13209 for (;;) GetMessageA( &msg
, 0, 0, 0 );
13212 SetEvent( start_event
);
13214 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13215 SetTimer( hwnd
, 3, 1, NULL
);
13217 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
13220 SetEvent( start_event
);
13222 return; /* exiting the process makes WaitForInputIdle return success too */
13224 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13226 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
13227 SetEvent( start_event
);
13230 SetEvent( start_event
);
13231 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13233 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
13234 WaitForSingleObject( thread
, 10000 );
13235 CloseHandle( thread
);
13238 SetEvent( start_event
);
13240 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
13243 SetEvent( start_event
);
13245 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
13248 SetEvent( start_event
);
13250 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
13253 SetEvent( start_event
);
13255 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
13258 SetEvent( start_event
);
13260 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
13263 SetEvent( start_event
);
13265 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
13268 SetEvent( start_event
);
13270 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
13273 WaitForSingleObject( end_event
, 2000 );
13274 CloseHandle( start_event
);
13275 CloseHandle( end_event
);
13276 if (hwnd
) DestroyWindow( hwnd
);
13279 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
13281 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
13282 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
13285 static DWORD CALLBACK
wait_idle_thread( void *arg
)
13291 memset( &cls
, 0, sizeof(cls
) );
13292 cls
.lpfnWndProc
= wait_idle_proc
;
13293 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
13294 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
13295 cls
.lpszClassName
= "TestClass";
13296 RegisterClassA( &cls
);
13298 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
13299 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
13300 DestroyWindow(hwnd
);
13304 static void test_WaitForInputIdle( char *argv0
)
13306 char path
[MAX_PATH
];
13307 PROCESS_INFORMATION pi
;
13308 STARTUPINFOA startup
;
13310 HANDLE start_event
, end_event
, thread
;
13313 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
13314 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
13315 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
13317 if (console_app
) /* build the test with -mwindows for better coverage */
13318 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
13320 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
13321 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
13322 ok(start_event
!= 0, "failed to create start event, error %u\n", GetLastError());
13323 ok(end_event
!= 0, "failed to create end event, error %u\n", GetLastError());
13325 memset( &startup
, 0, sizeof(startup
) );
13326 startup
.cb
= sizeof(startup
);
13327 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
13328 startup
.wShowWindow
= SW_SHOWNORMAL
;
13330 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
13332 for (i
= 0; i
< sizeof(wait_idle_expect
)/sizeof(wait_idle_expect
[0]); i
++)
13334 ResetEvent( start_event
);
13335 ResetEvent( end_event
);
13336 sprintf( path
, "%s msg %u", argv0
, i
);
13337 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
13338 ok( ret
, "CreateProcess '%s' failed err %u.\n", path
, GetLastError() );
13341 ret
= WaitForSingleObject( start_event
, 5000 );
13342 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
13343 if (ret
== WAIT_OBJECT_0
)
13345 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
13346 if (ret
== WAIT_FAILED
)
13348 ret
== wait_idle_expect
[i
].exp
||
13349 broken(ret
== wait_idle_expect
[i
].broken
),
13350 "%u: WaitForInputIdle error %08x expected %08x\n",
13351 i
, ret
, wait_idle_expect
[i
].exp
);
13352 else if (wait_idle_expect
[i
].todo
)
13354 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
13355 "%u: WaitForInputIdle error %08x expected %08x\n",
13356 i
, ret
, wait_idle_expect
[i
].exp
);
13358 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
13359 "%u: WaitForInputIdle error %08x expected %08x\n",
13360 i
, ret
, wait_idle_expect
[i
].exp
);
13361 SetEvent( end_event
);
13362 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
13364 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
13365 winetest_wait_child_process( pi
.hProcess
);
13366 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
13367 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
13368 CloseHandle( pi
.hProcess
);
13369 CloseHandle( pi
.hThread
);
13372 CloseHandle( start_event
);
13373 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
13374 WaitForSingleObject( thread
, 10000 );
13375 CloseHandle( thread
);
13378 static const struct message WmSetParentSeq_1
[] = {
13379 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
13380 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13381 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
13382 { WM_CHILDACTIVATE
, sent
},
13383 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
13384 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
13385 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13386 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13390 static const struct message WmSetParentSeq_2
[] = {
13391 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
13392 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13393 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13394 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13395 { HCBT_SETFOCUS
, hook
|optional
},
13396 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
13397 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
13398 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13399 { WM_KILLFOCUS
, sent
|wparam
, 0 },
13400 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13401 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
13402 { HCBT_ACTIVATE
, hook
|optional
},
13403 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
13404 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13405 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
13406 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
13407 { HCBT_SETFOCUS
, hook
|optional
},
13408 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13409 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
13410 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
13411 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
13412 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
13413 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
13414 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
13415 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
13416 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13421 static void test_SetParent(void)
13423 HWND parent1
, parent2
, child
, popup
;
13426 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
13427 100, 100, 200, 200, 0, 0, 0, NULL
);
13428 ok(parent1
!= 0, "Failed to create parent1 window\n");
13430 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
13431 400, 100, 200, 200, 0, 0, 0, NULL
);
13432 ok(parent2
!= 0, "Failed to create parent2 window\n");
13434 /* WS_CHILD window */
13435 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
13436 10, 10, 150, 150, parent1
, 0, 0, NULL
);
13437 ok(child
!= 0, "Failed to create child window\n");
13439 GetWindowRect(parent1
, &rc
);
13440 trace("parent1 (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13441 GetWindowRect(child
, &rc_old
);
13442 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
13443 trace("child (%d,%d)-(%d,%d)\n", rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
);
13447 SetParent(child
, parent2
);
13449 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", TRUE
);
13451 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
13452 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
13454 GetWindowRect(parent2
, &rc
);
13455 trace("parent2 (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13456 GetWindowRect(child
, &rc
);
13457 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
13458 trace("child (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13460 ok(EqualRect(&rc_old
, &rc
), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
13461 rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
,
13462 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13464 /* WS_POPUP window */
13465 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
13466 20, 20, 100, 100, 0, 0, 0, NULL
);
13467 ok(popup
!= 0, "Failed to create popup window\n");
13469 GetWindowRect(popup
, &rc_old
);
13470 trace("popup (%d,%d)-(%d,%d)\n", rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
);
13474 SetParent(popup
, child
);
13476 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
13478 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
13479 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
13481 GetWindowRect(child
, &rc
);
13482 trace("parent2 (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13483 GetWindowRect(popup
, &rc
);
13484 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
13485 trace("popup (%d,%d)-(%d,%d)\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13487 ok(EqualRect(&rc_old
, &rc
), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
13488 rc_old
.left
, rc_old
.top
, rc_old
.right
, rc_old
.bottom
,
13489 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
13491 DestroyWindow(popup
);
13492 DestroyWindow(child
);
13493 DestroyWindow(parent1
);
13494 DestroyWindow(parent2
);
13499 static const struct message WmKeyReleaseOnly
[] = {
13500 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
13501 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
13504 static const struct message WmKeyPressNormal
[] = {
13505 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
13506 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
13509 static const struct message WmKeyPressRepeat
[] = {
13510 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
13511 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
13514 static const struct message WmKeyReleaseNormal
[] = {
13515 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
13516 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
13520 static void test_keyflags(void)
13524 BYTE keyboard_state
[256];
13527 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13528 100, 100, 200, 200, 0, 0, 0, NULL
);
13533 /* keyup without a keydown */
13534 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
13535 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13536 DispatchMessageA(&msg
);
13537 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
13539 key_state
= GetAsyncKeyState(0x41);
13540 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13542 key_state
= GetKeyState(0x41);
13543 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13546 keybd_event(0x41, 0, 0, 0);
13547 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13548 DispatchMessageA(&msg
);
13549 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
13551 key_state
= GetAsyncKeyState(0x41);
13552 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13554 key_state
= GetKeyState(0x41);
13555 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13557 /* keydown repeat */
13558 keybd_event(0x41, 0, 0, 0);
13559 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13560 DispatchMessageA(&msg
);
13561 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
13563 key_state
= GetAsyncKeyState(0x41);
13564 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13566 key_state
= GetKeyState(0x41);
13567 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13570 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
13571 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13572 DispatchMessageA(&msg
);
13573 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
13575 key_state
= GetAsyncKeyState(0x41);
13576 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13578 key_state
= GetKeyState(0x41);
13579 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13581 /* set the key state in this thread */
13582 GetKeyboardState(keyboard_state
);
13583 keyboard_state
[0x41] = 0x80;
13584 SetKeyboardState(keyboard_state
);
13586 key_state
= GetAsyncKeyState(0x41);
13587 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13590 keybd_event(0x41, 0, 0, 0);
13591 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13592 DispatchMessageA(&msg
);
13593 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
13595 key_state
= GetAsyncKeyState(0x41);
13596 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13598 key_state
= GetKeyState(0x41);
13599 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13601 /* clear the key state in this thread */
13602 GetKeyboardState(keyboard_state
);
13603 keyboard_state
[0x41] = 0;
13604 SetKeyboardState(keyboard_state
);
13606 key_state
= GetAsyncKeyState(0x41);
13607 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13610 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
13611 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
13612 DispatchMessageA(&msg
);
13613 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
13615 key_state
= GetAsyncKeyState(0x41);
13616 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13618 key_state
= GetKeyState(0x41);
13619 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
13621 DestroyWindow(test_window
);
13625 static const struct message WmHotkeyPressLWIN
[] = {
13626 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
13627 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
13628 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
13631 static const struct message WmHotkeyPress
[] = {
13632 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13633 { WM_HOTKEY
, sent
|wparam
, 5 },
13636 static const struct message WmHotkeyRelease
[] = {
13637 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13638 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
13639 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
13642 static const struct message WmHotkeyReleaseLWIN
[] = {
13643 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
13644 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
13645 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
13648 static const struct message WmHotkeyCombined
[] = {
13649 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
13650 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13651 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13652 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
13653 { WM_APP
, sent
, 0, 0 },
13654 { WM_HOTKEY
, sent
|wparam
, 5 },
13655 { WM_APP
+1, sent
, 0, 0 },
13656 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
13657 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
13658 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
13659 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
13660 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
13661 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
13664 static const struct message WmHotkeyPrevious
[] = {
13665 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
13666 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13667 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13668 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
13669 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
13670 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
13671 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
13672 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
13673 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
13674 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
13675 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
13676 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
13679 static const struct message WmHotkeyNew
[] = {
13680 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
13681 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
13682 { WM_HOTKEY
, sent
|wparam
, 5 },
13683 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
13684 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
13688 static int hotkey_letter
;
13690 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
13692 struct recvd_message msg
;
13694 if (nCode
== HC_ACTION
)
13696 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
13699 msg
.message
= wParam
;
13700 msg
.flags
= kbd_hook
|wparam
|lparam
;
13701 msg
.wParam
= kdbhookstruct
->vkCode
;
13702 msg
.lParam
= kdbhookstruct
->flags
;
13703 msg
.descr
= "KeyboardHookProc";
13706 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
)
13708 ok(kdbhookstruct
->vkCode
== VK_LWIN
|| kdbhookstruct
->vkCode
== hotkey_letter
,
13709 "unexpected keycode %x\n", kdbhookstruct
->vkCode
);
13713 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
13716 static void test_hotkey(void)
13718 HWND test_window
, taskbar_window
;
13721 DWORD queue_status
;
13724 SetLastError(0xdeadbeef);
13725 ret
= UnregisterHotKey(NULL
, 0);
13726 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13727 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13728 "unexpected error %d\n", GetLastError());
13732 skip("hotkeys not supported\n");
13736 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13737 100, 100, 200, 200, 0, 0, 0, NULL
);
13741 SetLastError(0xdeadbeef);
13742 ret
= UnregisterHotKey(test_window
, 0);
13743 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13744 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13745 "unexpected error %d\n", GetLastError());
13747 /* Search for a Windows Key + letter combination that hasn't been registered */
13748 for (hotkey_letter
= 0x41; hotkey_letter
<= 0x51; hotkey_letter
++)
13750 SetLastError(0xdeadbeef);
13751 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
13759 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13760 "unexpected error %d\n", GetLastError());
13764 if (hotkey_letter
== 0x52)
13766 ok(0, "Couldn't find any free Windows Key + letter combination\n");
13770 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
13771 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
13773 /* Same key combination, different id */
13774 SetLastError(0xdeadbeef);
13775 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
13776 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13777 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13778 "unexpected error %d\n", GetLastError());
13780 /* Same key combination, different window */
13781 SetLastError(0xdeadbeef);
13782 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
13783 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13784 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13785 "unexpected error %d\n", GetLastError());
13787 /* Register the same hotkey twice */
13788 SetLastError(0xdeadbeef);
13789 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
13790 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13791 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13792 "unexpected error %d\n", GetLastError());
13794 /* Window on another thread */
13795 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
13796 if (!taskbar_window
)
13798 skip("no taskbar?\n");
13802 SetLastError(0xdeadbeef);
13803 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
13804 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13805 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
13806 "unexpected error %d\n", GetLastError());
13809 /* Inject the appropriate key sequence */
13810 keybd_event(VK_LWIN
, 0, 0, 0);
13811 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13812 DispatchMessageA(&msg
);
13813 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
13815 keybd_event(hotkey_letter
, 0, 0, 0);
13816 queue_status
= GetQueueStatus(QS_HOTKEY
);
13817 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
13818 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13820 if (msg
.message
== WM_HOTKEY
)
13822 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
13823 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13825 DispatchMessageA(&msg
);
13827 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
13829 queue_status
= GetQueueStatus(QS_HOTKEY
);
13830 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
13832 key_state
= GetAsyncKeyState(hotkey_letter
);
13833 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
13835 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13836 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13837 DispatchMessageA(&msg
);
13838 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
13840 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13841 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13842 DispatchMessageA(&msg
);
13843 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
13845 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
13846 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
13847 queue_status
= GetQueueStatus(QS_HOTKEY
);
13848 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
13849 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
13850 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
13851 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13852 DispatchMessageA(&msg
);
13855 /* Send and process all messages at once */
13856 PostMessageA(test_window
, WM_APP
, 0, 0);
13857 keybd_event(VK_LWIN
, 0, 0, 0);
13858 keybd_event(hotkey_letter
, 0, 0, 0);
13859 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13860 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13862 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13864 if (msg
.message
== WM_HOTKEY
)
13866 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
13867 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13869 DispatchMessageA(&msg
);
13871 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
13873 /* Register same hwnd/id with different key combination */
13874 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
13875 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13877 /* Previous key combination does not work */
13878 keybd_event(VK_LWIN
, 0, 0, 0);
13879 keybd_event(hotkey_letter
, 0, 0, 0);
13880 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13881 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13883 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13884 DispatchMessageA(&msg
);
13885 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
13887 /* New key combination works */
13888 keybd_event(hotkey_letter
, 0, 0, 0);
13889 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13891 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13893 if (msg
.message
== WM_HOTKEY
)
13895 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
13896 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13898 DispatchMessageA(&msg
);
13900 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
13902 /* Unregister hotkey properly */
13903 ret
= UnregisterHotKey(test_window
, 5);
13904 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13906 /* Unregister hotkey again */
13907 SetLastError(0xdeadbeef);
13908 ret
= UnregisterHotKey(test_window
, 5);
13909 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
13910 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
13911 "unexpected error %d\n", GetLastError());
13913 /* Register thread hotkey */
13914 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
13915 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13917 /* Inject the appropriate key sequence */
13918 keybd_event(VK_LWIN
, 0, 0, 0);
13919 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13921 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13922 DispatchMessageA(&msg
);
13924 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
13926 keybd_event(hotkey_letter
, 0, 0, 0);
13927 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13929 if (msg
.message
== WM_HOTKEY
)
13931 struct recvd_message message
;
13932 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
13933 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
13934 message
.message
= msg
.message
;
13935 message
.flags
= sent
|wparam
|lparam
;
13936 message
.wParam
= msg
.wParam
;
13937 message
.lParam
= msg
.lParam
;
13938 message
.descr
= "test_hotkey thread message";
13939 add_message(&message
);
13942 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13943 DispatchMessageA(&msg
);
13945 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
13947 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
13948 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13950 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13951 DispatchMessageA(&msg
);
13953 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
13955 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
13956 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
13958 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
13959 DispatchMessageA(&msg
);
13961 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
13963 /* Unregister thread hotkey */
13964 ret
= UnregisterHotKey(NULL
, 5);
13965 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
13967 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
13971 UnregisterHotKey(NULL
, 5);
13972 UnregisterHotKey(test_window
, 5);
13973 DestroyWindow(test_window
);
13978 static const struct message WmSetFocus_1
[] = {
13979 { HCBT_SETFOCUS
, hook
}, /* child */
13980 { HCBT_ACTIVATE
, hook
}, /* parent */
13981 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
13982 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
13983 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
13984 { WM_NCACTIVATE
, sent
|parent
},
13985 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
13986 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
13987 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
13988 { HCBT_SETFOCUS
, hook
}, /* parent */
13989 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
13990 { WM_KILLFOCUS
, sent
|parent
},
13991 { WM_SETFOCUS
, sent
},
13994 static const struct message WmSetFocus_2
[] = {
13995 { HCBT_SETFOCUS
, hook
}, /* parent */
13996 { WM_KILLFOCUS
, sent
},
13997 { WM_SETFOCUS
, sent
|parent
},
14000 static const struct message WmSetFocus_3
[] = {
14001 { HCBT_SETFOCUS
, hook
}, /* child */
14005 static void test_SetFocus(void)
14007 HWND parent
, old_parent
, child
, old_focus
, old_active
;
14009 struct wnd_event wnd_event
;
14013 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
14014 ok(wnd_event
.start_event
!= 0, "CreateEvent error %d\n", GetLastError());
14015 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
14016 ok(hthread
!= 0, "CreateThread error %d\n", GetLastError());
14017 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
14018 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
14019 CloseHandle(wnd_event
.start_event
);
14021 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
14022 0, 0, 0, 0, 0, 0, 0, NULL
);
14023 ok(parent
!= 0, "failed to create parent window\n");
14024 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
14025 0, 0, 0, 0, parent
, 0, 0, NULL
);
14026 ok(child
!= 0, "failed to create child window\n");
14028 trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
14031 SetActiveWindow(0);
14036 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
14037 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
14039 log_all_parent_messages
++;
14041 old_focus
= SetFocus(child
);
14042 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14043 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
14044 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
14045 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14046 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
14048 old_focus
= SetFocus(parent
);
14049 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14050 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
14051 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
14052 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14053 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14055 SetLastError(0xdeadbeef);
14056 old_focus
= SetFocus((HWND
)0xdeadbeef);
14057 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14058 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
14059 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14060 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
14061 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14062 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14063 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14065 SetLastError(0xdeadbeef);
14066 old_focus
= SetFocus(GetDesktopWindow());
14067 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
14068 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
14069 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14070 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
14071 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14072 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14073 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14075 SetLastError(0xdeadbeef);
14076 old_focus
= SetFocus(wnd_event
.hwnd
);
14077 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
14078 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
14079 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14080 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
14081 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14082 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14083 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14085 SetLastError(0xdeadbeef);
14086 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
14087 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14088 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
14089 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14090 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
14091 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
14092 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14093 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14095 SetLastError(0xdeadbeef);
14096 old_active
= SetActiveWindow(GetDesktopWindow());
14098 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
14099 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14100 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
14101 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
14102 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14103 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14105 SetLastError(0xdeadbeef);
14106 old_active
= SetActiveWindow(wnd_event
.hwnd
);
14108 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
14109 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14110 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
14111 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
14112 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14113 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14115 SetLastError(0xdeadbeef);
14116 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
14117 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
14120 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14121 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14126 old_focus
= SetFocus(wnd_event
.hwnd
);
14127 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14128 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
14129 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
14130 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
14132 old_focus
= SetFocus(parent
);
14133 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14134 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
14135 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14136 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14141 old_active
= SetActiveWindow(wnd_event
.hwnd
);
14142 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14143 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
14144 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
14145 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
14147 SetLastError(0xdeadbeef);
14148 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
14149 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
14151 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
14152 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
14154 old_parent
= SetParent(child
, GetDesktopWindow());
14155 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
14157 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
14158 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
14160 old_focus
= SetFocus(parent
);
14161 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14162 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
14163 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14164 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14169 SetLastError(0xdeadbeef);
14170 old_focus
= SetFocus(child
);
14172 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
14173 broken(GetLastError() == 0) /* XP */ ||
14174 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
14175 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14176 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
14177 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
14178 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14179 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14181 SetLastError(0xdeadbeef);
14182 old_active
= SetActiveWindow(child
);
14183 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
14184 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
14185 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
14186 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
14187 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
14188 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
14190 log_all_parent_messages
--;
14192 DestroyWindow(child
);
14193 DestroyWindow(parent
);
14195 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
14196 ok(ret
, "PostMessage(WM_QUIT) error %d\n", GetLastError());
14197 ret
= WaitForSingleObject(hthread
, INFINITE
);
14198 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
14199 CloseHandle(hthread
);
14202 static const struct message WmSetLayeredStyle
[] = {
14203 { WM_STYLECHANGING
, sent
},
14204 { WM_STYLECHANGED
, sent
},
14205 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14209 static const struct message WmSetLayeredStyle2
[] = {
14210 { WM_STYLECHANGING
, sent
},
14211 { WM_STYLECHANGED
, sent
},
14212 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14213 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
14214 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
14215 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
14216 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
14220 struct layered_window_info
14229 static DWORD CALLBACK
update_layered_proc( void *param
)
14231 struct layered_window_info
*info
= param
;
14232 POINT src
= { 0, 0 };
14234 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
14235 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14236 ok( info
->ret
, "failed\n");
14237 SetEvent( info
->event
);
14241 static void test_layered_window(void)
14252 struct layered_window_info info
;
14254 if (!pUpdateLayeredWindow
)
14256 win_skip( "UpdateLayeredWindow not supported\n" );
14260 hdc
= CreateCompatibleDC( 0 );
14261 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
14262 SelectObject( hdc
, bmp
);
14264 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
14265 100, 100, 300, 300, 0, 0, 0, NULL
);
14266 ok( hwnd
!= 0, "failed to create window\n" );
14267 ShowWindow( hwnd
, SW_SHOWNORMAL
);
14268 UpdateWindow( hwnd
);
14272 GetWindowRect( hwnd
, &rect
);
14273 GetClientRect( hwnd
, &client
);
14274 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
14275 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
14278 pos
.x
= pos
.y
= 300;
14279 size
.cx
= size
.cy
= 250;
14280 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14281 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
14282 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
14283 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
14284 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
14286 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14287 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
14288 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
14289 GetWindowRect( hwnd
, &rect
);
14290 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
14291 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14292 GetClientRect( hwnd
, &rect
);
14293 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
14294 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14298 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14299 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
14300 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
14301 GetWindowRect( hwnd
, &rect
);
14302 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
14303 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14304 GetClientRect( hwnd
, &rect
);
14305 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
14306 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14308 SetWindowLongA( hwnd
, GWL_STYLE
,
14309 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
14310 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
14314 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14315 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
14316 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
14317 GetWindowRect( hwnd
, &rect
);
14318 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
14319 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14320 GetClientRect( hwnd
, &rect
);
14321 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
14322 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
14323 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
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
|| broken(ERROR_MR_MID_NOT_FOUND
) /* win7 */,
14329 "wrong error %u\n", GetLastError() );
14332 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
14333 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
14334 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
14336 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
14337 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
14338 GetWindowRect( hwnd
, &rect
);
14339 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
14340 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14341 GetClientRect( hwnd
, &rect
);
14342 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
14343 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
14344 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14346 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
14349 info
.size
.cx
= 250;
14350 info
.size
.cy
= 300;
14351 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
14353 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
14354 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
14355 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
14356 WaitForSingleObject( thread
, 1000 );
14357 CloseHandle( thread
);
14358 GetWindowRect( hwnd
, &rect
);
14359 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
14360 "wrong window rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14361 GetClientRect( hwnd
, &rect
);
14362 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
14363 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
14364 "wrong client rect %d,%d,%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
14366 DestroyWindow( hwnd
);
14368 DeleteObject( bmp
);
14371 static HMENU hpopupmenu
;
14373 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14375 if (ignore_message( message
)) return 0;
14379 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
14383 case WM_INITMENUPOPUP
:
14384 case WM_UNINITMENUPOPUP
:
14385 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %lx\n", hpopupmenu
, wParam
);
14387 case WM_CAPTURECHANGED
:
14388 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %lx\n", lParam
);
14392 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
14395 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14397 if (ignore_message( message
)) return 0;
14400 case WM_ENTERMENULOOP
:
14401 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
14405 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
14408 static void test_TrackPopupMenu(void)
14413 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
14416 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
14418 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
14420 hpopupmenu
= CreatePopupMenu();
14421 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
14423 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
14424 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
14428 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14429 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
14430 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
14432 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
14436 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14437 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
14438 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
14440 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
14446 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14447 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
14448 ok(ret
== 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError());
14450 DestroyMenu(hpopupmenu
);
14451 DestroyWindow(hwnd
);
14454 static void test_TrackPopupMenuEmpty(void)
14459 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
14462 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
14464 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
14466 hpopupmenu
= CreatePopupMenu();
14467 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
14471 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
14472 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
14473 todo_wine
ok(ret
== 0, "TrackPopupMenu succeeded\n");
14475 DestroyMenu(hpopupmenu
);
14476 DestroyWindow(hwnd
);
14479 static void init_funcs(void)
14481 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
14483 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
14486 X(DeactivateActCtx
);
14487 X(GetCurrentActCtx
);
14496 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
14497 HMODULE hModuleImm32
;
14498 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
14503 argc
= winetest_get_mainargs( &test_argv
);
14507 /* Child process. */
14508 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
14509 do_wait_idle_child( arg
);
14513 InitializeCriticalSection( &sequence_cs
);
14516 hModuleImm32
= LoadLibraryA("imm32.dll");
14517 if (hModuleImm32
) {
14518 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
14519 if (pImmDisableIME
)
14522 pImmDisableIME
= NULL
;
14523 FreeLibrary(hModuleImm32
);
14525 if (!RegisterWindowClasses()) assert(0);
14527 if (pSetWinEventHook
)
14529 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
14530 GetModuleHandleA(0), win_event_proc
,
14531 0, GetCurrentThreadId(),
14532 WINEVENT_INCONTEXT
);
14533 if (pIsWinEventHookInstalled
&& hEvent_hook
)
14536 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
14537 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
14540 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
14542 cbt_hook_thread_id
= GetCurrentThreadId();
14543 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
14544 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
14548 /* Fix message sequences before removing 4 lines below */
14549 if (pUnhookWinEvent
&& hEvent_hook
)
14551 ret
= pUnhookWinEvent(hEvent_hook
);
14552 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
14553 pUnhookWinEvent
= 0;
14558 test_PostMessage();
14560 test_PeekMessage();
14561 test_PeekMessage2();
14562 test_WaitForInputIdle( test_argv
[0] );
14563 test_scrollwindowex();
14565 test_setwindowpos();
14567 invisible_parent_tests();
14568 test_mdi_messages();
14569 test_button_messages();
14570 test_static_messages();
14571 test_listbox_messages();
14572 test_combobox_messages();
14573 test_wmime_keydown_message();
14574 test_paint_messages();
14575 test_interthread_messages();
14576 test_message_conversion();
14577 test_accelerators();
14579 test_timers_no_wnd();
14580 test_timers_exceptions();
14581 if (hCBT_hook
) test_set_hook();
14582 test_DestroyWindow();
14583 test_DispatchMessage();
14584 test_SendMessageTimeout();
14585 test_edit_messages();
14586 test_quit_message();
14587 test_SetActiveWindow();
14589 if (!pTrackMouseEvent
)
14590 win_skip("TrackMouseEvent is not available\n");
14592 test_TrackMouseEvent();
14594 test_SetWindowRgn();
14596 test_dialog_messages();
14598 test_nullCallback();
14599 test_dbcs_wm_char();
14600 test_unicode_wm_char();
14601 test_menu_messages();
14602 test_paintingloop();
14604 test_clipboard_viewers();
14607 test_layered_window();
14608 test_TrackPopupMenu();
14609 test_TrackPopupMenuEmpty();
14610 /* keep it the last test, under Windows it tends to break the tests
14611 * which rely on active/foreground windows being correct.
14613 test_SetForegroundWindow();
14615 UnhookWindowsHookEx(hCBT_hook
);
14616 if (pUnhookWinEvent
&& hEvent_hook
)
14618 ret
= pUnhookWinEvent(hEvent_hook
);
14619 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
14620 SetLastError(0xdeadbeef);
14621 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
14622 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
14623 GetLastError() == 0xdeadbeef, /* Win9x */
14624 "unexpected error %d\n", GetLastError());
14626 DeleteCriticalSection( &sequence_cs
);