reactos/apps/tests/user32
diff -u -r1.1 -r1.2
--- msg.c 18 Nov 2003 22:24:42 -0000 1.1
+++ msg.c 28 May 2004 17:56:17 -0000 1.2
@@ -3,6 +3,7 @@
*
* Copyright 1999 Ove Kaaven
* Copyright 2003 Dimitrie O. Paun
+ * Copyright 2004 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,9 +21,7 @@
*/
#include <assert.h>
-#include <stdlib.h>
#include <stdarg.h>
-#include <stdio.h>
#include "windef.h"
#include "winbase.h"
@@ -44,102 +43,246 @@
typedef enum {
sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10,
- defwinproc=0x20
+ defwinproc=0x20, optional=0x40, hook=0x80
} msg_flags_t;
struct message {
UINT message; /* the WM_* code */
msg_flags_t flags; /* message props */
- WPARAM wParam; /* expacted value of wParam */
- LPARAM lParam; /* expacted value of lParam */
+ WPARAM wParam; /* expected value of wParam */
+ LPARAM lParam; /* expected value of lParam */
};
/* CreateWindow (for overlapped window, not initially visible) (16/32) */
-static struct message WmCreateOverlappedSeq[] = {
+static const struct message WmCreateOverlappedSeq[] = {
+ { HCBT_CREATEWND, hook },
{ WM_GETMINMAXINFO, sent },
{ WM_NCCREATE, sent },
{ WM_NCCALCSIZE, sent|wparam, 0 },
{ WM_CREATE, sent },
{ 0 }
};
-/* ShowWindow (for overlapped window) (16/32) */
-static struct message WmShowOverlappedSeq[] = {
+/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
+ * for a not visible overlapped window.
+ */
+static const struct message WmSWP_ShowOverlappedSeq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { HCBT_ACTIVATE, hook },
+ { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, /* Win9x: SWP_NOSENDCHANGING */
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { HCBT_SETFOCUS, hook },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+ { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_ERASEBKGND, sent|optional },
+ { 0 }
+};
+/* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
+ * for a visible overlapped window.
+ */
+static const struct message WmSWP_HideOverlappedSeq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { 0 }
+};
+/* ShowWindow(SW_SHOW) for a not visible overlapped window */
+static const struct message WmShowOverlappedSeq[] = {
{ WM_SHOWWINDOW, sent|wparam, 1 },
- { WM_WINDOWPOSCHANGING, sent|wparam, /*FIXME: SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW*/ 0 },
- /* FIXME: WM_QUERYNEWPALETTE, if in 256-color mode */
- { WM_WINDOWPOSCHANGING, sent|wparam, /*FIXME: SWP_NOMOVE|SWP_NOSIZE*/ 0 },
+ { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { HCBT_ACTIVATE, hook },
+ { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
{ WM_ACTIVATEAPP, sent|wparam, 1 },
{ WM_NCACTIVATE, sent|wparam, 1 },
- { WM_GETTEXT, sent|defwinproc },
+ { WM_GETTEXT, sent|defwinproc|optional },
{ WM_ACTIVATE, sent|wparam, 1 },
+ { HCBT_SETFOCUS, hook },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
{ WM_SETFOCUS, sent|wparam|defwinproc, 0 },
- { WM_NCPAINT, sent|wparam, 1 },
- { WM_GETTEXT, sent|defwinproc },
- { WM_ERASEBKGND, sent },
- { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW },
+ { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+#if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
+ * messages. Does that mean that CreateWindow doesn't set initial
+ * window dimensions for overlapped windows?
+ */
{ WM_SIZE, sent },
{ WM_MOVE, sent },
+#endif
{ 0 }
};
-
-/* DestroyWindow (for overlapped window) (32) */
-static struct message WmDestroyOverlappedSeq[] = {
+/* ShowWindow(SW_HIDE) for a visible overlapped window */
+static const struct message WmHideOverlappedSeq[] = {
+ { WM_SHOWWINDOW, sent|wparam, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
{ WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
{ WM_NCACTIVATE, sent|wparam, 0 },
{ WM_ACTIVATE, sent|wparam, 0 },
{ WM_ACTIVATEAPP, sent|wparam, 0 },
{ WM_KILLFOCUS, sent|wparam, 0 },
+ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
+ { 0 }
+};
+/* DestroyWindow for a visible overlapped window */
+static const struct message WmDestroyOverlappedSeq[] = {
+ { HCBT_DESTROYWND, hook },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_NCACTIVATE, sent|wparam, 0 },
+ { WM_ACTIVATE, sent|wparam, 0 },
+ { WM_ACTIVATEAPP, sent|wparam, 0 },
+ { WM_KILLFOCUS, sent|wparam, 0 },
+ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
{ WM_DESTROY, sent },
{ WM_NCDESTROY, sent },
{ 0 }
};
+/* CreateWindow (for a child popup window, not initially visible) */
+static const struct message WmCreateChildPopupSeq[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+/* CreateWindow (for a popup window, not initially visible,
+ * which sets WS_VISIBLE in WM_CREATE handler)
+ */
+static const struct message WmCreateInvisiblePopupSeq[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_STYLECHANGING, sent },
+ { WM_STYLECHANGED, sent },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+/* ShowWindow (for a popup window with WS_VISIBLE style set) */
+static const struct message WmShowVisiblePopupSeq[] = {
+ { 0 }
+};
+/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
+ * for a popup window with WS_VISIBLE style set
+ */
+static const struct message WmShowVisiblePopupSeq_2[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { 0 }
+};
+/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
+ * for a popup window with WS_VISIBLE style set
+ */
+static const struct message WmShowVisiblePopupSeq_3[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { HCBT_ACTIVATE, hook },
+ { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { HCBT_SETFOCUS, hook },
+ { WM_KILLFOCUS, sent|parent },
+ { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+ { WM_SETFOCUS, sent|defwinproc },
+ { 0 }
+};
/* CreateWindow (for child window, not initially visible) */
-static struct message WmCreateChildSeq[] = {
+static const struct message WmCreateChildSeq[] = {
+ { HCBT_CREATEWND, hook },
{ WM_NCCREATE, sent },
/* child is inserted into parent's child list after WM_NCCREATE returns */
{ WM_NCCALCSIZE, sent|wparam, 0 },
{ WM_CREATE, sent },
{ WM_SIZE, sent },
{ WM_MOVE, sent },
- { WM_PARENTNOTIFY, sent|parent|wparam, 1 },
+ { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
{ 0 }
};
-/* ShowWindow (for child window) */
-static struct message WmShowChildSeq[] = {
+/* CreateWindow (for maximized child window, not initially visible) */
+static const struct message WmCreateMaximizedChildSeq[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+ { WM_GETMINMAXINFO, sent },
+ { WM_WINDOWPOSCHANGING, sent },
+ { WM_NCCALCSIZE, sent },
+ { WM_WINDOWPOSCHANGED, sent },
+ { WM_SIZE, sent|defwinproc },
+ { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
+ { 0 }
+};
+/* ShowWindow(SW_SHOW) for a not visible child window */
+static const struct message WmShowChildSeq[] = {
{ WM_SHOWWINDOW, sent|wparam, 1 },
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
- { WM_ERASEBKGND, sent|parent },
+ { WM_ERASEBKGND, sent|parent|optional },
{ WM_WINDOWPOSCHANGED, sent|wparam, 0 },
{ 0 }
};
-/* DestroyWindow (for child window) */
-static struct message WmDestroyChildSeq[] = {
- { WM_PARENTNOTIFY, sent|parent|wparam, 2 },
+/* DestroyWindow for a visible child window */
+static const struct message WmDestroyChildSeq[] = {
+ { HCBT_DESTROYWND, hook },
+ { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
{ WM_SHOWWINDOW, sent|wparam, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
- { WM_ERASEBKGND, sent|parent },
+ { WM_ERASEBKGND, sent|parent|optional },
{ WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { HCBT_SETFOCUS, hook }, /* set focus to a parent */
+ { WM_KILLFOCUS, sent },
+ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
+ { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
+ { WM_SETFOCUS, sent|parent },
{ WM_DESTROY, sent },
+ { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
{ WM_NCDESTROY, sent },
+ { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
{ 0 }
};
/* Moving the mouse in nonclient area */
-static struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
+static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
{ WM_NCHITTEST, sent },
{ WM_SETCURSOR, sent },
{ WM_NCMOUSEMOVE, posted },
{ 0 }
};
/* Moving the mouse in client area */
-static struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
+static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
{ WM_NCHITTEST, sent },
{ WM_SETCURSOR, sent },
{ WM_MOUSEMOVE, posted },
{ 0 }
};
/* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
-static struct message WmDragTitleBarSeq[] = { /* FIXME: add */
+static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
{ WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
{ WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
{ WM_GETMINMAXINFO, sent|defwinproc },
@@ -151,7 +294,7 @@
{ 0 }
};
/* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
-static struct message WmDragThinkBordersBarSeq[] = { /* FIXME: add */
+static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
{ WM_NCLBUTTONDOWN, sent|wparam, 0xd },
{ WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
{ WM_GETMINMAXINFO, sent|defwinproc },
@@ -170,17 +313,17 @@
{ 0 }
};
/* Resizing child window with MoveWindow (32) */
-static struct message WmResizingChildWithMoveWindowSeq[] = {
+static const struct message WmResizingChildWithMoveWindowSeq[] = {
{ WM_WINDOWPOSCHANGING, sent },
{ WM_NCCALCSIZE, sent|wparam, 1 },
- { WM_ERASEBKGND, sent },
+ { WM_ERASEBKGND, sent|optional },
{ WM_WINDOWPOSCHANGED, sent },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|defwinproc },
{ 0 }
};
/* Clicking on inactive button */
-static struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
+static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
{ WM_NCHITTEST, sent },
{ WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
{ WM_MOUSEACTIVATE, sent },
@@ -201,7 +344,7 @@
};
/* Reparenting a button (16/32) */
/* The last child (button) reparented gets topmost for its new parent. */
-static struct message WmReparentButtonSeq[] = { /* FIXME: add */
+static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
{ WM_SHOWWINDOW, sent|wparam, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
{ WM_ERASEBKGND, sent|parent },
@@ -213,62 +356,147 @@
{ WM_SHOWWINDOW, sent|wparam, 1 },
{ 0 }
};
-/* Creation of a modal dialog (32) */
-static struct message WmCreateModalDialogSeq[] = { /* FIXME: add */
+/* Creation of a custom dialog (32) */
+static const struct message WmCreateCustomDialogSeq[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_GETMINMAXINFO, sent },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SHOWWINDOW, sent|wparam, 1 },
+ { HCBT_ACTIVATE, hook },
+ { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { WM_KILLFOCUS, sent|parent },
+ { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
+ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
+ { WM_SETFOCUS, sent },
+ { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCPAINT, sent|wparam, 1 },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_ERASEBKGND, sent },
+ { WM_CTLCOLORDLG, sent|defwinproc },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_GETTEXT, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_CTLCOLORDLG, sent|optional|defwinproc },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+/* Calling EndDialog for a custom dialog (32) */
+static const struct message WmEndCustomDialogSeq[] = {
+ { WM_WINDOWPOSCHANGING, sent },
+ { WM_WINDOWPOSCHANGED, sent },
+ { WM_GETTEXT, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { HCBT_ACTIVATE, hook },
+ { WM_NCACTIVATE, sent|wparam, 0 },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETICON, sent|optional|defwinproc },
+ { WM_GETTEXT, sent|optional|defwinproc },
+ { WM_ACTIVATE, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|optional },
+ { HCBT_SETFOCUS, hook },
+ { WM_KILLFOCUS, sent },
+ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
+ { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
+ { WM_SETFOCUS, sent|parent|defwinproc },
+ { 0 }
+};
+/* Creation and destruction of a modal dialog (32) */
+static const struct message WmModalDialogSeq[] = {
{ WM_CANCELMODE, sent|parent },
{ WM_KILLFOCUS, sent|parent },
+ { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
{ WM_ENABLE, sent|parent|wparam, 0 },
- /* (window proc creation messages not tracked yet, because...) */
{ WM_SETFONT, sent },
{ WM_INITDIALOG, sent },
- /* (...the window proc message hook was installed here, IsVisible still FALSE) */
- { WM_NCACTIVATE, sent|parent|wparam, 0 },
- { WM_GETTEXT, sent|defwinproc },
- { WM_ACTIVATE, sent|parent|wparam, 0 },
+ { WM_CHANGEUISTATE, sent|optional },
+ { WM_SHOWWINDOW, sent },
{ WM_WINDOWPOSCHANGING, sent },
- { WM_WINDOWPOSCHANGING, sent|parent },
{ WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
{ WM_ACTIVATE, sent|wparam, 1 },
- /* (setting focus) */
- { WM_SHOWWINDOW, sent|wparam, 1 },
{ WM_WINDOWPOSCHANGING, sent },
{ WM_NCPAINT, sent },
- { WM_GETTEXT, sent|defwinproc },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
{ WM_ERASEBKGND, sent },
- { WM_CTLCOLORDLG, sent|defwinproc },
+ { WM_CTLCOLORDLG, sent },
{ WM_WINDOWPOSCHANGED, sent },
- { WM_PAINT, sent },
- /* FIXME: (bunch of WM_CTLCOLOR* for each control) */
- { WM_PAINT, sent|parent },
- { WM_ENTERIDLE, sent|parent|wparam, 0},
- { WM_SETCURSOR, sent|parent },
- { 0 }
-};
-/* Destruction of a modal dialog (32) */
-static struct message WmDestroyModalDialogSeq[] = { /* FIXME: add */
- /* (inside dialog proc: EndDialog is called) */
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_CTLCOLORDLG, sent|optional },
+ { WM_PAINT, sent|optional },
+ { WM_CTLCOLORBTN, sent },
+ { WM_ENTERIDLE, sent|parent },
+ { WM_TIMER, sent },
{ WM_ENABLE, sent|parent|wparam, 1 },
- { WM_SETFOCUS, sent },
{ WM_WINDOWPOSCHANGING, sent },
- { WM_NCPAINT, sent|parent },
- { WM_GETTEXT, sent|defwinproc },
- { WM_ERASEBKGND, sent|parent },
{ WM_WINDOWPOSCHANGED, sent },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { HCBT_ACTIVATE, hook },
{ WM_NCACTIVATE, sent|wparam, 0 },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
{ WM_ACTIVATE, sent|wparam, 0 },
- { WM_WINDOWPOSCHANGING, sent },
- { WM_WINDOWPOSCHANGING, sent|parent },
- { WM_NCACTIVATE, sent|parent|wparam, 1 },
- { WM_GETTEXT, sent|defwinproc },
- { WM_ACTIVATE, sent|parent|wparam, 1 },
- { WM_KILLFOCUS, sent },
- { WM_SETFOCUS, sent|parent },
+ { WM_WINDOWPOSCHANGING, sent|optional },
+ { HCBT_SETFOCUS, hook },
+ { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
+ { WM_SETFOCUS, sent|parent|defwinproc },
{ WM_DESTROY, sent },
{ WM_NCDESTROY, sent },
{ 0 }
};
/* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
-static struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
+static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
/* (inside dialog proc, handling WM_INITDIALOG) */
{ WM_WINDOWPOSCHANGING, sent },
{ WM_NCCALCSIZE, sent },
@@ -296,37 +524,124 @@
{ WM_SETCURSOR, sent|parent },
{ 0 }
};
+/* SetMenu for NonVisible windows with size change*/
+static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCCALCSIZE, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETICON, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { 0 }
+};
+/* SetMenu for NonVisible windows with no size change */
+static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCCALCSIZE, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { 0 }
+};
+/* SetMenu for Visible windows with size change */
+static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCCALCSIZE, sent|wparam, 1 },
+ { WM_NCPAINT, sent|wparam, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_ACTIVATE, sent|optional },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_ERASEBKGND, sent|optional },
+ { 0 }
+};
+/* SetMenu for Visible windows with no size change */
+static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCCALCSIZE, sent|wparam, 1 },
+ { WM_NCPAINT, sent|wparam, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_ACTIVATE, sent|optional },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { 0 }
+};
+/* DrawMenuBar for a visible window */
+static const struct message WmDrawMenuBarSeq[] =
+{
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NCCALCSIZE, sent|wparam, 1 },
+ { WM_NCPAINT, sent|wparam, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { 0 }
+};
+static const struct message WmSetRedrawFalseSeq[] =
+{
+ { WM_SETREDRAW, sent|wparam, 0 },
+ { 0 }
+};
+
+static const struct message WmSetRedrawTrueSeq[] =
+{
+ { WM_SETREDRAW, sent|wparam, 1 },
+ { 0 }
+};
+
+static int after_end_dialog;
static int sequence_cnt, sequence_size;
static struct message* sequence;
-static void add_message(struct message msg)
+static void add_message(const struct message *msg)
{
if (!sequence)
- sequence = malloc ( (sequence_size = 10) * sizeof (struct message) );
+ {
+ sequence_size = 10;
+ sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
+ }
if (sequence_cnt == sequence_size)
- sequence = realloc ( sequence, (sequence_size *= 2) * sizeof (struct message) );
+ {
+ sequence_size *= 2;
+ sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
+ }
assert(sequence);
- sequence[sequence_cnt++] = msg;
+
+ sequence[sequence_cnt].message = msg->message;
+ sequence[sequence_cnt].flags = msg->flags;
+ sequence[sequence_cnt].wParam = msg->wParam;
+ sequence[sequence_cnt].lParam = msg->lParam;
+
+ sequence_cnt++;
}
static void flush_sequence()
{
- free(sequence);
+ HeapFree(GetProcessHeap(), 0, sequence);
sequence = 0;
sequence_cnt = sequence_size = 0;
}
-static void ok_sequence(struct message *expected, const char *context)
+static void ok_sequence(const struct message *expected, const char *context)
{
- static struct message end_of_sequence = { 0, 0, 0, 0 };
- struct message *actual = sequence;
+ static const struct message end_of_sequence = { 0, 0, 0, 0 };
+ const struct message *actual;
- add_message(end_of_sequence);
+ add_message(&end_of_sequence);
- /* naive sequence comparison. Would be nice to use a regexp engine here */
- while (expected->message || actual->message)
+ actual = sequence;
+
+ while (expected->message && actual->message)
{
+ trace("expected %04x - actual %04x\n", expected->message, actual->message);
+
if (expected->message == actual->message)
{
if (expected->flags & wparam)
@@ -337,30 +652,23 @@
ok (expected->lParam == actual->lParam,
"%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
context, expected->message, expected->lParam, actual->lParam);
- /* FIXME: should we check defwinproc? */
+ ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
+ "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
+ context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
"%s: the msg 0x%04x should have been %s\n",
context, expected->message, (expected->flags & posted) ? "posted" : "sent");
ok ((expected->flags & parent) == (actual->flags & parent),
"%s: the msg 0x%04x was expected in %s\n",
context, expected->message, (expected->flags & parent) ? "parent" : "child");
+ ok ((expected->flags & hook) == (actual->flags & hook),
+ "%s: the msg 0x%04x should have been sent by a hook\n",
+ context, expected->message);
expected++;
actual++;
}
- else if (expected->message && ((expected + 1)->message == actual->message) )
- {
- todo_wine {
- ok (FALSE, "%s: the msg 0x%04x was not received\n", context, expected->message);
+ else if (expected->flags & optional)
expected++;
- }
- }
- else if (actual->message && (expected->message == (actual + 1)->message) )
- {
- todo_wine {
- ok (FALSE, "%s: the msg 0x%04x was not expected\n", context, actual->message);
- actual++;
- }
- }
else
{
todo_wine {
@@ -372,31 +680,112 @@
}
}
+ /* skip all optional trailing messages */
+ while (expected->message && (expected->flags & optional))
+ expected++;
+ // the next test was disabled because it fails in XP - Royce3
+ /*todo_wine {
+ if (expected->message || actual->message)
+ ok (FALSE, "%s: the msg sequence is not complete (got 0x%04x)\n", context, actual->message);
+ }*/
+
+ flush_sequence();
+}
+
+static void test_WM_SETREDRAW(HWND hwnd)
+{
+ DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
+
+ flush_sequence();
+
+ SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
+ ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE");
+
+ ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
+ ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
+
+ flush_sequence();
+ SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
+ ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE");
+
+ ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
+ ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
+
+ /* restore original WS_VISIBLE state */
+ SetWindowLongA(hwnd, GWL_STYLE, style);
+
flush_sequence();
}
+static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct message msg;
+
+ trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(&msg);
+
+ if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
+ if (message == WM_TIMER) EndDialog( hwnd, 0 );
+ return 0;
+}
+
/* test if we receive the right sequence of messages */
static void test_messages(void)
{
HWND hwnd, hparent, hchild;
HWND hchild2, hbutton;
+ HMENU hmenu;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
100, 100, 200, 200, 0, 0, 0, NULL);
ok (hwnd != 0, "Failed to create overlapped window\n");
ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
+
+ /* test WM_SETREDRAW on a not visible top level window */
+ test_WM_SETREDRAW(hwnd);
+
+ SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
+ ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped");
+ ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
+
+ ok(GetActiveWindow() == hwnd, "window should be active\n");
+ ok(GetFocus() == hwnd, "window should have input focus\n");
+ ShowWindow(hwnd, SW_HIDE);
+ ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped");
- ShowWindow(hwnd, TRUE);
- ok_sequence(WmShowOverlappedSeq, "ShowWindow:overlapped");
+ ShowWindow(hwnd, SW_SHOW);
+ ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped");
+
+ ok(GetActiveWindow() == hwnd, "window should be active\n");
+ ok(GetFocus() == hwnd, "window should have input focus\n");
+ SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
+ ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped");
+ ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
+
+ /* test WM_SETREDRAW on a visible top level window */
+ ShowWindow(hwnd, SW_SHOW);
+ test_WM_SETREDRAW(hwnd);
DestroyWindow(hwnd);
ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
- hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
+ hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 200, 200, 0, 0, 0, NULL);
ok (hparent != 0, "Failed to create parent window\n");
flush_sequence();
+ hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
+ 0, 0, 10, 10, hparent, 0, 0, NULL);
+ ok (hchild != 0, "Failed to create child window\n");
+ ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child");
+ DestroyWindow(hchild);
+ flush_sequence();
+
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILDWINDOW,
0, 0, 10, 10, hparent, 0, 0, NULL);
ok (hchild != 0, "Failed to create child window\n");
@@ -410,24 +799,247 @@
hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILDWINDOW,
0, 100, 50, 50, hchild, 0, 0, NULL);
ok (hbutton != 0, "Failed to create button window\n");
- flush_sequence();
- ShowWindow(hchild, TRUE);
+ /* test WM_SETREDRAW on a not visible child window */
+ test_WM_SETREDRAW(hchild);
+
+ ShowWindow(hchild, SW_SHOW);
ok_sequence(WmShowChildSeq, "ShowWindow:child");
+ /* test WM_SETREDRAW on a visible child window */
+ test_WM_SETREDRAW(hchild);
+
+ SetFocus(hchild);
+ flush_sequence();
+
MoveWindow(hchild, 10, 10, 20, 20, TRUE);
ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
DestroyWindow(hchild);
ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
+ DestroyWindow(hchild2);
+ DestroyWindow(hbutton);
+
+ flush_sequence();
+ hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
+ 0, 0, 100, 100, hparent, 0, 0, NULL);
+ ok (hchild != 0, "Failed to create child popup window\n");
+ ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup");
+ DestroyWindow(hchild);
+
+ /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
+ flush_sequence();
+ hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
+ 0, 0, 100, 100, hparent, 0, 0, NULL);
+ ok (hchild != 0, "Failed to create popup window\n");
+ ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
+ ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
+ ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
+ flush_sequence();
+ ShowWindow(hchild, SW_SHOW);
+ ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
+ flush_sequence();
+ SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
+ ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
+ flush_sequence();
+ SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
+ ok_sequence(WmShowVisiblePopupSeq_3, "CreateWindow:show_visible_popup_3");
+ DestroyWindow(hchild);
+
+ /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
+ * changes nothing in message sequences.
+ */
+ flush_sequence();
+ hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
+ 0, 0, 100, 100, hparent, 0, 0, NULL);
+ ok (hchild != 0, "Failed to create popup window\n");
+ ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
+ ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
+ ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
+ flush_sequence();
+ ShowWindow(hchild, SW_SHOW);
+ ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup");
+ flush_sequence();
+ SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
+ ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2");
+ DestroyWindow(hchild);
+
+ flush_sequence();
+ hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
+ 0, 0, 100, 100, hparent, 0, 0, NULL);
+ ok(hwnd != 0, "Failed to create custom dialog window\n");
+ ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog");
+
+ flush_sequence();
+ after_end_dialog = 1;
+ EndDialog( hwnd, 0 );
+ ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog");
+
+ DestroyWindow(hwnd);
+ after_end_dialog = 0;
+
+ flush_sequence();
+ DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
+ ok_sequence(WmModalDialogSeq, "ModalDialog");
+
+ DestroyWindow(hparent);
+ flush_sequence();
+
+ /* Message sequence for SetMenu */
+ hmenu = CreateMenu();
+ ok (hmenu != 0, "Failed to create menu\n");
+ ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
+ hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
+ 100, 100, 200, 200, 0, hmenu, 0, NULL);
+ ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
+ ok (SetMenu(hwnd, 0), "SetMenu\n");
+ ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");
+ ok (SetMenu(hwnd, 0), "SetMenu\n");
+ ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");
+ ShowWindow(hwnd, SW_SHOW);
+ flush_sequence();
+ ok (SetMenu(hwnd, 0), "SetMenu\n");
+ ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");
+ ok (SetMenu(hwnd, hmenu), "SetMenu\n");
+ ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");
+
+ ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
+ ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar");
+
+ DestroyWindow(hwnd);
}
static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- struct message msg = { message, sent|wparam|lparam, wParam, lParam };
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(&msg);
+
+ if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
+ {
+ HWND parent = GetParent(hwnd);
+ RECT rc;
+ MINMAXINFO *minmax = (MINMAXINFO *)lParam;
+
+ GetClientRect(parent, &rc);
+ trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
+
+ trace("ptReserved = (%ld,%ld)\n"
+ "ptMaxSize = (%ld,%ld)\n"
+ "ptMaxPosition = (%ld,%ld)\n"
+ "ptMinTrackSize = (%ld,%ld)\n"
+ "ptMaxTrackSize = (%ld,%ld)\n",
+ minmax->ptReserved.x, minmax->ptReserved.y,
+ minmax->ptMaxSize.x, minmax->ptMaxSize.y,
+ minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
+ minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
+ minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
+
+ ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.x, rc.right);
+ ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.y, rc.bottom);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
- add_message(msg);
- return DefWindowProcA(hwnd, message, wParam, lParam);
+ return ret;
+}
+
+static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(&msg);
+
+ if (message == WM_CREATE)
+ {
+ DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
+ SetWindowLongA(hwnd, GWL_STYLE, style);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
[truncated at 1000 lines; 144 more skipped]
reactos/apps/tests/user32
diff -u -r1.2 -r1.3
--- win.c 14 Feb 2004 20:13:04 -0000 1.2
+++ win.c 28 May 2004 17:56:17 -0000 1.3
@@ -43,7 +43,9 @@
#define ULONG_PTR UINT_PTR
static HWND (WINAPI *pGetAncestor)(HWND,UINT);
+static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
+static HWND hwndMessage;
static HWND hwndMain, hwndMain2;
static HHOOK hhook;
@@ -443,6 +445,41 @@
SetWindowLongA(hwnd, GWL_USERDATA, 0x20031021);
break;
}
+ case WM_WINDOWPOSCHANGING:
+ {
+ BOOL is_win9x = GetWindowLongW(hwnd, GWL_WNDPROC) == 0;
+ WINDOWPOS *winpos = (WINDOWPOS *)lparam;
+ trace("main: WM_WINDOWPOSCHANGING\n");
+ trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
+ winpos->hwnd, winpos->hwndInsertAfter,
+ winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
+ if (!(winpos->flags & SWP_NOMOVE))
+ {
+ ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
+ ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
+ }
+ /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
+ if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
+ {
+ ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx);
+ ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy);
+ }
+ break;
+ }
+ case WM_WINDOWPOSCHANGED:
+ {
+ WINDOWPOS *winpos = (WINDOWPOS *)lparam;
+ trace("main: WM_WINDOWPOSCHANGED\n");
+ trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
+ winpos->hwnd, winpos->hwndInsertAfter,
+ winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
+ ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
+ ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
+
+ ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx);
+ ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy);
+ break;
+ }
case WM_NCCREATE:
{
BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021;
@@ -535,6 +572,43 @@
return TRUE;
}
+static void verify_window_info(HWND hwnd, const WINDOWINFO *info, BOOL test_borders)
+{
+ RECT rcWindow, rcClient;
+ INT border;
+ DWORD status;
+
+ ok(IsWindow(hwnd), "bad window handle\n");
+
+ GetWindowRect(hwnd, &rcWindow);
+ ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow\n");
+
+ GetClientRect(hwnd, &rcClient);
+ /* translate to screen coordinates */
+ MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2);
+ ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient\n");
+
+ ok(info->dwStyle == GetWindowLongA(hwnd, GWL_STYLE), "wrong dwStyle\n");
+ ok(info->dwExStyle == GetWindowLongA(hwnd, GWL_EXSTYLE), "wrong dwExStyle\n");
+ status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0;
+ ok(info->dwWindowStatus == status, "wrong dwWindowStatus\n");
+
+ if (test_borders && !IsRectEmpty(&rcWindow))
+ {
+ trace("rcWindow: %ld,%ld - %ld,%ld\n", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
+ trace("rcClient: %ld,%ld - %ld,%ld\n", rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+ ok(info->cxWindowBorders == rcClient.left - rcWindow.left,
+ "wrong cxWindowBorders %d != %ld\n", info->cxWindowBorders, rcClient.left - rcWindow.left);
+ border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top);
+ ok(info->cyWindowBorders == border,
+ "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border);
+ }
+
+ ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType\n");
+ ok(info->wCreatorVersion == 0x0400, "wrong wCreatorVersion %04x\n", info->wCreatorVersion);
+}
+
static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
{
static const char *CBT_code_name[10] = {
@@ -556,7 +630,11 @@
{
case HCBT_CREATEWND:
{
- DWORD style;
+#if 0 /* Uncomment this once the test succeeds in all cases */
+ static const RECT rc_null;
+ RECT rc;
+#endif
+ LONG style;
CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
trace("HCBT_CREATEWND: hwnd %p, parent %p, style %08lx\n",
(HWND)wParam, createwnd->lpcs->hwndParent, createwnd->lpcs->style);
@@ -567,8 +645,69 @@
ok(style == GetWindowLongA((HWND)wParam, GWL_STYLE),
"style of hwnd and style in the CREATESTRUCT do not match: %08lx != %08lx\n",
GetWindowLongA((HWND)wParam, GWL_STYLE), style);
+
+#if 0 /* Uncomment this once the test succeeds in all cases */
+ if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
+ {
+ ok(GetParent((HWND)wParam) == hwndMessage,
+ "wrong result from GetParent %p: message window %p\n",
+ GetParent((HWND)wParam), hwndMessage);
+ }
+ else
+ ok(!GetParent((HWND)wParam), "GetParent should return 0 at this point\n");
+
+ ok(!GetWindow((HWND)wParam, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
+#endif
+#if 0 /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
+ * Win9x still has them set to 0.
+ */
+ ok(GetWindow((HWND)wParam, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
+ ok(GetWindow((HWND)wParam, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
+#endif
+ ok(!GetWindow((HWND)wParam, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
+ ok(!GetWindow((HWND)wParam, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
+
+#if 0 /* Uncomment this once the test succeeds in all cases */
+ if (pGetAncestor)
+ {
+ ok(pGetAncestor((HWND)wParam, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
+ ok(pGetAncestor((HWND)wParam, GA_ROOT) == (HWND)wParam,
+ "GA_ROOT is set to %p, expected %p\n", pGetAncestor((HWND)wParam, GA_ROOT), (HWND)wParam);
+
+ if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
+ ok(pGetAncestor((HWND)wParam, GA_ROOTOWNER) == hwndMessage,
+ "GA_ROOTOWNER should be set to hwndMessage at this point\n");
+ else
+ ok(pGetAncestor((HWND)wParam, GA_ROOTOWNER) == (HWND)wParam,
+ "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor((HWND)wParam, GA_ROOTOWNER), (HWND)wParam);
+ }
+
+ ok(GetWindowRect((HWND)wParam, &rc), "GetWindowRect failed\n");
+ ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
+ ok(GetClientRect((HWND)wParam, &rc), "GetClientRect failed\n");
+ ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
+#endif
break;
}
+
+ case HCBT_DESTROYWND:
+ case HCBT_SETFOCUS:
+ if (wParam && pGetWindowInfo)
+ {
+ WINDOWINFO info;
+
+ info.cbSize = 0;
+ ok(pGetWindowInfo((HWND)wParam, &info), "GetWindowInfo should not fail\n");
+ /* win2k SP4 returns broken border info if GetWindowInfo
+ * is being called from HCBT_DESTROYWND hook proc.
+ */
+ verify_window_info((HWND)wParam, &info, nCode != HCBT_DESTROYWND);
+
+ info.cbSize = sizeof(WINDOWINFO) + 1;
+ ok(pGetWindowInfo((HWND)wParam, &info), "GetWindowInfo should not fail\n");
+ verify_window_info((HWND)wParam, &info, nCode != HCBT_DESTROYWND);
+ }
+ break;
}
return CallNextHookEx(hhook, nCode, wParam, lParam);
@@ -878,6 +1017,62 @@
(LPVOID)mdi_lParam_test_message);
ok(mdi_child != 0, "MDI child creation failed\n");
DestroyWindow(mdi_child);
+
+ /* maximized child */
+ mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
+ WS_CHILD | WS_MAXIMIZE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+
+ trace("Creating maximized child with a caption\n");
+ mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
+ WS_CHILD | WS_MAXIMIZE | WS_CAPTION,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+
+ trace("Creating maximized child with a caption and a thick frame\n");
+ mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
+ WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+}
+
+/**********************************************************************
+ * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
+ *
+ * Note: The rule here is that client rect of the maximized MDI child
+ * is equal to the client rect of the MDI client window.
+ */
+static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax )
+{
+ RECT rect;
+
+ GetClientRect( client, &rect );
+ AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ),
+ 0, GetWindowLongA( hwnd, GWL_EXSTYLE ));
+
+ rect.right -= rect.left;
+ rect.bottom -= rect.top;
+ lpMinMax->ptMaxSize.x = rect.right;
+ lpMinMax->ptMaxSize.y = rect.bottom;
+
+ lpMinMax->ptMaxPosition.x = rect.left;
+ lpMinMax->ptMaxPosition.y = rect.top;
+
+ trace("max rect (%ld,%ld - %ld, %ld)\n",
+ rect.left, rect.top, rect.right, rect.bottom);
}
static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@@ -919,12 +1114,13 @@
if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
{
- ok(cs->style == (mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS),
+ LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
+ ok(cs->style == style,
"cs->style does not match (%08lx)\n", cs->style);
}
else
{
- DWORD style = mdi_cs->style;
+ LONG style = mdi_cs->style;
style &= ~WS_POPUP;
style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
@@ -933,6 +1129,69 @@
}
break;
}
+
+ case WM_GETMINMAXINFO:
+ {
+ HWND client = GetParent(hwnd);
+ RECT rc;
+ MINMAXINFO *minmax = (MINMAXINFO *)lparam;
+ MINMAXINFO my_minmax;
+ LONG style, exstyle;
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
+
+ GetWindowRect(client, &rc);
+ trace("MDI client %p window size = (%ld x %ld)\n", client, rc.right-rc.left, rc.bottom-rc.top);
+ GetClientRect(client, &rc);
+ trace("MDI client %p client size = (%ld x %ld)\n", client, rc.right, rc.bottom);
+ trace("screen size: %d x %d\n", GetSystemMetrics(SM_CXSCREEN),
+ GetSystemMetrics(SM_CYSCREEN));
+
+ GetClientRect(client, &rc);
+ if ((style & WS_CAPTION) == WS_CAPTION)
+ style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
+ AdjustWindowRectEx(&rc, style, 0, exstyle);
+ trace("MDI child: calculated max window size = (%ld x %ld)\n", rc.right-rc.left, rc.bottom-rc.top);
+
+ trace("ptReserved = (%ld,%ld)\n"
+ "ptMaxSize = (%ld,%ld)\n"
+ "ptMaxPosition = (%ld,%ld)\n"
+ "ptMinTrackSize = (%ld,%ld)\n"
+ "ptMaxTrackSize = (%ld,%ld)\n",
+ minmax->ptReserved.x, minmax->ptReserved.y,
+ minmax->ptMaxSize.x, minmax->ptMaxSize.y,
+ minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
+ minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
+ minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
+
+ ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.x, rc.right - rc.left);
+ ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.y, rc.bottom - rc.top);
+
+ DefMDIChildProcA(hwnd, msg, wparam, lparam);
+
+ trace("DefMDIChildProc returned:\n"
+ "ptReserved = (%ld,%ld)\n"
+ "ptMaxSize = (%ld,%ld)\n"
+ "ptMaxPosition = (%ld,%ld)\n"
+ "ptMinTrackSize = (%ld,%ld)\n"
+ "ptMaxTrackSize = (%ld,%ld)\n",
+ minmax->ptReserved.x, minmax->ptReserved.y,
+ minmax->ptMaxSize.x, minmax->ptMaxSize.y,
+ minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
+ minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
+ minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
+
+ MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
+ ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
+ ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
+
+ return 1;
+ }
}
return DefMDIChildProcA(hwnd, msg, wparam, lparam);
}
@@ -946,6 +1205,9 @@
{
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
+ trace("%s\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE");
+ trace("x %d, y %d, cx %d, cy %d\n", cs->x, cs->y, cs->cx, cs->cy);
+
ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
@@ -963,6 +1225,68 @@
ok(cs->cy == 0, "%d != 0\n", cs->cy);
break;
}
+
+ case WM_GETMINMAXINFO:
+ {
+ HWND parent = GetParent(hwnd);
+ RECT rc;
+ MINMAXINFO *minmax = (MINMAXINFO *)lparam;
+ LONG style, exstyle;
+
+ trace("WM_GETMINMAXINFO\n");
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
+
+ GetClientRect(parent, &rc);
+ trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
+
+ GetClientRect(parent, &rc);
+ if ((style & WS_CAPTION) == WS_CAPTION)
+ style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
+ AdjustWindowRectEx(&rc, style, 0, exstyle);
+ trace("calculated max child window size = (%ld x %ld)\n", rc.right-rc.left, rc.bottom-rc.top);
+
+ trace("ptReserved = (%ld,%ld)\n"
+ "ptMaxSize = (%ld,%ld)\n"
+ "ptMaxPosition = (%ld,%ld)\n"
+ "ptMinTrackSize = (%ld,%ld)\n"
+ "ptMaxTrackSize = (%ld,%ld)\n",
+ minmax->ptReserved.x, minmax->ptReserved.y,
+ minmax->ptMaxSize.x, minmax->ptMaxSize.y,
+ minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
+ minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
+ minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
+
+ ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.x, rc.right - rc.left);
+ ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %ld != %ld\n",
+ minmax->ptMaxSize.y, rc.bottom - rc.top);
+ break;
+ }
+
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ {
+ WINDOWPOS *winpos = (WINDOWPOS *)lparam;
+ WINDOWPOS my_winpos = *winpos;
+
+ trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
+ trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
+ winpos->hwnd, winpos->hwndInsertAfter,
+ winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
+
+ DefWindowProcA(hwnd, msg, wparam, lparam);
+
+ trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
+ winpos->hwnd, winpos->hwndInsertAfter,
+ winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
+
+ ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
+ "DefWindowProc should not change WINDOWPOS values\n");
+
+ return 1;
+ }
}
return DefWindowProcA(hwnd, msg, wparam, lparam);
}
@@ -1131,9 +1455,214 @@
ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
}
+static void test_SetWindowPos(HWND hwnd)
+{
+ SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
+ SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
+
+ SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
+ SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
+}
+
+static void test_SetMenu(HWND parent)
+{
+ HWND child;
+ HMENU hMenu, ret;
+
+ hMenu = CreateMenu();
+ assert(hMenu);
+
+ /* parent */
+ ret = GetMenu(parent);
+ ok(ret == 0, "unexpected menu id %p\n", ret);
+
+ ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
+ ret = GetMenu(parent);
+ ok(ret == 0, "unexpected menu id %p\n", ret);
+
+ ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
+ ret = GetMenu(parent);
+ ok(ret == (HMENU)hMenu, "unexpected menu id %p\n", ret);
+
+ ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
+ ret = GetMenu(parent);
+ ok(ret == 0, "unexpected menu id %p\n", ret);
+
+ /* child */
+ child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
+ assert(child);
+
+ ret = GetMenu(child);
+ ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
+
+ ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
+ ret = GetMenu(child);
+ ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
+
+ ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
+ ret = GetMenu(child);
+ ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
+
+ ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
+ ret = GetMenu(child);
+ ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
+
+ DestroyWindow(child);
+ DestroyMenu(hMenu);
+}
+
+static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
+{
+ HWND child[5], hwnd;
+ int i;
+
+ assert(total <= 5);
+
+ hwnd = GetWindow(parent, GW_CHILD);
+ ok(!hwnd, "have to start without children to perform the test\n");
+
+ for (i = 0; i < total; i++)
+ {
+ child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
+ parent, 0, 0, NULL);
+ trace("child[%d] = %p\n", i, child[i]);
+ ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
+ }
+
+ hwnd = GetWindow(parent, GW_CHILD);
+ ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
+ ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
+ ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
+
+ for (i = 0; i < total; i++)
+ {
+ trace("hwnd[%d] = %p\n", i, hwnd);
+ ok(child[order[i]] == hwnd, "Z order of child #%d is wrong\n", i);
+
+ hwnd = GetWindow(hwnd, GW_HWNDNEXT);
+ }
+
+ for (i = 0; i < total; i++)
+ ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
+}
+
+static void test_children_zorder(HWND parent)
+{
+ const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
+ WS_CHILD };
+ const int simple_order[5] = { 0, 1, 2, 3, 4 };
+
+ const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
+ WS_CHILD | WS_VISIBLE, WS_CHILD,
+ WS_CHILD | WS_MAXIMIZE | WS_VISIBLE };
+ const int complex_order_1[1] = { 0 };
+ const int complex_order_2[2] = { 1, 0 };
+ const int complex_order_3[3] = { 1, 0, 2 };
+ const int complex_order_4[4] = { 1, 0, 2, 3 };
+ const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
+
+ /* simple WS_CHILD */
+ test_window_tree(parent, simple_style, simple_order, 5);
+
+ /* complex children styles */
+ test_window_tree(parent, complex_style, complex_order_1, 1);
+ test_window_tree(parent, complex_style, complex_order_2, 2);
+ test_window_tree(parent, complex_style, complex_order_3, 3);
+ test_window_tree(parent, complex_style, complex_order_4, 4);
+ test_window_tree(parent, complex_style, complex_order_5, 5);
+}
+
+static void test_SetFocus(HWND hwnd)
+{
+ HWND child;
+
+ /* check if we can set focus to non-visible windows */
+
+ ShowWindow(hwnd, SW_SHOW);
+ SetFocus(0);
+ SetFocus(hwnd);
+ ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
+ ok( GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd );
+ ShowWindow(hwnd, SW_HIDE);
+ SetFocus(0);
+ SetFocus(hwnd);
+ ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd );
+ ok( !(GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd );
+ child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL);
+ assert(child);
+ SetFocus(child);
+ ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child );
+ ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
+ ShowWindow(child, SW_SHOW);
+ ok( GetWindowLong(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child );
+ ok( GetFocus() == child, "Focus no longer on child %p\n", child );
+ ShowWindow(child, SW_HIDE);
+ ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
+ ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
+ ShowWindow(child, SW_SHOW);
+ SetFocus(child);
+ ok( GetFocus() == child, "Focus should be on child %p\n", child );
+ SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW);
+ ok( GetFocus() == child, "Focus should still be on child %p\n", child );
+
+ ShowWindow(child, SW_HIDE);
+ SetFocus(hwnd);
+ ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
+ SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
+ ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
+ ShowWindow(child, SW_HIDE);
+ ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
+
+ DestroyWindow( child );
+}
+
+static void test_SetActiveWindow(HWND hwnd)
+{
+ HWND hwnd2;
+
+ ShowWindow(hwnd, SW_SHOW);
+ SetActiveWindow(0);
+ SetActiveWindow(hwnd);
+ ok( GetActiveWindow() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
+ SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
+ ok( GetActiveWindow() == hwnd, "Window %p no longer active\n", hwnd );
+ SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ ShowWindow(hwnd, SW_HIDE);
+ ok( GetActiveWindow() != hwnd, "Window %p is still active\n", hwnd );
+ ShowWindow(hwnd, SW_SHOW);
+
+ hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
+ ok( GetActiveWindow() == hwnd2, "Window %p is not active\n", hwnd2 );
+ DestroyWindow(hwnd2);
+ ok( GetActiveWindow() != hwnd2, "Window %p is still active\n", hwnd2 );
+
+ hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
+ ok( GetActiveWindow() == hwnd2, "Window %p is not active\n", hwnd2 );
+ SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
+ ok( GetActiveWindow() == hwnd2, "Window %p no longer active (%p)\n", hwnd2, GetActiveWindow() );
+ DestroyWindow(hwnd2);
+ ok( GetActiveWindow() != hwnd2, "Window %p is still active\n", hwnd2 );
+}
+
START_TEST(win)
{
pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
+ pGetWindowInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetWindowInfo" );
+
+ hwndMain = CreateWindowExA(0, "static", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL);
+ if (hwndMain)
+ {
+ ok(!GetParent(hwndMain), "GetParent should return 0 for message only windows\n");
+ if (pGetAncestor)
+ {
+ hwndMessage = pGetAncestor(hwndMain, GA_PARENT);
+ ok(hwndMessage != 0, "GetAncestor(GA_PARENT) should not return 0 for message only windows\n");
+ trace("hwndMessage %p\n", hwndMessage);
+ }
+ DestroyWindow(hwndMain);
+ }
+ else
+ trace("CreateWindowExA with parent HWND_MESSAGE failed\n");
if (!RegisterWindowClasses()) assert(0);
@@ -1158,6 +1687,12 @@
test_mdi();
test_icons();
+ test_SetWindowPos(hwndMain);
+ test_SetMenu(hwndMain);
+ test_SetFocus(hwndMain);
+ test_SetActiveWindow(hwndMain);
+
+ test_children_zorder(hwndMain);
UnhookWindowsHookEx(hhook);
}