Make message flow for MDI creation/activation/destruction more like in Windows

Dmitry Timoshkov dmitry at baikal.ru
Mon Sep 20 05:04:51 CDT 2004


Hello,

this patch adds another bunch of message tests for MDI children
and makes message flow for MDI creation/activation/destruction
more like in Windows. It's still not exactly the same as in Windows,
but it's close enough.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Make message flow for MDI creation/activation/destruction
    more like in Windows. Add a bunch of MDI message tests.

diff -u cvs/hq/wine/dlls/user/tests/msg.c wine/dlls/user/tests/msg.c
--- cvs/hq/wine/dlls/user/tests/msg.c	2004-09-20 17:08:26.000000000 +0900
+++ wine/dlls/user/tests/msg.c	2004-09-20 18:21:30.000000000 +0900
@@ -316,6 +316,14 @@ static const struct message WmShowChildS
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
     { 0 }
 };
+/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
+ * for a visible child window with a caption
+ */
+static const struct message WmShowChildSeq_4[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
+    { WM_CHILDACTIVATE, sent },
+    { 0 }
+};
 /* ShowWindow(SW_SHOW) for child with invisible parent */
 static const struct message WmShowChildInvisibleParentSeq[] = {
     { WM_SHOWWINDOW, sent|wparam, 1 },
@@ -1268,6 +1276,76 @@ static const struct message WmDestroyMDI
     { WM_NCDESTROY, sent|defwinproc },
     { 0 }
 };
+/* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
+static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
+    { HCBT_MINMAX, hook },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
+
+    { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
+    { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
+    { WM_SETFOCUS, sent }, /* in MDI client */
+    { HCBT_SETFOCUS, hook },
+    { WM_KILLFOCUS, sent }, /* in MDI client */
+    { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
+    { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+    { WM_SETFOCUS, sent|defwinproc },
+    { WM_MDIACTIVATE, sent|defwinproc },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
+    { WM_SIZE, sent|defwinproc },
+     /* in MDI frame */
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { 0 }
+};
+/* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
+static const struct message WmMaximizeMDIchildVisibleSeq[] = {
+    { HCBT_MINMAX, hook },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
+    { WM_SIZE, sent|defwinproc },
+     /* in MDI frame */
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { 0 }
+};
+/* ShowWindow(SW_RESTORE) for a visible MDI child window */
+static const struct message WmRestoreMDIchildVisibleSeq[] = {
+    { HCBT_MINMAX, hook },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
+    { WM_SIZE, sent|defwinproc },
+     /* in MDI frame */
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { 0 }
+};
+/* ShowWindow(SW_RESTORE) for a not visible MDI child window */
+static const struct message WmRestoreMDIchildInisibleSeq[] = {
+    { HCBT_MINMAX, hook },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
+    { WM_SIZE, sent|defwinproc },
+     /* in MDI frame */
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
+    { WM_NCCALCSIZE, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { 0 }
+};
 
 static HWND mdi_client;
 static WNDPROC old_mdi_client_proc;
@@ -1462,6 +1540,9 @@ static void test_mdi_messages(void)
     assert(mdi_frame);
     ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
+
     trace("creating MDI client window\n");
     client_cs.hWindowMenu = 0;
     client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
@@ -1473,6 +1554,7 @@ static void test_mdi_messages(void)
     assert(mdi_client);
     ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
     ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
 
     active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
@@ -1493,6 +1575,9 @@ static void test_mdi_messages(void)
     ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
     ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
+
     active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
     ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
     ok(!zoomed, "wrong zoomed state %d\n", zoomed);
@@ -1501,6 +1586,9 @@ static void test_mdi_messages(void)
     DestroyWindow(mdi_child);
     ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
     /* Win2k: MDI client still returns a just destroyed child as active
      * Win9x: MDI client returns 0
      */
@@ -1510,7 +1598,6 @@ static void test_mdi_messages(void)
        "wrong active MDI child %p\n", active_child);
     ok(!zoomed, "wrong zoomed state %d\n", zoomed);
 
