WM_MDISETMENU handling fix

Dmitry Timoshkov dmitry at baikal.ru
Mon Oct 11 08:35:51 CDT 2004


Hello,

this can happen since WM_MDIDESTROY handler now hides a being destroyed MDI
child first. An app I'm working on does WM_MDISETMENU in the WM_MDIACTIVATE
handler of a being deactivated child, and current code blindly adds sys menu
and sys buttons to a new frame manu.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    - WM_MDISETMENU handler should update new frame menu only if an active
    and maximized MDI child is visible.
    - Add a test case for MDI child activation sequence.

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-10-11 13:21:59.000000000 +0900
+++ wine/dlls/user/tests/msg.c	2004-10-11 22:03:52.000000000 +0900
@@ -1556,7 +1556,8 @@ static LRESULT WINAPI mdi_client_hook_pr
     if (message != WM_PAINT &&
         message != WM_ERASEBKGND &&
         message != WM_NCPAINT &&
-        message != WM_GETTEXT)
+        message != WM_GETTEXT &&
+        message != WM_MDIGETACTIVE)
     {
         trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
 
@@ -1622,6 +1623,19 @@ static LRESULT WINAPI mdi_child_wnd_proc
                 wParam = winpos->flags & 0xffff;
                 break;
             }
+
+            case WM_MDIACTIVATE:
+            {
+                HWND active, client = GetParent(hwnd);
+
+                active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
+
+                if (hwnd == (HWND)lParam) /* if we are being activated */
+                    ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
+                else
+                    ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
+                break;
+            }
         }
 
         msg.message = message;
diff -u cvs/hq/wine/dlls/user/tests/win.c wine/dlls/user/tests/win.c
--- cvs/hq/wine/dlls/user/tests/win.c	2004-09-26 16:55:04.000000000 +0900
+++ wine/dlls/user/tests/win.c	2004-10-11 22:03:46.000000000 +0900
@@ -947,22 +947,27 @@ static void test_MDI_create(HWND parent,
     mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    DestroyWindow(mdi_child);
+    SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+    ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
     mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    DestroyWindow(mdi_child);
+    SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+    ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
     mdi_cs.style = 0xffffffff; /* with WS_POPUP */
     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
     {
         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
-        DestroyWindow(mdi_child);
     }
     else
+    {
         ok(mdi_child != 0, "MDI child creation failed\n");
+        SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+        ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
+    }
 
     /* test MDICREATESTRUCT A<->W mapping */
     /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
@@ -978,7 +983,11 @@ static void test_MDI_create(HWND parent,
         else
             ok(mdi_child != 0, "MDI child creation failed\n");
     }
-    DestroyWindow(mdi_child);
+    else
+    {
+        SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+        ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
+    }
 
     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
                                  0,
@@ -987,7 +996,8 @@ static void test_MDI_create(HWND parent,
                                  mdi_client, GetModuleHandle(0),
                                  (LPARAM)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    DestroyWindow(mdi_child);
+    SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+    ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
                                  0x7fffffff, /* without WS_POPUP */
@@ -996,7 +1006,8 @@ static void test_MDI_create(HWND parent,
                                  mdi_client, GetModuleHandle(0),
                                  (LPARAM)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    DestroyWindow(mdi_child);
+    SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+    ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
                                  0xffffffff, /* with WS_POPUP */
@@ -1007,10 +1018,13 @@ static void test_MDI_create(HWND parent,
     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
     {
         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
-        DestroyWindow(mdi_child);
     }
     else
+    {
         ok(mdi_child != 0, "MDI child creation failed\n");
+        SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+        ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
+    }
 
     /* test MDICREATESTRUCT A<->W mapping */
     SetLastError(0xdeadbeef);
@@ -1027,7 +1041,11 @@ static void test_MDI_create(HWND parent,
         else
             ok(mdi_child != 0, "MDI child creation failed\n");
     }
-    DestroyWindow(mdi_child);
+    else
+    {
+        SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+        ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
+    }
 
     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
                                 0,
@@ -1036,7 +1054,8 @@ static void test_MDI_create(HWND parent,
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    DestroyWindow(mdi_child);
+    SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+    ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
                                 0x7fffffff, /* without WS_POPUP */
@@ -1045,7 +1064,8 @@ static void test_MDI_create(HWND parent,
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    DestroyWindow(mdi_child);
+    SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+    ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
                                 0xffffffff, /* with WS_POPUP */
@@ -1056,10 +1076,13 @@ static void test_MDI_create(HWND parent,
     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
     {
         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
-        DestroyWindow(mdi_child);
     }
     else
+    {
         ok(mdi_child != 0, "MDI child creation failed\n");
+        SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+        ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
+    }
 
     /* test MDICREATESTRUCT A<->W mapping */
     SetLastError(0xdeadbeef);
@@ -1076,7 +1099,11 @@ static void test_MDI_create(HWND parent,
         else
             ok(mdi_child != 0, "MDI child creation failed\n");
     }
-    DestroyWindow(mdi_child);
+    else
+    {
+        SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
+        ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
+    }
 
     /* This test fails on Win9x */
     if (!isWin9x)
@@ -1282,6 +1309,18 @@ static LRESULT WINAPI mdi_child_wnd_proc
 
             return 1;
         }
+
+        case WM_MDIACTIVATE:
+        {
+            HWND active, client = GetParent(hwnd);
+            /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
+            active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
+            if (hwnd == (HWND)lparam) /* if we are being activated */
+                ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
+            else
+                ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
+            break;
+        }
     }
     return DefMDIChildProcA(hwnd, msg, wparam, lparam);
 }
diff -u cvs/hq/wine/windows/mdi.c wine/windows/mdi.c
--- cvs/hq/wine/windows/mdi.c	2004-10-11 13:22:00.000000000 +0900
+++ wine/windows/mdi.c	2004-10-11 22:12:55.000000000 +0900
@@ -300,7 +300,7 @@ static LRESULT MDISetMenu( HWND hwnd, HM
     {
         if (hmenuFrame == ci->hFrameMenu) return (LRESULT)hmenuFrame;
 
-        if( IsZoomed(ci->hwndActiveChild) && hmenuFrame != ci->hFrameMenu )
+        if (IsZoomed(ci->hwndActiveChild))
             MDI_RestoreFrameMenu( hwndFrame, ci->hwndActiveChild );
     }
 
@@ -335,7 +335,7 @@ static LRESULT MDISetMenu( HWND hwnd, HM
             HMENU oldFrameMenu = ci->hFrameMenu;
 
             ci->hFrameMenu = hmenuFrame;
-            if( IsZoomed(ci->hwndActiveChild) )
+            if (IsZoomed(ci->hwndActiveChild) && (GetWindowLongW(ci->hwndActiveChild, GWL_STYLE) & WS_VISIBLE))
                 MDI_AugmentFrameMenu( hwndFrame, ci->hwndActiveChild );
 
             return (LRESULT)oldFrameMenu;






More information about the wine-patches mailing list