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_KILLFOCUS, sent|parent },
152 { WM_IME_SETCONTEXT, sent|defwinproc|optional },
153 { WM_SETFOCUS, sent|defwinproc },
156 /* CreateWindow (for child window, not initially visible) */
157 static const struct message WmCreateChildSeq[] = {
158 { HCBT_CREATEWND, hook },
159 { WM_NCCREATE, sent },
160 /* child is inserted into parent's child list after WM_NCCREATE returns */
161 { WM_NCCALCSIZE, sent|wparam, 0 },
165 { WM_PARENTNOTIFY, sent|parent|wparam, 1 },
168 /* ShowWindow (for child window) */
169 static const struct message WmShowChildSeq[] = {
170 { WM_SHOWWINDOW, sent|wparam, 1 },
171 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
172 { WM_ERASEBKGND, sent|parent|optional },
173 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
176 /* DestroyWindow (for child window) */
177 static const struct message WmDestroyChildSeq[] = {
178 { HCBT_DESTROYWND, hook },
179 { WM_PARENTNOTIFY, sent|parent|wparam, 2 },
180 { WM_SHOWWINDOW, sent|wparam, 0 },
181 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
182 { WM_ERASEBKGND, sent|parent|optional },
183 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
184 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
185 { WM_KILLFOCUS, sent },
186 { WM_IME_SETCONTEXT, sent|optional },
187 { WM_DESTROY, sent },
188 { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
189 { WM_NCDESTROY, sent },
190 { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
193 /* Moving the mouse in nonclient area */
194 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
195 { WM_NCHITTEST, sent },
196 { WM_SETCURSOR, sent },
197 { WM_NCMOUSEMOVE, posted },
200 /* Moving the mouse in client area */
201 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
202 { WM_NCHITTEST, sent },
203 { WM_SETCURSOR, sent },
204 { WM_MOUSEMOVE, posted },
207 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
208 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
209 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
210 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
211 { WM_GETMINMAXINFO, sent|defwinproc },
212 { WM_ENTERSIZEMOVE, sent|defwinproc },
213 { WM_WINDOWPOSCHANGING, sent|defwinproc },
214 { WM_WINDOWPOSCHANGED, sent|defwinproc },
215 { WM_MOVE, sent|defwinproc },
216 { WM_EXITSIZEMOVE, sent|defwinproc },
219 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
220 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
221 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
222 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
223 { WM_GETMINMAXINFO, sent|defwinproc },
224 { WM_ENTERSIZEMOVE, sent|defwinproc },
225 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
226 { WM_WINDOWPOSCHANGING, sent|defwinproc },
227 { WM_GETMINMAXINFO, sent|defwinproc },
228 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
229 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
230 { WM_GETTEXT, sent|defwinproc },
231 { WM_ERASEBKGND, sent|defwinproc },
232 { WM_WINDOWPOSCHANGED, sent|defwinproc },
233 { WM_MOVE, sent|defwinproc },
234 { WM_SIZE, sent|defwinproc },
235 { WM_EXITSIZEMOVE, sent|defwinproc },
238 /* Resizing child window with MoveWindow (32) */
239 static const struct message WmResizingChildWithMoveWindowSeq[] = {
240 { WM_WINDOWPOSCHANGING, sent },
241 { WM_NCCALCSIZE, sent|wparam, 1 },
242 { WM_ERASEBKGND, sent|optional },
243 { WM_WINDOWPOSCHANGED, sent },
244 { WM_MOVE, sent|defwinproc },
245 { WM_SIZE, sent|defwinproc },
248 /* Clicking on inactive button */
249 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
250 { WM_NCHITTEST, sent },
251 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
252 { WM_MOUSEACTIVATE, sent },
253 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
254 { WM_SETCURSOR, sent },
255 { WM_SETCURSOR, sent|parent|defwinproc },
256 { WM_LBUTTONDOWN, posted },
257 { WM_KILLFOCUS, posted|parent },
258 { WM_SETFOCUS, posted },
259 { WM_CTLCOLORBTN, posted|parent },
260 { BM_SETSTATE, posted },
261 { WM_CTLCOLORBTN, posted|parent },
262 { WM_LBUTTONUP, posted },
263 { BM_SETSTATE, posted },
264 { WM_CTLCOLORBTN, posted|parent },
265 { WM_COMMAND, posted|parent },
268 /* Reparenting a button (16/32) */
269 /* The last child (button) reparented gets topmost for its new parent. */
270 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
271 { WM_SHOWWINDOW, sent|wparam, 0 },
272 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
273 { WM_ERASEBKGND, sent|parent },
274 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
275 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
276 { WM_CHILDACTIVATE, sent },
277 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
278 { WM_MOVE, sent|defwinproc },
279 { WM_SHOWWINDOW, sent|wparam, 1 },
282 /* Creation of a custom dialog (32) */
283 static const struct message WmCreateCustomDialogSeq[] = {
284 { HCBT_CREATEWND, hook },
285 { WM_GETMINMAXINFO, sent },
286 { WM_NCCREATE, sent },
287 { WM_NCCALCSIZE, sent|wparam, 0 },
289 { WM_SHOWWINDOW, sent|wparam, 1 },
290 { HCBT_ACTIVATE, hook },
291 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
292 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
293 { WM_NCACTIVATE, sent|wparam, 1 },
294 { WM_ACTIVATE, sent|wparam, 1 },
295 { WM_KILLFOCUS, sent|parent },
296 { WM_IME_SETCONTEXT, sent|optional },
297 { WM_SETFOCUS, sent },
298 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
299 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
300 { WM_NCPAINT, sent|wparam, 1 },
301 { WM_GETTEXT, sent|defwinproc },
302 { WM_ERASEBKGND, sent },
303 { WM_CTLCOLORDLG, sent|defwinproc },
304 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
309 /* Creation of a modal dialog (32) */
310 static const struct message WmCreateModalDialogSeq[] = { /* FIXME: add */
311 { WM_CANCELMODE, sent|parent },
312 { WM_KILLFOCUS, sent|parent },
313 { WM_ENABLE, sent|parent|wparam, 0 },
314 /* (window proc creation messages not tracked yet, because...) */
315 { WM_SETFONT, sent },
316 { WM_INITDIALOG, sent },
317 /* (...the window proc message hook was installed here, IsVisible still FALSE) */
318 { WM_NCACTIVATE, sent|parent|wparam, 0 },
319 { WM_GETTEXT, sent|defwinproc },
320 { WM_ACTIVATE, sent|parent|wparam, 0 },
321 { WM_WINDOWPOSCHANGING, sent },
322 { WM_WINDOWPOSCHANGING, sent|parent },
323 { WM_NCACTIVATE, sent|wparam, 1 },
324 { WM_ACTIVATE, sent|wparam, 1 },
325 /* (setting focus) */
326 { WM_SHOWWINDOW, sent|wparam, 1 },
327 { WM_WINDOWPOSCHANGING, sent },
328 { WM_NCPAINT, sent },
329 { WM_GETTEXT, sent|defwinproc },
330 { WM_ERASEBKGND, sent },
331 { WM_CTLCOLORDLG, sent|defwinproc },
332 { WM_WINDOWPOSCHANGED, sent },
334 /* FIXME: (bunch of WM_CTLCOLOR* for each control) */
335 { WM_PAINT, sent|parent },
336 { WM_ENTERIDLE, sent|parent|wparam, 0},
337 { WM_SETCURSOR, sent|parent },
340 /* Destruction of a modal dialog (32) */
341 static const struct message WmDestroyModalDialogSeq[] = { /* FIXME: add */
342 /* (inside dialog proc: EndDialog is called) */
343 { WM_ENABLE, sent|parent|wparam, 1 },
344 { WM_SETFOCUS, sent },
345 { WM_WINDOWPOSCHANGING, sent },
346 { WM_NCPAINT, sent|parent },
347 { WM_GETTEXT, sent|defwinproc },
348 { WM_ERASEBKGND, sent|parent },
349 { WM_WINDOWPOSCHANGED, sent },
350 { WM_NCACTIVATE, sent|wparam, 0 },
351 { WM_ACTIVATE, sent|wparam, 0 },
352 { WM_WINDOWPOSCHANGING, sent },
353 { WM_WINDOWPOSCHANGING, sent|parent },
354 { WM_NCACTIVATE, sent|parent|wparam, 1 },
355 { WM_GETTEXT, sent|defwinproc },
356 { WM_ACTIVATE, sent|parent|wparam, 1 },
357 { WM_KILLFOCUS, sent },
358 { WM_SETFOCUS, sent|parent },
359 { WM_DESTROY, sent },
360 { WM_NCDESTROY, sent },
363 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
364 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
365 /* (inside dialog proc, handling WM_INITDIALOG) */
366 { WM_WINDOWPOSCHANGING, sent },
367 { WM_NCCALCSIZE, sent },
368 { WM_NCACTIVATE, sent|parent|wparam, 0 },
369 { WM_GETTEXT, sent|defwinproc },
370 { WM_ACTIVATE, sent|parent|wparam, 0 },
371 { WM_WINDOWPOSCHANGING, sent },
372 { WM_WINDOWPOSCHANGING, sent|parent },
373 { WM_NCACTIVATE, sent|wparam, 1 },
374 { WM_ACTIVATE, sent|wparam, 1 },
375 { WM_WINDOWPOSCHANGED, sent },
376 { WM_SIZE, sent|defwinproc },
377 /* (setting focus) */
378 { WM_SHOWWINDOW, sent|wparam, 1 },
379 { WM_WINDOWPOSCHANGING, sent },
380 { WM_NCPAINT, sent },
381 { WM_GETTEXT, sent|defwinproc },
382 { WM_ERASEBKGND, sent },
383 { WM_CTLCOLORDLG, sent|defwinproc },
384 { WM_WINDOWPOSCHANGED, sent },
386 /* (bunch of WM_CTLCOLOR* for each control) */
387 { WM_PAINT, sent|parent },
388 { WM_ENTERIDLE, sent|parent|wparam, 0 },
389 { WM_SETCURSOR, sent|parent },
392 /* SetMenu for NonVisible windows with size change*/
393 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
394 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
395 { WM_NCCALCSIZE, sent|wparam, 1 },
396 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
397 { WM_MOVE, sent|defwinproc },
398 { WM_SIZE, sent|defwinproc },
401 /* SetMenu for NonVisible windows with no size change */
402 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
403 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
404 { WM_NCCALCSIZE, sent|wparam, 1 },
405 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
408 /* SetMenu for Visible windows with size change */
409 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
410 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
411 { WM_NCCALCSIZE, sent|wparam, 1 },
412 { WM_NCPAINT, sent|wparam, 1 },
413 { WM_GETTEXT, sent|defwinproc },
414 { WM_ERASEBKGND, sent|optional },
415 { WM_ACTIVATE, sent|optional },
416 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
417 { WM_MOVE, sent|defwinproc },
418 { WM_SIZE, sent|defwinproc },
421 /* SetMenu for Visible windows with no size change */
422 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
423 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
424 { WM_NCCALCSIZE, sent|wparam, 1 },
425 { WM_NCPAINT, sent|wparam, 1 },
426 { WM_GETTEXT, sent|defwinproc },
427 { WM_ERASEBKGND, sent|optional },
428 { WM_ACTIVATE, sent|optional },
429 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
433 static const struct message WmSetRedrawFalseSeq[] =
435 { WM_SETREDRAW, sent|wparam, 0 },
439 static const struct message WmSetRedrawTrueSeq[] =
441 { WM_SETREDRAW, sent|wparam, 1 },
445 static int sequence_cnt, sequence_size;
446 static struct message* sequence;
448 static void add_message(const struct message *msg)
453 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
455 if (sequence_cnt == sequence_size)
458 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
462 sequence[sequence_cnt].message = msg->message;
463 sequence[sequence_cnt].flags = msg->flags;
464 sequence[sequence_cnt].wParam = msg->wParam;
465 sequence[sequence_cnt].lParam = msg->lParam;
470 static void flush_sequence()
472 HeapFree(GetProcessHeap(), 0, sequence);
474 sequence_cnt = sequence_size = 0;
477 static void ok_sequence(const struct message *expected, const char *context)
479 static const struct message end_of_sequence = { 0, 0, 0, 0 };
480 const struct message *actual;
482 add_message(&end_of_sequence);
486 while (expected->message && actual->message)
488 trace("expected %04x - actual %04x\n", expected->message, actual->message);
490 if (expected->message == actual->message)
492 if (expected->flags & wparam)
493 ok (expected->wParam == actual->wParam,
494 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
495 context, expected->message, expected->wParam, actual->wParam);
496 if (expected->flags & lparam)
497 ok (expected->lParam == actual->lParam,
498 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
499 context, expected->message, expected->lParam, actual->lParam);
500 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
501 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
502 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
503 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
504 "%s: the msg 0x%04x should have been %s\n",
505 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
506 ok ((expected->flags & parent) == (actual->flags & parent),
507 "%s: the msg 0x%04x was expected in %s\n",
508 context, expected->message, (expected->flags & parent) ? "parent" : "child");
509 ok ((expected->flags & hook) == (actual->flags & hook),
510 "%s: the msg 0x%04x should have been sent by a hook\n",
511 context, expected->message);
515 else if (expected->flags & optional)
520 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
521 context, expected->message, actual->message);
529 if (expected->message || actual->message)
530 ok (FALSE, "%s: the msg sequence is not complete\n", context);
536 static void test_WM_SETREDRAW(HWND hwnd)
538 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
542 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
543 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE");
545 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
546 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
549 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
550 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE");
552 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
553 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE");
555 /* restore original WS_VISIBLE state */
556 SetWindowLongA(hwnd, GWL_STYLE, style);
561 /* test if we receive the right sequence of messages */
562 static void test_messages(void)
564 HWND hwnd, hparent, hchild;
565 HWND hchild2, hbutton;
568 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
569 100, 100, 200, 200, 0, 0, 0, NULL);
570 ok (hwnd != 0, "Failed to create overlapped window\n");
571 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
573 /* test WM_SETREDRAW on a not visible top level window */
574 test_WM_SETREDRAW(hwnd);
576 ShowWindow(hwnd, SW_SHOW);
577 ok_sequence(WmShowOverlappedSeq, "ShowWindow:overlapped");
579 /* test WM_SETREDRAW on a visible top level window */
580 test_WM_SETREDRAW(hwnd);
583 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
585 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
586 100, 100, 200, 200, 0, 0, 0, NULL);
587 ok (hparent != 0, "Failed to create parent window\n");
590 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILDWINDOW,
591 0, 0, 10, 10, hparent, 0, 0, NULL);
592 ok (hchild != 0, "Failed to create child window\n");
593 ok_sequence(WmCreateChildSeq, "CreateWindow:child");
595 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILDWINDOW,
596 100, 100, 50, 50, hparent, 0, 0, NULL);
597 ok (hchild2 != 0, "Failed to create child2 window\n");
600 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILDWINDOW,
601 0, 100, 50, 50, hchild, 0, 0, NULL);
602 ok (hbutton != 0, "Failed to create button window\n");
604 /* test WM_SETREDRAW on a not visible child window */
605 test_WM_SETREDRAW(hchild);
607 ShowWindow(hchild, SW_SHOW);
608 ok_sequence(WmShowChildSeq, "ShowWindow:child");
610 /* test WM_SETREDRAW on a visible child window */
611 test_WM_SETREDRAW(hchild);
616 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
617 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
619 DestroyWindow(hchild);
620 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
621 DestroyWindow(hchild2);
622 DestroyWindow(hbutton);
625 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
626 0, 0, 100, 100, hparent, 0, 0, NULL);
627 ok (hchild != 0, "Failed to create child popup window\n");
628 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup");
629 DestroyWindow(hchild);
631 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
633 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
634 0, 0, 100, 100, hparent, 0, 0, NULL);
635 ok (hchild != 0, "Failed to create popup window\n");
636 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
637 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
638 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
640 ShowWindow(hchild, SW_SHOW);
641 ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
643 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
644 ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
646 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
647 ok_sequence(WmShowVisiblePopupSeq_3, "CreateWindow:show_visible_popup_3");
648 DestroyWindow(hchild);
650 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
651 * changes nothing in message sequences.
654 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
655 0, 0, 100, 100, hparent, 0, 0, NULL);
656 ok (hchild != 0, "Failed to create popup window\n");
657 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
658 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
659 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
661 ShowWindow(hchild, SW_SHOW);
662 ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
664 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
665 ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
666 DestroyWindow(hchild);
669 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
670 0, 0, 100, 100, hparent, 0, 0, NULL);
671 ok(hwnd != 0, "Failed to create custom dialog window\n");
672 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog");
675 DestroyWindow(hparent);
678 /* Message sequence for SetMenu */
679 hmenu = CreateMenu();
680 ok (hmenu != 0, "Failed to create menu\n");
681 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
682 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
683 100, 100, 200, 200, 0, hmenu, 0, NULL);
684 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
685 ok (SetMenu(hwnd, 0), "SetMenu");
686 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");
687 ok (SetMenu(hwnd, 0), "SetMenu");
688 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");
689 ShowWindow(hwnd, SW_SHOW);
691 ok (SetMenu(hwnd, 0), "SetMenu");
692 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");
693 ok (SetMenu(hwnd, hmenu), "SetMenu");
694 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");
699 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
701 static long defwndproc_counter = 0;
705 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
707 msg.message = message;
708 msg.flags = sent|wparam|lparam;
709 if (defwndproc_counter) msg.flags |= defwinproc;
714 defwndproc_counter++;
715 ret = DefWindowProcA(hwnd, message, wParam, lParam);
716 defwndproc_counter--;
721 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
723 static long defwndproc_counter = 0;
727 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
729 msg.message = message;
730 msg.flags = sent|wparam|lparam;
731 if (defwndproc_counter) msg.flags |= defwinproc;
736 if (message == WM_CREATE)
738 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
739 SetWindowLongA(hwnd, GWL_STYLE, style);
742 defwndproc_counter++;
743 ret = DefWindowProcA(hwnd, message, wParam, lParam);
744 defwndproc_counter--;
749 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
751 static long defwndproc_counter = 0;
755 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
757 if (message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
758 message == WM_KILLFOCUS || message == WM_ENABLE)
760 msg.message = message;
761 msg.flags = sent|parent|wparam|lparam;
762 if (defwndproc_counter) msg.flags |= defwinproc;
768 defwndproc_counter++;
769 ret = DefWindowProcA(hwnd, message, wParam, lParam);
770 defwndproc_counter--;
775 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
777 static long defwndproc_counter = 0;
781 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
783 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
784 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
785 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID\n");
787 msg.message = message;
788 msg.flags = sent|wparam|lparam;
789 if (defwndproc_counter) msg.flags |= defwinproc;
794 defwndproc_counter++;
795 ret = DefDlgProcA(hwnd, message, wParam, lParam);
796 defwndproc_counter--;
801 static BOOL RegisterWindowClasses(void)
806 cls.lpfnWndProc = MsgCheckProcA;
809 cls.hInstance = GetModuleHandleA(0);
811 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
812 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
813 cls.lpszMenuName = NULL;
814 cls.lpszClassName = "TestWindowClass";
815 if(!RegisterClassA(&cls)) return FALSE;
817 cls.lpfnWndProc = PopupMsgCheckProcA;
818 cls.lpszClassName = "TestPopupClass";
819 if(!RegisterClassA(&cls)) return FALSE;
821 cls.lpfnWndProc = ParentMsgCheckProcA;
822 cls.lpszClassName = "TestParentClass";
823 if(!RegisterClassA(&cls)) return FALSE;
825 cls.lpfnWndProc = DefWindowProcA;
826 cls.lpszClassName = "SimpleWindowClass";
827 if(!RegisterClassA(&cls)) return FALSE;
829 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
830 cls.lpfnWndProc = TestDlgProcA;
831 cls.lpszClassName = "TestDialogClass";
832 if(!RegisterClassA(&cls)) return FALSE;
837 static HHOOK hCBT_hook;
839 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
843 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
845 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
847 if (!strcmp(buf, "TestWindowClass") ||
848 !strcmp(buf, "TestParentClass") ||
849 !strcmp(buf, "TestPopupClass") ||
850 !strcmp(buf, "SimpleWindowClass") ||
851 !strcmp(buf, "TestDialogClass"))
862 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
867 if (!RegisterWindowClasses()) assert(0);
869 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
874 UnhookWindowsHookEx(hCBT_hook);