-    SetFocus(0);
     flush_sequence();
 
     trace("creating invisible MDI child window\n");
@@ -1519,11 +1606,14 @@ static void test_mdi_messages(void)
                                 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
                                 mdi_client, 0, GetModuleHandleA(0), NULL);
     assert(mdi_child2);
-    ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", TRUE);
+    ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
 
     ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
     ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
     /* Win2k: MDI client still returns a just destroyed child as active
      * Win9x: MDI client returns mdi_child2
      */
@@ -1534,15 +1624,79 @@ static void test_mdi_messages(void)
     ok(!zoomed, "wrong zoomed state %d\n", zoomed);
     flush_sequence();
 
+    ShowWindow(mdi_child2, SW_MAXIMIZE);
+    ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
+
+    ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
+    ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
+
+    active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
+    ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
+    ok(zoomed, "wrong zoomed state %d\n", zoomed);
+    flush_sequence();
+
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_child2 || /* win2k */
+       GetFocus() == 0, /* win9x */
+       "wrong focus window %p\n", GetFocus());
+
+    SetFocus(0);
+    flush_sequence();
+
+    ShowWindow(mdi_child2, SW_HIDE);
+    ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
+
+    ShowWindow(mdi_child2, SW_RESTORE);
+    ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
+    flush_sequence();
+
+    ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
+    ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
+
+    active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
+    ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
+    ok(!zoomed, "wrong zoomed state %d\n", zoomed);
+    flush_sequence();
+
+    SetFocus(0);
+    flush_sequence();
+
+    ShowWindow(mdi_child2, SW_HIDE);
+    ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
+
     ShowWindow(mdi_child2, SW_SHOW);
     ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", TRUE);
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
+    ShowWindow(mdi_child2, SW_MAXIMIZE);
+    ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
+
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
+    ShowWindow(mdi_child2, SW_RESTORE);
+    ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
+
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
+    SetFocus(0);
+    flush_sequence();
+
     ShowWindow(mdi_child2, SW_HIDE);
     ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
     DestroyWindow(mdi_child2);
     ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", TRUE);
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
     /* test for maximized MDI children */
     trace("creating maximized visible MDI child window 1\n");
     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
@@ -1553,6 +1707,11 @@ static void test_mdi_messages(void)
     ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
     ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_child || /* win2k */
+       GetFocus() == 0, /* win9x */
+       "wrong focus window %p\n", GetFocus());
+
     active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
     ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
     ok(zoomed, "wrong zoomed state %d\n", zoomed);
@@ -1568,16 +1727,22 @@ static void test_mdi_messages(void)
     ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
     ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
+
     active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
     ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
     ok(zoomed, "wrong zoomed state %d\n", zoomed);
     flush_sequence();
 
+    trace("destroying maximized visible MDI child window 2\n");
     DestroyWindow(mdi_child2);
     ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
 
     ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
-    ok(GetFocus() == 0, "GetFocus() = %p\n", GetFocus());
+
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
 
     /* Win2k: MDI client still returns a just destroyed child as active
      * Win9x: MDI client returns 0
@@ -1592,6 +1757,9 @@ static void test_mdi_messages(void)
     ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
     flush_sequence();
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
+
     trace("re-creating maximized visible MDI child window 2\n");
     mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
                                 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
@@ -1602,6 +1770,9 @@ static void test_mdi_messages(void)
     ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
     ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
+
     active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
     ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
     ok(zoomed, "wrong zoomed state %d\n", zoomed);
@@ -1612,9 +1783,8 @@ static void test_mdi_messages(void)
     ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
 
     ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
-todo_wine {
-    ok(GetFocus() == mdi_child, "GetFocus() = %p\n", GetFocus());
-}
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
 
     active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
     ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
@@ -1624,6 +1794,9 @@ todo_wine {
     DestroyWindow(mdi_child);
     ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
 
+    ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
+    ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
+
     /* Win2k: MDI client still returns a just destroyed child as active
      * Win9x: MDI client returns 0
      */
