RFC: MDI fix attempt

Krzysztof Foltman kfoltman at portal.onet.pl
Sun Apr 25 09:23:25 CDT 2004


This patch is supposed to fix a minor problem with the Window menu.

Before this patch, Window menu has its last part (from the last 
separator on) chopped off - it incorrectly assumes that the Window menu 
always has the separator that separates child window names from 
remaining options.

Applying this patch makes MDI Window menu behave as follows:

- if no child windows are present, no separator is added (or it is 
removed if it was present before)
- if any child windows are present (and visible), a separator is added 
after last item of the original Window menu (unless it was already there)

In other words, it's either

MenuItem1
MenuItem2
MenuItem3

or

MenuItem1
MenuItem2
MenuItem3
---------
Child1
Child2

Please check if it works for your favourite MDI apps and tell me if 
there's anything wrong with it.

Enjoy,
Krzysztof
-------------- next part --------------
? mdipatch.diff
? windows/mdi2.c
Index: windows/mdi.c
===================================================================
RCS file: /home/wine/wine/windows/mdi.c,v
retrieving revision 1.125
diff -u -r1.125 mdi.c
--- windows/mdi.c	1 Apr 2004 04:57:12 -0000	1.125
+++ windows/mdi.c	25 Apr 2004 14:17:42 -0000
@@ -126,6 +126,7 @@
     UINT      nTotalCreated;
     UINT      mdiFlags;
     UINT      sbRecalc;   /* SB_xxx flags for scrollbar fixup */
+    UINT      nWinMenuChildren;
 } MDICLIENTINFO;
 
 static HBITMAP hBmpClose   = 0;
@@ -303,7 +304,7 @@
         /* delete menu items from ci->hWindowMenu
          * and add them to hmenuWindow */
         /* Agent newsreader calls this function with  ci->hWindowMenu == NULL */
-        if( ci->hWindowMenu && ci->nActiveChildren )
+        if( ci->hWindowMenu )
         {
             UINT nActiveChildren_old = ci->nActiveChildren;
 
@@ -312,14 +313,18 @@
             MDI_RefreshMenu(ci);
 
             ci->hWindowMenu = hmenuWindow;
+	    ci->nWinMenuChildren = 0; /* completely fresh menu, no children yet */
 
             /* Add items to the new Window menu */
             ci->nActiveChildren = nActiveChildren_old;
-            AppendMenuW(hmenuWindow, MF_SEPARATOR, 0, NULL);
+            /* AppendMenuW(hmenuWindow, MF_SEPARATOR, 0, NULL); */
             MDI_RefreshMenu(ci);
         }
-        else
+        else {
+            ci->nWinMenuChildren = 0;
             ci->hWindowMenu = hmenuWindow;
+            MDI_RefreshMenu(ci);
+	}
     }
 
     if (hmenuFrame)
@@ -359,7 +364,8 @@
     UINT i, count, visible, separator_pos;
     WCHAR buf[MDI_MAXTITLELENGTH];
 
-    TRACE("children %u, window menu %p\n", ci->nActiveChildren, ci->hWindowMenu);
+    TRACE("children %u, created %u, window menu %p\n", ci->nActiveChildren, 
+        ci->nWinMenuChildren, ci->hWindowMenu);
 
     if (!ci->hWindowMenu)
         return 0;
@@ -373,25 +379,32 @@
     /* 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 = 0; i < count; i++)
-    {
-        MENUITEMINFOW mii;
+    separator_pos = -1;
 
-        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;
+    if (ci->nWinMenuChildren) {
+        count = GetMenuItemCount(ci->hWindowMenu);
+        for (i = count-1; i != (UINT)-1; 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;
+                break;
+            }
+        }
+        for (i = separator_pos + 1; i < count; i++)
+            RemoveMenu(ci->hWindowMenu, separator_pos + 1, MF_BYPOSITION);
+    } else {
+        separator_pos = -1;
     }
 
-    for (i = separator_pos + 1; i < count; i++)
-        RemoveMenu(ci->hWindowMenu, separator_pos + 1, MF_BYPOSITION);
-
     visible = 0;
+    ci->nWinMenuChildren = 0;
     for (i = 0; i < ci->nActiveChildren; i++)
     {
         UINT id = ci->idFirstChild + i;
@@ -400,16 +413,18 @@
         {
             LoadStringW(user32_module, IDS_MDI_MOREWINDOWS, buf, sizeof(buf)/sizeof(WCHAR));
             AppendMenuW(ci->hWindowMenu, MF_STRING, id, buf);
+	    ci->nWinMenuChildren++;
             break;
         }
 
         if (GetWindowLongW(ci->child[i], GWL_STYLE) & WS_VISIBLE)
         {
-            if (!visible && !separator_pos)
+            if (!visible && separator_pos == -1)
                 /* Visio expects that separator has id 0 */
                 AppendMenuW(ci->hWindowMenu, MF_SEPARATOR, 0, NULL);
 
             visible++;
+            ci->nWinMenuChildren++;
 
             SetWindowLongW(ci->child[i], GWL_ID, id);
 
@@ -426,6 +441,8 @@
         else
             TRACE("MDI child %p is not visible, skipping\n", ci->child[i]);
     }
+    if (separator_pos != -1 && ci->hWindowMenu && !ci->nWinMenuChildren)
+        RemoveMenu(ci->hWindowMenu, separator_pos, MF_BYPOSITION);
 
     return (LRESULT)ci->hFrameMenu;
 }
@@ -1047,6 +1064,7 @@
 
         ci->child = NULL;
 	ci->nActiveChildren	= 0;
+	ci->nWinMenuChildren    = 0;
 	ci->nTotalCreated	= 0;
 	ci->frameTitle		= NULL;
 	ci->mdiFlags		= 0;


More information about the wine-patches mailing list