2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/test.h"
35 FIXME: add tests for these
36 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
37 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
38 WS_THICKFRAME: thick border
39 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
40 WS_BORDER (default for overlapped windows): single black border
41 none (default for child (and popup?) windows): no border
45 sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10,
46 defwinproc=0x20, optional=0x40, hook=0x80
50 UINT message; /* the WM_* code */
51 msg_flags_t flags; /* message props */
52 WPARAM wParam; /* expected value of wParam */
53 LPARAM lParam; /* expected value of lParam */
56 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
57 static const struct message WmCreateOverlappedSeq[] = {
58 { HCBT_CREATEWND, hook },
59 { WM_GETMINMAXINFO, sent },
60 { WM_NCCREATE, sent },
61 { WM_NCCALCSIZE, sent|wparam, 0 },
65 /* ShowWindow (for overlapped window) (16/32) */
66 static const struct message WmShowOverlappedSeq[] = {
67 { WM_SHOWWINDOW, sent|wparam, 1 },
68 { WM_NCPAINT, sent|wparam|optional, 1 },
69 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
70 { WM_NCPAINT, sent|wparam|optional, 1 },
71 { WM_GETTEXT, sent|defwinproc|optional },
72 { WM_ERASEBKGND, sent|optional },
73 { HCBT_ACTIVATE, hook },
74 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
75 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
76 { WM_ACTIVATEAPP, sent|wparam, 1 },
77 { WM_NCACTIVATE, sent|wparam, 1 },
78 { WM_GETTEXT, sent|defwinproc },
79 { WM_ACTIVATE, sent|wparam, 1 },
80 { HCBT_SETFOCUS, hook },
81 { WM_IME_SETCONTEXT, sent|defwinproc|optional },
82 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
83 { WM_NCPAINT, sent|wparam|optional, 1 },
84 { WM_GETTEXT, sent|defwinproc|optional },
85 { WM_ERASEBKGND, sent|optional },
86 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
91 /* DestroyWindow (for overlapped window) (32) */
92 static const struct message WmDestroyOverlappedSeq[] = {
93 { HCBT_DESTROYWND, hook },
94 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
95 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
96 { WM_NCACTIVATE, sent|wparam, 0 },
97 { WM_ACTIVATE, sent|wparam, 0 },
98 { WM_ACTIVATEAPP, sent|wparam, 0 },
99 { WM_KILLFOCUS, sent|wparam, 0 },
100 { WM_IME_SETCONTEXT, sent|optional },
101 { WM_DESTROY, sent },
102 { WM_NCDESTROY, sent },
105 /* CreateWindow (for a child popup window, not initially visible) */
106 static const struct message WmCreateChildPopupSeq[] = {
107 { HCBT_CREATEWND, hook },
108 { WM_NCCREATE, sent },
109 { WM_NCCALCSIZE, sent|wparam, 0 },
115 /* CreateWindow (for a popup window, not initially visible,
116 * which sets WS_VISIBLE in WM_CREATE handler)
118 static const struct message WmCreateInvisiblePopupSeq[] = {
119 { HCBT_CREATEWND, hook },
120 { WM_NCCREATE, sent },
121 { WM_NCCALCSIZE, sent|wparam, 0 },
123 { WM_STYLECHANGING, sent },
124 { WM_STYLECHANGED, sent },
129 /* ShowWindow (for a popup window with WS_VISIBLE style set) */
130 static const struct message WmShowVisiblePopupSeq[] = {
133 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
134 * for a popup window with WS_VISIBLE style set
136 static const struct message WmShowVisiblePopupSeq_2[] = {
137 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
140 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
141 * for a popup window with WS_VISIBLE style set
143 static const struct message WmShowVisiblePopupSeq_3[] = {
144 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
145 { HCBT_ACTIVATE, hook },
146 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
147 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
148 { WM_NCACTIVATE, sent|wparam, 1 },
149 { WM_ACTIVATE, sent|wparam, 1 },
150 { HCBT_SETFOCUS, hook },
151 { WM_IME_SETCONTEXT, sent|defwinproc|optional },
152 { WM_SETFOCUS, sent|defwinproc },
155 /* CreateWindow (for child window, not initially visible) */
156 static const struct message WmCreateChildSeq[] = {
157 { HCBT_CREATEWND, hook },
158 { WM_NCCREATE, sent },
159 /* child is inserted into parent's child list after WM_NCCREATE returns */
160 { WM_NCCALCSIZE, sent|wparam, 0 },
164 { WM_PARENTNOTIFY, sent|parent|wparam, 1 },
167 /* ShowWindow (for child window) */
168 static const struct message WmShowChildSeq[] = {
169 { WM_SHOWWINDOW, sent|wparam, 1 },
170 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
171 { WM_ERASEBKGND, sent|parent|optional },
172 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
175 /* DestroyWindow (for child window) */
176 static const struct message WmDestroyChildSeq[] = {
177 { HCBT_DESTROYWND, hook },
178 { WM_PARENTNOTIFY, sent|parent|wparam, 2 },
179 { WM_SHOWWINDOW, sent|wparam, 0 },
180 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
181 { WM_ERASEBKGND, sent|parent|optional },
182 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
183 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
184 { WM_KILLFOCUS, sent },
185 { WM_IME_SETCONTEXT, sent|optional },
186 { WM_DESTROY, sent },
187 { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
188 { WM_NCDESTROY, sent },
189 { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
192 /* Moving the mouse in nonclient area */
193 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
194 { WM_NCHITTEST, sent },
195 { WM_SETCURSOR, sent },
196 { WM_NCMOUSEMOVE, posted },
199 /* Moving the mouse in client area */
200 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
201 { WM_NCHITTEST, sent },
202 { WM_SETCURSOR, sent },
203 { WM_MOUSEMOVE, posted },
206 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
207 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
208 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
209 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
210 { WM_GETMINMAXINFO, sent|defwinproc },
211 { WM_ENTERSIZEMOVE, sent|defwinproc },
212 { WM_WINDOWPOSCHANGING, sent|defwinproc },
213 { WM_WINDOWPOSCHANGED, sent|defwinproc },
214 { WM_MOVE, sent|defwinproc },
215 { WM_EXITSIZEMOVE, sent|defwinproc },
218 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
219 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
220 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
221 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
222 { WM_GETMINMAXINFO, sent|defwinproc },
223 { WM_ENTERSIZEMOVE, sent|defwinproc },
224 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
225 { WM_WINDOWPOSCHANGING, sent|defwinproc },
226 { WM_GETMINMAXINFO, sent|defwinproc },
227 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
228 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
229 { WM_GETTEXT, sent|defwinproc },
230 { WM_ERASEBKGND, sent|defwinproc },
231 { WM_WINDOWPOSCHANGED, sent|defwinproc },
232 { WM_MOVE, sent|defwinproc },
233 { WM_SIZE, sent|defwinproc },
234 { WM_EXITSIZEMOVE, sent|defwinproc },
237 /* Resizing child window with MoveWindow (32) */
238 static const struct message WmResizingChildWithMoveWindowSeq[] = {
239 { WM_WINDOWPOSCHANGING, sent },
240 { WM_NCCALCSIZE, sent|wparam, 1 },
241 { WM_ERASEBKGND, sent|optional },
242 { WM_WINDOWPOSCHANGED, sent },
243 { WM_MOVE, sent|defwinproc },
244 { WM_SIZE, sent|defwinproc },
247 /* Clicking on inactive button */
248 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
249 { WM_NCHITTEST, sent },
250 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
251 { WM_MOUSEACTIVATE, sent },
252 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
253 { WM_SETCURSOR, sent },
254 { WM_SETCURSOR, sent|parent|defwinproc },
255 { WM_LBUTTONDOWN, posted },
256 { WM_KILLFOCUS, posted|parent },
257 { WM_SETFOCUS, posted },
258 { WM_CTLCOLORBTN, posted|parent },
259 { BM_SETSTATE, posted },
260 { WM_CTLCOLORBTN, posted|parent },
261 { WM_LBUTTONUP, posted },
262 { BM_SETSTATE, posted },
263 { WM_CTLCOLORBTN, posted|parent },
264 { WM_COMMAND, posted|parent },
267 /* Reparenting a button (16/32) */
268 /* The last child (button) reparented gets topmost for its new parent. */
269 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
270 { WM_SHOWWINDOW, sent|wparam, 0 },
271 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
272 { WM_ERASEBKGND, sent|parent },
273 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
274 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
275 { WM_CHILDACTIVATE, sent },
276 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
277 { WM_MOVE, sent|defwinproc },
278 { WM_SHOWWINDOW, sent|wparam, 1 },
281 /* Creation of a modal dialog (32) */
282 static const struct message WmCreateModalDialogSeq[] = { /* FIXME: add */
283 { WM_CANCELMODE, sent|parent },
284 { WM_KILLFOCUS, sent|parent },
285 { WM_ENABLE, sent|parent|wparam, 0 },
286 /* (window proc creation messages not tracked yet, because...) */
287 { WM_SETFONT, sent },
288 { WM_INITDIALOG, sent },
289 /* (...the window proc message hook was installed here, IsVisible still FALSE) */
290 { WM_NCACTIVATE, sent|parent|wparam, 0 },
291 { WM_GETTEXT, sent|defwinproc },
292 { WM_ACTIVATE, sent|parent|wparam, 0 },
293 { WM_WINDOWPOSCHANGING, sent },
294 { WM_WINDOWPOSCHANGING, sent|parent },
295 { WM_NCACTIVATE, sent|wparam, 1 },
296 { WM_ACTIVATE, sent|wparam, 1 },
297 /* (setting focus) */
298 { WM_SHOWWINDOW, sent|wparam, 1 },
299 { WM_WINDOWPOSCHANGING, sent },
300 { WM_NCPAINT, sent },
301 { WM_GETTEXT, sent|defwinproc },
302 { WM_ERASEBKGND, sent },
303 { WM_CTLCOLORDLG, sent|defwinproc },
304 { WM_WINDOWPOSCHANGED, sent },
306 /* FIXME: (bunch of WM_CTLCOLOR* for each control) */
307 { WM_PAINT, sent|parent },
308 { WM_ENTERIDLE, sent|parent|wparam, 0},
309 { WM_SETCURSOR, sent|parent },
312 /* Destruction of a modal dialog (32) */
313 static const struct message WmDestroyModalDialogSeq[] = { /* FIXME: add */
314 /* (inside dialog proc: EndDialog is called) */
315 { WM_ENABLE, sent|parent|wparam, 1 },
316 { WM_SETFOCUS, sent },
317 { WM_WINDOWPOSCHANGING, sent },
318 { WM_NCPAINT, sent|parent },
319 { WM_GETTEXT, sent|defwinproc },
320 { WM_ERASEBKGND, sent|parent },
321 { WM_WINDOWPOSCHANGED, sent },
322 { WM_NCACTIVATE, sent|wparam, 0 },
323 { WM_ACTIVATE, sent|wparam, 0 },
324 { WM_WINDOWPOSCHANGING, sent },
325 { WM_WINDOWPOSCHANGING, sent|parent },
326 { WM_NCACTIVATE, sent|parent|wparam, 1 },
327 { WM_GETTEXT, sent|defwinproc },
328 { WM_ACTIVATE, sent|parent|wparam, 1 },
329 { WM_KILLFOCUS, sent },
330 { WM_SETFOCUS, sent|parent },
331 { WM_DESTROY, sent },
332 { WM_NCDESTROY, sent },
335 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
336 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
337 /* (inside dialog proc, handling WM_INITDIALOG) */
338 { WM_WINDOWPOSCHANGING, sent },
339 { WM_NCCALCSIZE, sent },
340 { WM_NCACTIVATE, sent|parent|wparam, 0 },
341 { WM_GETTEXT, sent|defwinproc },
342 { WM_ACTIVATE, sent|parent|wparam, 0 },
343 { WM_WINDOWPOSCHANGING, sent },
344 { WM_WINDOWPOSCHANGING, sent|parent },
345 { WM_NCACTIVATE, sent|wparam, 1 },
346 { WM_ACTIVATE, sent|wparam, 1 },
347 { WM_WINDOWPOSCHANGED, sent },
348 { WM_SIZE, sent|defwinproc },
349 /* (setting focus) */
350 { WM_SHOWWINDOW, sent|wparam, 1 },
351 { WM_WINDOWPOSCHANGING, sent },
352 { WM_NCPAINT, sent },
353 { WM_GETTEXT, sent|defwinproc },
354 { WM_ERASEBKGND, sent },
355 { WM_CTLCOLORDLG, sent|defwinproc },
356 { WM_WINDOWPOSCHANGED, sent },
358 /* (bunch of WM_CTLCOLOR* for each control) */
359 { WM_PAINT, sent|parent },
360 { WM_ENTERIDLE, sent|parent|wparam, 0 },
361 { WM_SETCURSOR, sent|parent },
364 /* SetMenu for NonVisible windows with size change*/
365 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
366 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
367 { WM_NCCALCSIZE, sent|wparam, 1 },
368 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
369 { WM_MOVE, sent|defwinproc },
370 { WM_SIZE, sent|defwinproc },
373 /* SetMenu for NonVisible windows with no size change */
374 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
375 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
376 { WM_NCCALCSIZE, sent|wparam, 1 },
377 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
380 /* SetMenu for Visible windows with size change */
381 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
382 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
383 { WM_NCCALCSIZE, sent|wparam, 1 },
384 { WM_NCPAINT, sent|wparam, 1 },
385 { WM_GETTEXT, sent|defwinproc },
386 { WM_ERASEBKGND, sent|optional },
387 { WM_ACTIVATE, sent|optional },
388 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
389 { WM_MOVE, sent|defwinproc },
390 { WM_SIZE, sent|defwinproc },
393 /* SetMenu for Visible windows with no size change */
394 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
395 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
396 { WM_NCCALCSIZE, sent|wparam, 1 },
397 { WM_NCPAINT, sent|wparam, 1 },
398 { WM_GETTEXT, sent|defwinproc },
399 { WM_ERASEBKGND, sent|optional },
400 { WM_ACTIVATE, sent|optional },
401 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
405 static const struct message WmSetRedrawFalseSeq[] =
407 { WM_SETREDRAW, sent|wparam, 0 },
411 static const struct message WmSetRedrawTrueSeq[] =
413 { WM_SETREDRAW, sent|wparam, 1 },
417 static int sequence_cnt, sequence_size;
418 static struct message* sequence;
420 static void add_message(const struct message *msg)
425 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
427 if (sequence_cnt == sequence_size)
430 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
434 sequence[sequence_cnt].message = msg->message;
435 sequence[sequence_cnt].flags = msg->flags;
436 sequence[sequence_cnt].wParam = msg->wParam;
437 sequence[sequence_cnt].lParam = msg->lParam;
442 static void flush_sequence()
444 HeapFree(GetProcessHeap(), 0, sequence);
446 sequence_cnt = sequence_size = 0;
449 static void ok_sequence(const struct message *expected, const char *context)
451 static const struct message end_of_sequence = { 0, 0, 0, 0 };
452 const struct message *actual;
454 add_message(&end_of_sequence);
458 while (expected->message && actual->message)
460 trace("expected %04x - actual %04x\n", expected->message, actual->message);
462 if (expected->message == actual->message)
464 if (expected->flags & wparam)
465 ok (expected->wParam == actual->wParam,
466 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
467 context, expected->message, expected->wParam, actual->wParam);
468 if (expected->flags & lparam)
469 ok (expected->lParam == actual->lParam,
470 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
471 context, expected->message, expected->lParam, actual->lParam);
472 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
473 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
474 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
475 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
476 "%s: the msg 0x%04x should have been %s\n",
477 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
478 ok ((expected->flags & parent) == (actual->flags & parent),
479 "%s: the msg 0x%04x was expected in %s\n",
480 context, expected->message, (expected->flags & parent) ? "parent" : "child");
481 ok ((expected->flags & hook) == (actual->flags & hook),
482 "%s: the msg 0x%04x should have been sent by a hook\n",
483 context, expected->message);
487 else if (expected->flags & optional)
492 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
493 context, expected->message, actual->message);
501 if (expected->message || actual->message)
502 ok (FALSE, "%s: the msg sequence is not complete\n", context);
508 static void test_WM_SETREDRAW(HWND hwnd)
510 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
514 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
515 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE");
517 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
518 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
521 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
522 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE");
524 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
525 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE");
527 /* restore original WS_VISIBLE state */
528 SetWindowLongA(hwnd, GWL_STYLE, style);
533 /* test if we receive the right sequence of messages */
534 static void test_messages(void)
536 HWND hwnd, hparent, hchild;
537 HWND hchild2, hbutton;
540 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
541 100, 100, 200, 200, 0, 0, 0, NULL);
542 ok (hwnd != 0, "Failed to create overlapped window\n");
543 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
545 /* test WM_SETREDRAW on a not visible top level window */
546 test_WM_SETREDRAW(hwnd);
548 ShowWindow(hwnd, SW_SHOW);
549 ok_sequence(WmShowOverlappedSeq, "ShowWindow:overlapped");
551 /* test WM_SETREDRAW on a visible top level window */
552 test_WM_SETREDRAW(hwnd);
555 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
557 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
558 100, 100, 200, 200, 0, 0, 0, NULL);
559 ok (hparent != 0, "Failed to create parent window\n");
562 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILDWINDOW,
563 0, 0, 10, 10, hparent, 0, 0, NULL);
564 ok (hchild != 0, "Failed to create child window\n");
565 ok_sequence(WmCreateChildSeq, "CreateWindow:child");
567 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILDWINDOW,
568 100, 100, 50, 50, hparent, 0, 0, NULL);
569 ok (hchild2 != 0, "Failed to create child2 window\n");
572 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILDWINDOW,
573 0, 100, 50, 50, hchild, 0, 0, NULL);
574 ok (hbutton != 0, "Failed to create button window\n");
576 /* test WM_SETREDRAW on a not visible child window */
577 test_WM_SETREDRAW(hchild);
579 ShowWindow(hchild, SW_SHOW);
580 ok_sequence(WmShowChildSeq, "ShowWindow:child");
582 /* test WM_SETREDRAW on a visible child window */
583 test_WM_SETREDRAW(hchild);
588 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
589 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
591 DestroyWindow(hchild);
592 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
593 DestroyWindow(hchild2);
594 DestroyWindow(hbutton);
597 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
598 0, 0, 100, 100, hparent, 0, 0, NULL);
599 ok (hchild != 0, "Failed to create child popup window\n");
600 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup");
601 DestroyWindow(hchild);
603 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
605 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
606 0, 0, 100, 100, hparent, 0, 0, NULL);
607 ok (hchild != 0, "Failed to create popup window\n");
608 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
609 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
610 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
612 ShowWindow(hchild, SW_SHOW);
613 ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
615 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
616 ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
618 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
619 ok_sequence(WmShowVisiblePopupSeq_3, "CreateWindow:show_visible_popup_3");
620 DestroyWindow(hchild);
622 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
623 * changes nothing in message sequences.
626 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
627 0, 0, 100, 100, hparent, 0, 0, NULL);
628 ok (hchild != 0, "Failed to create popup window\n");
629 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
630 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
631 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
633 ShowWindow(hchild, SW_SHOW);
634 ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
636 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
637 ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
638 DestroyWindow(hchild);
640 DestroyWindow(hparent);
643 /* Message sequence for SetMenu */
644 hmenu = CreateMenu();
645 ok (hmenu != 0, "Failed to create menu\n");
646 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
647 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
648 100, 100, 200, 200, 0, hmenu, 0, NULL);
649 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
650 ok (SetMenu(hwnd, 0), "SetMenu");
651 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");
652 ok (SetMenu(hwnd, 0), "SetMenu");
653 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");
654 ShowWindow(hwnd, SW_SHOW);
656 ok (SetMenu(hwnd, 0), "SetMenu");
657 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");
658 ok (SetMenu(hwnd, hmenu), "SetMenu");
659 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");
664 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
666 static long defwndproc_counter = 0;
670 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
672 msg.message = message;
673 msg.flags = sent|wparam|lparam;
674 if (defwndproc_counter) msg.flags |= defwinproc;
679 defwndproc_counter++;
680 ret = DefWindowProcA(hwnd, message, wParam, lParam);
681 defwndproc_counter--;
686 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
688 static long defwndproc_counter = 0;
692 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
694 msg.message = message;
695 msg.flags = sent|wparam|lparam;
696 if (defwndproc_counter) msg.flags |= defwinproc;
701 if (message == WM_CREATE)
703 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
704 SetWindowLongA(hwnd, GWL_STYLE, style);
707 defwndproc_counter++;
708 ret = DefWindowProcA(hwnd, message, wParam, lParam);
709 defwndproc_counter--;
714 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
716 static long defwndproc_counter = 0;
720 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
722 if (message == WM_PARENTNOTIFY)
724 msg.message = message;
725 msg.flags = sent|parent|wparam|lparam;
726 if (defwndproc_counter) msg.flags |= defwinproc;
732 defwndproc_counter++;
733 ret = DefWindowProcA(hwnd, message, wParam, lParam);
734 defwndproc_counter--;
739 static BOOL RegisterWindowClasses(void)
744 cls.lpfnWndProc = MsgCheckProcA;
747 cls.hInstance = GetModuleHandleA(0);
749 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
750 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
751 cls.lpszMenuName = NULL;
752 cls.lpszClassName = "TestWindowClass";
753 if(!RegisterClassA(&cls)) return FALSE;
755 cls.lpfnWndProc = PopupMsgCheckProcA;
756 cls.lpszClassName = "TestPopupClass";
757 if(!RegisterClassA(&cls)) return FALSE;
759 cls.lpfnWndProc = ParentMsgCheckProcA;
760 cls.lpszClassName = "TestParentClass";
761 if(!RegisterClassA(&cls)) return FALSE;
763 cls.lpfnWndProc = DefWindowProcA;
764 cls.lpszClassName = "SimpleWindowClass";
765 if(!RegisterClassA(&cls)) return FALSE;
770 static HHOOK hCBT_hook;
772 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
776 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
778 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
780 if (!strcmp(buf, "TestWindowClass") ||
781 !strcmp(buf, "TestParentClass") ||
782 !strcmp(buf, "TestPopupClass") ||
783 !strcmp(buf, "SimpleWindowClass"))
794 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
799 if (!RegisterWindowClasses()) assert(0);
801 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
806 UnhookWindowsHookEx(hCBT_hook);