@@ -1884,7 +2057,7 @@ static void test_messages(void)
     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", FALSE);
+    ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", TRUE);
     ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
 
     /* test WM_SETREDRAW on a visible top level window */
@@ -1909,7 +2082,9 @@ static void test_messages(void)
     DestroyWindow(hchild);
     flush_sequence();
 
-    hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
+    /* visible child window with a caption */
+    hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
+                             WS_CHILD | WS_VISIBLE | WS_CAPTION,
                              0, 0, 10, 10, hparent, 0, 0, NULL);
     ok (hchild != 0, "Failed to create child window\n");
     ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
@@ -1917,6 +2092,9 @@ static void test_messages(void)
     trace("testing scroll APIs on a visible child window %p\n", hchild);
     test_scroll_messages(hchild);
 
+    SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
+    ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
+
     DestroyWindow(hchild);
     flush_sequence();
 
diff -u cvs/hq/wine/windows/mdi.c wine/windows/mdi.c
--- cvs/hq/wine/windows/mdi.c	2004-09-20 17:08:26.000000000 +0900
+++ wine/windows/mdi.c	2004-09-20 18:40:38.000000000 +0900
@@ -480,23 +480,33 @@ static void MDI_ChildGetMinMaxInfo( HWND
  * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
  *       being activated
  */
-static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
-                                   BOOL bNextWindow )
+static void MDI_SwitchActiveChild( MDICLIENTINFO *ci, HWND hwndTo )
 {
-    HWND	   hwndTo    = 0;
-    HWND	   hwndPrev  = 0;
-    MDICLIENTINFO *ci = get_client_info( clientHwnd );
+    HWND hwndPrev;
 
-    hwndTo = MDI_GetWindow(ci, childHwnd, bNextWindow, 0);
     hwndPrev = ci->hwndActiveChild;
 
-    TRACE("from %p, to %p\n",childHwnd,hwndTo);
+    TRACE("from %p, to %p\n", hwndPrev, hwndTo);
 
-    if ( !hwndTo )
-        MDI_ChildActivate( clientHwnd, 0 );
-    else if ( hwndTo != hwndPrev )
-	SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
-                      SWP_NOMOVE | SWP_NOSIZE );
+    if ( hwndTo != hwndPrev )
+    {
+        BOOL was_zoomed = IsZoomed(hwndPrev);
+
+        if (was_zoomed)
+        {
+            /* restore old MDI child */
+            SendMessageW( hwndPrev, WM_SETREDRAW, FALSE, 0 );
+            ShowWindow( hwndPrev, SW_RESTORE );
+            SendMessageW( hwndPrev, WM_SETREDRAW, TRUE, 0 );
+
+            /* activate new MDI child */
+            SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
+            /* maximize new MDI child */
+            ShowWindow( hwndTo, SW_MAXIMIZE );
+        }
+        /* activate new MDI child */
+        SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
+    }
 }
 
 
