Make the MDI Window menu refreshing Windows compatible

Dmitry Timoshkov dmitry at baikal.ru
Fri Jan 30 10:08:09 CST 2004


Hello,

Windows simply finds the last separator in the Window menu and
uses it as a border in the process of Window menu refreshing.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Make the MDI Window menu refreshing Windows compatible.
    Simplify MDI child visibility check.

--- cvs/hq/wine/windows/mdi.c	2004-01-27 15:31:30.000000000 +0800
+++ wine/windows/mdi.c	2004-01-30 23:43:21.000000000 +0800
@@ -121,7 +121,6 @@ typedef struct
     HWND      *child; /* array of tracked children */
     HMENU     hFrameMenu;
     HMENU     hWindowMenu;
-    UINT      add_pos; /* original number of items in the window menu */
     UINT      idFirstChild;
     LPWSTR    frameTitle;
     UINT      nTotalCreated;
@@ -312,7 +311,6 @@ static LRESULT MDISetMenu( HWND hwnd, HM
             ci->nActiveChildren = 0;
             MDI_RefreshMenu(ci);
 
-            ci->add_pos = GetMenuItemCount(hmenuWindow);
             ci->hWindowMenu = hmenuWindow;
 
             /* Add items to the new Window menu */
@@ -320,10 +318,7 @@ static LRESULT MDISetMenu( HWND hwnd, HM
             MDI_RefreshMenu(ci);
         }
         else
-        {
             ci->hWindowMenu = hmenuWindow;
-            ci->add_pos = GetMenuItemCount(hmenuWindow);
-        }
     }
 
     if (hmenuFrame)
@@ -360,7 +355,7 @@ static LRESULT MDISetMenu( HWND hwnd, HM
  */
 static LRESULT MDI_RefreshMenu(MDICLIENTINFO *ci)
 {
-    UINT i, count, visible;
+    UINT i, count, visible, separator_pos;
     WCHAR buf[MDI_MAXTITLELENGTH];
 
     TRACE("children %u, window menu %p\n", ci->nActiveChildren, ci->hWindowMenu);
@@ -374,9 +369,26 @@ static LRESULT MDI_RefreshMenu(MDICLIENT
         return 0;
     }
 
+    /* Windows finds the last separator in the menu, removes all existing
+     * menu items after it, and then adds visible MDI children.
+     */
+    separator_pos = 0;
     count = GetMenuItemCount(ci->hWindowMenu);
-    for (i = ci->add_pos; i < count; i++)
-        RemoveMenu(ci->hWindowMenu, ci->add_pos, MF_BYPOSITION);
+    for (i = 0; i < count; i++)
+    {
+        MENUITEMINFOW mii;
+
+        memset(&mii, 0, sizeof(mii));
+        mii.cbSize = sizeof(mii);
+        mii.fMask  = MIIM_TYPE;
+        GetMenuItemInfoW(ci->hWindowMenu, i, TRUE, &mii);
+
+        if (mii.fType & MFT_SEPARATOR)
+            separator_pos = i;
+    }
+
+    for (i = separator_pos + 1; i < count; i++)
+        RemoveMenu(ci->hWindowMenu, separator_pos + 1, MF_BYPOSITION);
 
     visible = 0;
     for (i = 0; i < ci->nActiveChildren; i++)
@@ -390,9 +402,9 @@ static LRESULT MDI_RefreshMenu(MDICLIENT
             break;
         }
 
-        if (IsWindowVisible(ci->child[i]))
+        if (GetWindowLongW(ci->child[i], GWL_STYLE) & WS_VISIBLE)
         {
-            if (!visible)
+            if (!visible && !separator_pos)
                 /* Visio expects that separator has id 0 */
                 AppendMenuW(ci->hWindowMenu, MF_SEPARATOR, 0, NULL);
 
@@ -404,12 +416,14 @@ static LRESULT MDI_RefreshMenu(MDICLIENT
             buf[1] = '0' + visible;
             buf[2] = ' ';
             InternalGetWindowText(ci->child[i], buf + 3, sizeof(buf)/sizeof(WCHAR) - 3);
-            TRACE("Adding %u %s\n", id, debugstr_w(buf));
+            TRACE("Adding %p, id %u %s\n", ci->child[i], id, debugstr_w(buf));
             AppendMenuW(ci->hWindowMenu, MF_STRING, id, buf);
 
             if (ci->child[i] == ci->hwndActiveChild)
                 CheckMenuItem(ci->hWindowMenu, id, MF_CHECKED);
         }
+        else
+            TRACE("MDI child %p is not visible, skipping\n", ci->child[i]);
     }
 
     return (LRESULT)ci->hFrameMenu;
@@ -557,21 +571,10 @@ static LONG MDI_ChildActivate( HWND clie
     /* deactivate prev. active child */
     if(prevActiveWnd)
     {
-        SetWindowLongA( prevActiveWnd, GWL_STYLE,
-                        GetWindowLongA( prevActiveWnd, GWL_STYLE ) | WS_SYSMENU );
-	SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
-        SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child);
-        /* uncheck menu item */
-       	if( clientInfo->hWindowMenu )
-        {
-            UINT prevID = GetWindowLongA( prevActiveWnd, GWL_ID );
-
-            if (prevID - clientInfo->idFirstChild < MDI_MOREWINDOWSLIMIT)
-                CheckMenuItem( clientInfo->hWindowMenu, prevID, 0);
-            else
-       	        CheckMenuItem( clientInfo->hWindowMenu,
-                               clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1, 0);
-        }
+        SetWindowLongW( prevActiveWnd, GWL_STYLE,
+                        GetWindowLongW( prevActiveWnd, GWL_STYLE ) | WS_SYSMENU );
+        SendMessageW( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
+        SendMessageW( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child);
     }
 
     /* set appearance */
@@ -599,8 +602,6 @@ static LONG MDI_ChildActivate( HWND clie
 
     clientInfo->hwndActiveChild = child;
 
-    MDI_RefreshMenu(clientInfo);
-
     /* check if we have any children left */
     if( !child )
     {
@@ -609,6 +610,8 @@ static LONG MDI_ChildActivate( HWND clie
         return 0;
     }
 
+    MDI_RefreshMenu(clientInfo);
+
     /* bring active child to the top */
     SetWindowPos( child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
 
@@ -1064,7 +1067,6 @@ static LRESULT MDIClientWndProc_common( 
 	ci->frameTitle		= NULL;
 	ci->mdiFlags		= 0;
         ci->hFrameMenu = GetMenu(cs->hwndParent);
-        ci->add_pos = GetMenuItemCount(ci->hWindowMenu);
 
 	if (!hBmpClose) hBmpClose = CreateMDIMenuBitmap();
 






More information about the wine-patches mailing list