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 /* FIXME: WM_QUERYNEWPALETTE, if in 256-color mode */
71 { WM_NCPAINT, sent|wparam|optional, 1 },
72 { WM_GETTEXT, sent|defwinproc|optional },
73 { WM_ERASEBKGND, sent|optional },
74 { HCBT_ACTIVATE, hook },
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_WINDOWPOSCHANGING, sent|wparam, 0 },
147 { WM_NCACTIVATE, sent|wparam, 1 },
148 { WM_ACTIVATE, sent|wparam, 1 },
149 { HCBT_SETFOCUS, hook },
150 { WM_IME_SETCONTEXT, sent|defwinproc|optional },
151 { WM_SETFOCUS, sent|defwinproc },
154 /* CreateWindow (for child window, not initially visible) */
155 static const struct message WmCreateChildSeq[] = {
156 { HCBT_CREATEWND, hook },
157 { WM_NCCREATE, sent },
158 /* child is inserted into parent's child list after WM_NCCREATE returns */
159 { WM_NCCALCSIZE, sent|wparam, 0 },
163 { WM_PARENTNOTIFY, sent|parent|wparam, 1 },
166 /* ShowWindow (for child window) */
167 static const struct message WmShowChildSeq[] = {
168 { WM_SHOWWINDOW, sent|wparam, 1 },
169 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
170 { WM_ERASEBKGND, sent|parent|optional },
171 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
174 /* DestroyWindow (for child window) */
175 static const struct message WmDestroyChildSeq[] = {
176 { HCBT_DESTROYWND, hook },
177 { WM_PARENTNOTIFY, sent|parent|wparam, 2 },
178 { WM_SHOWWINDOW, sent|wparam, 0 },
179 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
180 { WM_ERASEBKGND, sent|parent|optional },
181 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
182 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
183 { WM_KILLFOCUS, sent },
184 { WM_IME_SETCONTEXT, sent|optional },
185 { WM_DESTROY, sent },
186 { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
187 { WM_NCDESTROY, sent },
188 { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
191 /* Moving the mouse in nonclient area */
192 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
193 { WM_NCHITTEST, sent },
194 { WM_SETCURSOR, sent },
195 { WM_NCMOUSEMOVE, posted },
198 /* Moving the mouse in client area */
199 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
200 { WM_NCHITTEST, sent },
201 { WM_SETCURSOR, sent },
202 { WM_MOUSEMOVE, posted },
205 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
206 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
207 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
208 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
209 { WM_GETMINMAXINFO, sent|defwinproc },
210 { WM_ENTERSIZEMOVE, sent|defwinproc },
211 { WM_WINDOWPOSCHANGING, sent|defwinproc },
212 { WM_WINDOWPOSCHANGED, sent|defwinproc },
213 { WM_MOVE, sent|defwinproc },
214 { WM_EXITSIZEMOVE, sent|defwinproc },
217 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
218 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
219 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
220 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
221 { WM_GETMINMAXINFO, sent|defwinproc },
222 { WM_ENTERSIZEMOVE, sent|defwinproc },
223 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
224 { WM_WINDOWPOSCHANGING, sent|defwinproc },
225 { WM_GETMINMAXINFO, sent|defwinproc },
226 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
227 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
228 { WM_GETTEXT, sent|defwinproc },
229 { WM_ERASEBKGND, sent|defwinproc },
230 { WM_WINDOWPOSCHANGED, sent|defwinproc },
231 { WM_MOVE, sent|defwinproc },
232 { WM_SIZE, sent|defwinproc },
233 { WM_EXITSIZEMOVE, sent|defwinproc },
236 /* Resizing child window with MoveWindow (32) */
237 static const struct message WmResizingChildWithMoveWindowSeq[] = {
238 { WM_WINDOWPOSCHANGING, sent },
239 { WM_NCCALCSIZE, sent|wparam, 1 },
240 { WM_ERASEBKGND, sent|optional },
241 { WM_WINDOWPOSCHANGED, sent },
242 { WM_MOVE, sent|defwinproc },
243 { WM_SIZE, sent|defwinproc },
246 /* Clicking on inactive button */
247 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
248 { WM_NCHITTEST, sent },
249 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
250 { WM_MOUSEACTIVATE, sent },
251 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
252 { WM_SETCURSOR, sent },
253 { WM_SETCURSOR, sent|parent|defwinproc },
254 { WM_LBUTTONDOWN, posted },
255 { WM_KILLFOCUS, posted|parent },
256 { WM_SETFOCUS, posted },
257 { WM_CTLCOLORBTN, posted|parent },
258 { BM_SETSTATE, posted },
259 { WM_CTLCOLORBTN, posted|parent },
260 { WM_LBUTTONUP, posted },
261 { BM_SETSTATE, posted },
262 { WM_CTLCOLORBTN, posted|parent },
263 { WM_COMMAND, posted|parent },
266 /* Reparenting a button (16/32) */
267 /* The last child (button) reparented gets topmost for its new parent. */
268 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
269 { WM_SHOWWINDOW, sent|wparam, 0 },
270 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
271 { WM_ERASEBKGND, sent|parent },
272 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
273 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
274 { WM_CHILDACTIVATE, sent },
275 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
276 { WM_MOVE, sent|defwinproc },
277 { WM_SHOWWINDOW, sent|wparam, 1 },
280 /* Creation of a modal dialog (32) */
281 static const struct message WmCreateModalDialogSeq[] = { /* FIXME: add */
282 { WM_CANCELMODE, sent|parent },
283 { WM_KILLFOCUS, sent|parent },
284 { WM_ENABLE, sent|parent|wparam, 0 },
285 /* (window proc creation messages not tracked yet, because...) */
286 { WM_SETFONT, sent },
287 { WM_INITDIALOG, sent },
288 /* (...the window proc message hook was installed here, IsVisible still FALSE) */
289 { WM_NCACTIVATE, sent|parent|wparam, 0 },
290 { WM_GETTEXT, sent|defwinproc },
291 { WM_ACTIVATE, sent|parent|wparam, 0 },
292 { WM_WINDOWPOSCHANGING, sent },
293 { WM_WINDOWPOSCHANGING, sent|parent },
294 { WM_NCACTIVATE, sent|wparam, 1 },
295 { WM_ACTIVATE, sent|wparam, 1 },
296 /* (setting focus) */
297 { WM_SHOWWINDOW, sent|wparam, 1 },
298 { WM_WINDOWPOSCHANGING, sent },
299 { WM_NCPAINT, sent },
300 { WM_GETTEXT, sent|defwinproc },
301 { WM_ERASEBKGND, sent },
302 { WM_CTLCOLORDLG, sent|defwinproc },
303 { WM_WINDOWPOSCHANGED, sent },
305 /* FIXME: (bunch of WM_CTLCOLOR* for each control) */
306 { WM_PAINT, sent|parent },
307 { WM_ENTERIDLE, sent|parent|wparam, 0},
308 { WM_SETCURSOR, sent|parent },
311 /* Destruction of a modal dialog (32) */
312 static const struct message WmDestroyModalDialogSeq[] = { /* FIXME: add */
313 /* (inside dialog proc: EndDialog is called) */
314 { WM_ENABLE, sent|parent|wparam, 1 },
315 { WM_SETFOCUS, sent },
316 { WM_WINDOWPOSCHANGING, sent },
317 { WM_NCPAINT, sent|parent },
318 { WM_GETTEXT, sent|defwinproc },
319 { WM_ERASEBKGND, sent|parent },
320 { WM_WINDOWPOSCHANGED, sent },
321 { WM_NCACTIVATE, sent|wparam, 0 },
322 { WM_ACTIVATE, sent|wparam, 0 },
323 { WM_WINDOWPOSCHANGING, sent },
324 { WM_WINDOWPOSCHANGING, sent|parent },
325 { WM_NCACTIVATE, sent|parent|wparam, 1 },
326 { WM_GETTEXT, sent|defwinproc },
327 { WM_ACTIVATE, sent|parent|wparam, 1 },
328 { WM_KILLFOCUS, sent },
329 { WM_SETFOCUS, sent|parent },
330 { WM_DESTROY, sent },
331 { WM_NCDESTROY, sent },
334 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
335 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
336 /* (inside dialog proc, handling WM_INITDIALOG) */
337 { WM_WINDOWPOSCHANGING, sent },
338 { WM_NCCALCSIZE, sent },
339 { WM_NCACTIVATE, sent|parent|wparam, 0 },
340 { WM_GETTEXT, sent|defwinproc },
341 { WM_ACTIVATE, sent|parent|wparam, 0 },
342 { WM_WINDOWPOSCHANGING, sent },
343 { WM_WINDOWPOSCHANGING, sent|parent },
344 { WM_NCACTIVATE, sent|wparam, 1 },
345 { WM_ACTIVATE, sent|wparam, 1 },
346 { WM_WINDOWPOSCHANGED, sent },
347 { WM_SIZE, sent|defwinproc },
348 /* (setting focus) */
349 { WM_SHOWWINDOW, sent|wparam, 1 },
350 { WM_WINDOWPOSCHANGING, sent },
351 { WM_NCPAINT, sent },
352 { WM_GETTEXT, sent|defwinproc },
353 { WM_ERASEBKGND, sent },
354 { WM_CTLCOLORDLG, sent|defwinproc },
355 { WM_WINDOWPOSCHANGED, sent },
357 /* (bunch of WM_CTLCOLOR* for each control) */
358 { WM_PAINT, sent|parent },
359 { WM_ENTERIDLE, sent|parent|wparam, 0 },
360 { WM_SETCURSOR, sent|parent },
363 /* SetMenu for NonVisible windows with size change*/
364 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
365 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
366 { WM_NCCALCSIZE, sent|wparam, 1 },
367 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
368 { WM_MOVE, sent|defwinproc },
369 { WM_SIZE, sent|defwinproc },
372 /* SetMenu for NonVisible windows with no size change */
373 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
374 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
375 { WM_NCCALCSIZE, sent|wparam, 1 },
376 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
379 /* SetMenu for Visible windows with size change */
380 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
381 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
382 { WM_NCCALCSIZE, sent|wparam, 1 },
383 { WM_NCPAINT, sent|wparam, 1 },
384 { WM_GETTEXT, sent|defwinproc },
385 { WM_ERASEBKGND, sent|optional },
386 { WM_ACTIVATE, sent|optional },
387 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
388 { WM_MOVE, sent|defwinproc },
389 { WM_SIZE, sent|defwinproc },
392 /* SetMenu for Visible windows with no size change */
393 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
394 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
395 { WM_NCCALCSIZE, sent|wparam, 1 },
396 { WM_NCPAINT, sent|wparam, 1 },
397 { WM_GETTEXT, sent|defwinproc },
398 { WM_ERASEBKGND, sent|optional },
399 { WM_ACTIVATE, sent|optional },
400 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
404 static int sequence_cnt, sequence_size;
405 static struct message* sequence;
407 static void add_message(const struct message *msg)
412 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
414 if (sequence_cnt == sequence_size)
417 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
421 sequence[sequence_cnt].message = msg->message;
422 sequence[sequence_cnt].flags = msg->flags;
423 sequence[sequence_cnt].wParam = msg->wParam;
424 sequence[sequence_cnt].lParam = msg->lParam;
429 static void flush_sequence()
431 HeapFree(GetProcessHeap(), 0, sequence);
433 sequence_cnt = sequence_size = 0;
436 static void ok_sequence(const struct message *expected, const char *context)
438 static const struct message end_of_sequence = { 0, 0, 0, 0 };
439 const struct message *actual;
441 add_message(&end_of_sequence);
445 while (expected->message && actual->message)
447 trace("expected %04x - actual %04x\n", expected->message, actual->message);
449 if (expected->message == actual->message)
451 if (expected->flags & wparam)
452 ok (expected->wParam == actual->wParam,
453 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
454 context, expected->message, expected->wParam, actual->wParam);
455 if (expected->flags & lparam)
456 ok (expected->lParam == actual->lParam,
457 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
458 context, expected->message, expected->lParam, actual->lParam);
459 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
460 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
461 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
462 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
463 "%s: the msg 0x%04x should have been %s\n",
464 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
465 ok ((expected->flags & parent) == (actual->flags & parent),
466 "%s: the msg 0x%04x was expected in %s\n",
467 context, expected->message, (expected->flags & parent) ? "parent" : "child");
468 ok ((expected->flags & hook) == (actual->flags & hook),
469 "%s: the msg 0x%04x should have been sent by a hook\n",
470 context, expected->message);
474 else if (expected->flags & optional)
479 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
480 context, expected->message, actual->message);
488 if (expected->message || actual->message)
489 ok (FALSE, "%s: the msg sequence is not complete\n", context);
495 /* test if we receive the right sequence of messages */
496 static void test_messages(void)
498 HWND hwnd, hparent, hchild;
499 HWND hchild2, hbutton;
502 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
503 100, 100, 200, 200, 0, 0, 0, NULL);
504 ok (hwnd != 0, "Failed to create overlapped window\n");
505 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
507 ShowWindow(hwnd, SW_SHOW);
508 ok_sequence(WmShowOverlappedSeq, "ShowWindow:overlapped");
511 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
513 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
514 100, 100, 200, 200, 0, 0, 0, NULL);
515 ok (hparent != 0, "Failed to create parent window\n");
518 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILDWINDOW,
519 0, 0, 10, 10, hparent, 0, 0, NULL);
520 ok (hchild != 0, "Failed to create child window\n");
521 ok_sequence(WmCreateChildSeq, "CreateWindow:child");
523 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILDWINDOW,
524 100, 100, 50, 50, hparent, 0, 0, NULL);
525 ok (hchild2 != 0, "Failed to create child2 window\n");
528 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILDWINDOW,
529 0, 100, 50, 50, hchild, 0, 0, NULL);
530 ok (hbutton != 0, "Failed to create button window\n");
533 ShowWindow(hchild, SW_SHOW);
534 ok_sequence(WmShowChildSeq, "ShowWindow:child");
539 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
540 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
542 DestroyWindow(hchild);
543 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
544 DestroyWindow(hchild2);
545 DestroyWindow(hbutton);
548 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
549 0, 0, 100, 100, hparent, 0, 0, NULL);
550 ok (hchild != 0, "Failed to create child popup window\n");
551 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup");
552 DestroyWindow(hchild);
554 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
556 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
557 0, 0, 100, 100, hparent, 0, 0, NULL);
558 ok (hchild != 0, "Failed to create popup window\n");
559 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
560 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
561 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
563 ShowWindow(hchild, SW_SHOW);
564 ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
566 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
567 ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
569 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
570 ok_sequence(WmShowVisiblePopupSeq_3, "CreateWindow:show_visible_popup_3");
571 DestroyWindow(hchild);
573 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
574 * changes nothing in message sequences.
577 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
578 0, 0, 100, 100, hparent, 0, 0, NULL);
579 ok (hchild != 0, "Failed to create popup window\n");
580 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
581 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
582 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
584 ShowWindow(hchild, SW_SHOW);
585 ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
587 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
588 ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
589 DestroyWindow(hchild);
591 DestroyWindow(hparent);
594 /* Message sequence for SetMenu */
595 hmenu = CreateMenu();
596 ok (hmenu != 0, "Failed to create menu\n");
597 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
598 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
599 100, 100, 200, 200, 0, hmenu, 0, NULL);
600 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
601 ok (SetMenu(hwnd, 0), "SetMenu");
602 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");
603 ok (SetMenu(hwnd, 0), "SetMenu");
604 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");
605 ShowWindow(hwnd, SW_SHOW);
607 ok (SetMenu(hwnd, 0), "SetMenu");
608 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");
609 ok (SetMenu(hwnd, hmenu), "SetMenu");
610 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");
615 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
617 static long defwndproc_counter = 0;
621 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
623 msg.message = message;
624 msg.flags = sent|wparam|lparam;
625 if (defwndproc_counter) msg.flags |= defwinproc;
630 defwndproc_counter++;
631 ret = DefWindowProcA(hwnd, message, wParam, lParam);
632 defwndproc_counter--;
637 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
639 static long defwndproc_counter = 0;
643 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
645 msg.message = message;
646 msg.flags = sent|wparam|lparam;
647 if (defwndproc_counter) msg.flags |= defwinproc;
652 if (message == WM_CREATE)
654 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
655 SetWindowLongA(hwnd, GWL_STYLE, style);
658 defwndproc_counter++;
659 ret = DefWindowProcA(hwnd, message, wParam, lParam);
660 defwndproc_counter--;
665 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
667 static long defwndproc_counter = 0;
671 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
673 if (message == WM_PARENTNOTIFY)
675 msg.message = message;
676 msg.flags = sent|parent|wparam|lparam;
677 if (defwndproc_counter) msg.flags |= defwinproc;
683 defwndproc_counter++;
684 ret = DefWindowProcA(hwnd, message, wParam, lParam);
685 defwndproc_counter--;
690 static BOOL RegisterWindowClasses(void)
695 cls.lpfnWndProc = MsgCheckProcA;
698 cls.hInstance = GetModuleHandleA(0);
700 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
701 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
702 cls.lpszMenuName = NULL;
703 cls.lpszClassName = "TestWindowClass";
704 if(!RegisterClassA(&cls)) return FALSE;
706 cls.lpfnWndProc = PopupMsgCheckProcA;
707 cls.lpszClassName = "TestPopupClass";
708 if(!RegisterClassA(&cls)) return FALSE;
710 cls.lpfnWndProc = ParentMsgCheckProcA;
711 cls.lpszClassName = "TestParentClass";
712 if(!RegisterClassA(&cls)) return FALSE;
714 cls.lpfnWndProc = DefWindowProcA;
715 cls.lpszClassName = "SimpleWindowClass";
716 if(!RegisterClassA(&cls)) return FALSE;
721 static HHOOK hCBT_hook;
723 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
727 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
729 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
731 if (!strcmp(buf, "TestWindowClass") ||
732 !strcmp(buf, "TestParentClass") ||
733 !strcmp(buf, "TestPopupClass") ||
734 !strcmp(buf, "SimpleWindowClass"))
745 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
750 if (!RegisterWindowClasses()) assert(0);
752 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
757 UnhookWindowsHookEx(hCBT_hook);