@@ -512,8 +522,8 @@ static LRESULT MDIDestroyChild( HWND par
 
     if( child == ci->hwndActiveChild )
     {
-        MDI_SwitchActiveChild(parent, child, TRUE);
-        ShowWindow(child, SW_HIDE);
+        HWND next = MDI_GetWindow(ci, child, TRUE, 0);
+        MDI_SwitchActiveChild(ci, next);
     }
 
     for (i = 0; i < ci->nActiveChildren; i++)
@@ -546,7 +556,7 @@ static LRESULT MDIDestroyChild( HWND par
 /**********************************************************************
  *					MDI_ChildActivate
  *
- * Note: hWndChild is NULL when last child is being destroyed
+ * Called in response to WM_CHILDACTIVATE
  */
 static LONG MDI_ChildActivate( HWND client, HWND child )
 {
@@ -554,18 +564,16 @@ static LONG MDI_ChildActivate( HWND clie
     HWND prevActiveWnd, frame;
     BOOL isActiveFrameWnd;
 
-    if (child && (!IsWindowEnabled( child ))) return 0;
-
     clientInfo = get_client_info( client );
 
+    if (clientInfo->hwndActiveChild == child) return 0;
+
     TRACE("%p\n", child);
 
     frame = GetParent(client);
     isActiveFrameWnd = (GetActiveWindow() == frame);
     prevActiveWnd = clientInfo->hwndActiveChild;
 
-    if (prevActiveWnd == child) return 0;
-
     /* deactivate prev. active child */
     if(prevActiveWnd)
     {
@@ -575,39 +583,13 @@ static LONG MDI_ChildActivate( HWND clie
 
     clientInfo->hwndActiveChild = child;
 
-    /* set appearance */
-    if (IsZoomed(prevActiveWnd) && prevActiveWnd != child)
-    {
-        if( child )
-        {
-            INT cmd = SW_SHOWNORMAL;
-            HMENU hSysMenu = GetSystemMenu(child, FALSE);
-            UINT state = 0;
-            if (hSysMenu)
-                state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
-            if (state != 0xFFFFFFFF && !(state & (MF_DISABLED | MF_GRAYED)))
-                cmd = SW_SHOWMAXIMIZED;
-
-            ShowWindow( child, cmd );
-        }
-        else
-            MDI_RestoreFrameMenu(frame, child);
-    }
-
-    MDI_UpdateFrameText(frame, client, NULL);
-
-    /* check if we have any children left */
-    if( !child )
-    {
-	if( isActiveFrameWnd )
-	    SetFocus( client );
-        return 0;
-    }
-
     MDI_RefreshMenu(clientInfo);
 
     if( isActiveFrameWnd )
+    {
         SendMessageW( child, WM_NCACTIVATE, TRUE, 0L);
+        SetFocus(child);
+    }
 
     SendMessageW( child, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child );
     return TRUE;
@@ -1060,8 +1042,7 @@ static LRESULT MDIClientWndProc_common( 
 
       case WM_MDIACTIVATE:
       {
-        if( ci->hwndActiveChild != (HWND)wParam )
-	    SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
+        MDI_SwitchActiveChild( ci, (HWND)wParam );
         return 0;
       }
 
@@ -1111,8 +1092,11 @@ static LRESULT MDIClientWndProc_common( 
         return 0;
 
       case WM_MDINEXT: /* lParam != 0 means previous window */
-	MDI_SwitchActiveChild( hwnd, WIN_GetFullHandle( (HWND)wParam ), !lParam );
+      {
+        HWND next = MDI_GetWindow( ci, WIN_GetFullHandle( (HWND)wParam ), !lParam, 0 );
+        MDI_SwitchActiveChild( ci, next );
 	break;
+      }
 
       case WM_MDIRESTORE:
         SendMessageW( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
@@ -1399,6 +1383,7 @@ LRESULT WINAPI DefMDIChildProcA( HWND hw
     case WM_SIZE:
     case WM_NEXTMENU:
     case WM_SYSCHAR:
+    case WM_DESTROY:
         return DefMDIChildProcW( hwnd, message, wParam, lParam );
     }
     return DefWindowProcA(hwnd, message, wParam, lParam);
@@ -1472,29 +1457,20 @@ LRESULT WINAPI DefMDIChildProcW( HWND hw
         break;
 
     case WM_SIZE:
-        if (wParam == SIZE_MAXIMIZED && !IsWindowVisible(hwnd))
-            wParam = SIZE_RESTORED;
-
-        if( hwnd == ci->hwndActiveChild && wParam != SIZE_MAXIMIZED )
-        {
-            MDI_RestoreFrameMenu( GetParent(client), hwnd );
-            MDI_UpdateFrameText( GetParent(client), client, NULL );
-        }
-
-        if( wParam == SIZE_MAXIMIZED )
+        if( hwnd == ci->hwndActiveChild )
         {
-            TRACE("maximizing child %p\n", hwnd );
+            if( wParam == SIZE_MAXIMIZED )
+            {
+                TRACE("maximizing child %p\n", hwnd );
 
-            MDI_AugmentFrameMenu( GetParent(client), hwnd );
-            MDI_UpdateFrameText( GetParent(client), client, NULL );
+                MDI_AugmentFrameMenu( GetParent(client), hwnd );
+            }
+            else
+                MDI_RestoreFrameMenu( GetParent(client), hwnd );
         }
 
-        if( wParam == SIZE_MINIMIZED )
-        {
-            HWND switchTo = MDI_GetWindow(ci, hwnd, TRUE, WS_MINIMIZE);
-
-            if (switchTo) SendMessageW( switchTo, WM_CHILDACTIVATE, 0, 0);
-        }
+        MDI_UpdateFrameText( GetParent(client), client, NULL );
+        MDI_RefreshMenu(ci);
         MDI_PostUpdate(client, ci, SB_BOTH+1);
         break;
 
@@ -1524,6 +1500,11 @@ LRESULT WINAPI DefMDIChildProcW( HWND hw
             return 0;
         }
         break;
+
+    case WM_DESTROY:
+        /* Remove itself from the Window menu */
+        MDI_RefreshMenu(ci);
+        break;
     }
     return DefWindowProcW(hwnd, message, wParam, lParam);
 }
diff -u cvs/hq/wine/windows/win.c wine/windows/win.c
--- cvs/hq/wine/windows/win.c	2004-09-20 17:09:15.000000000 +0900
+++ wine/windows/win.c	2004-09-20 18:21:30.000000000 +0900
@@ -1024,6 +1024,18 @@ static HWND WIN_CreateWindowEx( CREATEST
         }
 
         top_child = GetWindow(cs->hwndParent, GW_CHILD);
+
+        if (top_child)
+        {
+            /* Restore current maximized child */
+            if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
+            {
+                TRACE("Restoring current maximized child %p\n", top_child);
+                SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
+                ShowWindow(top_child, SW_RESTORE);
+                SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
+            }
+        }
     }
 
     /* Find the parent window */
@@ -1167,24 +1179,22 @@ static HWND WIN_CreateWindowEx( CREATEST
     send_parent_notify( hwnd, WM_CREATE );
     if (!IsWindow( hwnd )) return 0;
 
-    if (cs->dwExStyle & WS_EX_MDICHILD)
+    if (cs->style & WS_VISIBLE)
     {
-        if (top_child)
+        if (cs->style & WS_MAXIMIZE)
+            sw = SW_SHOWMAXIMIZED;
+        else if (cs->style & WS_MINIMIZE)
+            sw = SW_SHOWMINIMIZED;
+
+        ShowWindow( hwnd, sw );
+        if (cs->dwExStyle & WS_EX_MDICHILD)
         {
-            /* Restore current maximized child */
-            if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
-            {
-                TRACE("Restoring current maximized child %p\n", top_child);
-                ShowWindow(top_child, SW_SHOWNOACTIVATE);
-            }
+            SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
+            /* ShowWindow won't activate child windows */
+            SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
         }
-
-        SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
     }
 
-    if (cs->style & WS_VISIBLE)
-        ShowWindow( hwnd, sw );
-
     /* Call WH_SHELL hook */
 
     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
@@ -1432,9 +1442,6 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
 
     TRACE("(%p)\n", hwnd);
 
-    if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
-        SendMessageW(GetAncestor(hwnd, GA_PARENT), WM_MDIREFRESHMENU, 0, 0);
-
       /* Call hooks */
 
     if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;






More information about the wine-patches mailing list