menu: drawing fixes split #1

Rein Klazes wijn at wanadoo.nl
Sun Feb 19 07:39:20 CST 2006


Hi,

OK, I start breaking up the drawing fixes in smaller parts. The tests
will have to come last. 

Here is one that does not change anything really, but generates a large
part of the diff because of the reduction of nesting depth in
if-statements.

Changelog;

dlls/user	: menu.c
Move drawing of pop menu arrows to a subroutine reduces nesting level of
some large if statements in the drawing code. Some updates to the
comments.  

Rein.
-------------- next part --------------
--- wine/dlls/user/menu.c	2006-02-18 12:50:38.000000000 +0100
+++ mywine/dlls/user/menu.c	2006-02-19 13:42:46.000000000 +0100
@@ -27,6 +27,11 @@
  * have been selected, i.e. their popup menu is currently displayed.
  * This is probably not the meaning this style has in MS-Windows.
  *
+ * Note 2: where there is a difference, these menu API's are according
+ * the behavior of Windows 2k and Windows XP. Known differences with
+ * Windows 9x/ME are documented in the comments, in case an application
+ * is found to depend on the old behavior.
+ * 
  * TODO:
  *    implements styles :
  *        - MNS_AUTODISMISS
@@ -104,7 +109,7 @@ typedef struct {
     DWORD	dwContextHelpID;
     DWORD	dwMenuData;	/* application defined value */
     HMENU       hSysMenuOwner;  /* Handle to the dummy sys menu holder */
-    SIZE        maxBmpSize;     /* Maximum size of the bitmap items in MIIM_BITMAP state */
+    SIZE        maxBmpSize;     /* Maximum size of the bitmap items */
 } POPUPMENU, *LPPOPUPMENU;
 
 /* internal flags for menu tracking */
@@ -155,6 +160,7 @@ typedef struct
 #define MENU_ITEM_TYPE(flags) \
   ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
 
+/* macro to test that flags do not indicate bitmap, ownerdraw or separator */
 #define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
 #define IS_MAGIC_BITMAP(id)     ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
 
@@ -1258,6 +1264,25 @@ MENU_DrawScrollArrows(LPPOPUPMENU lppop,
 
 
 /***********************************************************************
+ *           draw_popup_arrow
+ *
+ * Draws the popup-menu arrow.
+ */
+static void draw_popup_arrow( HDC hdc, RECT rect, UINT arrow_bitmap_width,
+        UINT arrow_bitmap_height)
+{
+    HDC hdcMem = CreateCompatibleDC( hdc );
+    HBITMAP hOrigBitmap;
+
+    hOrigBitmap = SelectObject( hdcMem, get_arrow_bitmap() );
+    BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
+            (rect.top + rect.bottom - arrow_bitmap_height) / 2,
+            arrow_bitmap_width, arrow_bitmap_height,
+            hdcMem, 0, 0, SRCCOPY );
+    SelectObject( hdcMem, hOrigBitmap );
+    DeleteDC( hdcMem );
+}
+/***********************************************************************
  *           MENU_DrawMenuItem
  *
  * Draw a single menu item.
@@ -1268,9 +1293,17 @@ static void MENU_DrawMenuItem( HWND hwnd
     RECT rect;
     BOOL flat_menu = FALSE;
     int bkgnd;
+    UINT arrow_bitmap_width = 0, arrow_bitmap_height = 0;
 
     debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
 
+    if (!menuBar) {
+        BITMAP bmp;
+        GetObjectW( get_arrow_bitmap(), sizeof(bmp), &bmp );
+        arrow_bitmap_width = bmp.bmWidth;
+        arrow_bitmap_height = bmp.bmHeight;
+    }
+
     if (lpitem->fType & MF_SYSMENU)
     {
 	if( !IsIconic(hwnd) )
@@ -1336,7 +1369,11 @@ static void MENU_DrawMenuItem( HWND hwnd
 	      dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
 	      dis.hDC, wine_dbgstr_rect( &dis.rcItem));
         SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
-        /* Fall through to draw popup-menu arrow */
+        /* Draw the popup-menu arrow */
+        if (lpitem->fType & MF_POPUP)
+            draw_popup_arrow( hdc, rect, arrow_bitmap_width,
+                    arrow_bitmap_height);
+        return;
     }
 
     TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->rect));
@@ -1346,70 +1383,66 @@ static void MENU_DrawMenuItem( HWND hwnd
     rect = lpitem->rect;
     MENU_AdjustMenuItemRect(MENU_GetMenu(hmenu), &rect);
 
-    if (!(lpitem->fType & MF_OWNERDRAW))
+    if (lpitem->fState & MF_HILITE)
     {
-	if (lpitem->fState & MF_HILITE)
-	{
-	    if (flat_menu)
-	    {
-		InflateRect (&rect, -1, -1);
-		FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT));
-		InflateRect (&rect, 1, 1);
-		FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
-	    }
-	    else
-	    {
-		if(menuBar)
-		    DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
-		else
-		    FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
-	    }
-	}
+        if (flat_menu)
+        {
+            InflateRect (&rect, -1, -1);
+            FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT));
+            InflateRect (&rect, 1, 1);
+            FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+        }
         else
-	    FillRect( hdc, &rect, GetSysColorBrush(bkgnd) );
+        {
+            if(menuBar)
+                DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
+            else
+                FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+        }
     }
+    else
+        FillRect( hdc, &rect, GetSysColorBrush(bkgnd) );
 
     SetBkMode( hdc, TRANSPARENT );
 
-    if (!(lpitem->fType & MF_OWNERDRAW))
+    /* vertical separator */
+    if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
     {
-	HPEN oldPen;
-    
-        /* vertical separator */
-        if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
+        HPEN oldPen;
+        RECT rc = rect;
+
+        rc.top = 3;
+        rc.bottom = height - 3;
+        if (flat_menu)
         {
-	    RECT rc = rect;
-	    rc.top = 3;
-	    rc.bottom = height - 3;
-	    if (flat_menu)
-	    {
-		oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
-		MoveToEx( hdc, rc.left, rc.top, NULL );
-		LineTo( hdc, rc.left, rc.bottom );
-		SelectObject( hdc, oldPen );
-	    }
-	    else
-		DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+            oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
+            MoveToEx( hdc, rc.left, rc.top, NULL );
+            LineTo( hdc, rc.left, rc.bottom );
+            SelectObject( hdc, oldPen );
         }
+        else
+            DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+    }
 
-        /* horizontal separator */
-        if (lpitem->fType & MF_SEPARATOR)
+    /* horizontal separator */
+    if (lpitem->fType & MF_SEPARATOR)
+    {
+        HPEN oldPen;
+        RECT rc = rect;
+
+        rc.left++;
+        rc.right--;
+        rc.top += SEPARATOR_HEIGHT / 2;
+        if (flat_menu)
         {
-	    RECT rc = rect;
-	    rc.left++;
-	    rc.right--;
-	    rc.top += SEPARATOR_HEIGHT / 2;
-	    if (flat_menu)
-	    {
-		oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
-		MoveToEx( hdc, rc.left, rc.top, NULL );
-		LineTo( hdc, rc.right, rc.top );
-		SelectObject( hdc, oldPen );
-	    }
-	    else
-		DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
-	    return;
+            oldPen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_BTNSHADOW) );
+            MoveToEx( hdc, rc.left, rc.top, NULL );
+            LineTo( hdc, rc.right, rc.top );
+            SelectObject( hdc, oldPen );
         }
+        else
+            DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
+        return;
     }
 
 	/* helper lines for debugging */
@@ -1423,115 +1456,91 @@ static void MENU_DrawMenuItem( HWND hwnd
     {
         HBITMAP bm;
         INT y = rect.top + rect.bottom;
+        RECT rc = rect;
         UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
         UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
-        UINT arrow_bitmap_width, arrow_bitmap_height;
-        BITMAP bmp;
-
-        GetObjectW( get_arrow_bitmap(), sizeof(bmp), &bmp );
-        arrow_bitmap_width = bmp.bmWidth;
-        arrow_bitmap_height = bmp.bmHeight;
 
-        if (!(lpitem->fType & MF_OWNERDRAW))
+        if (lpitem->hbmpItem)
         {
-            RECT rc;
-            rc = rect;
-            if (lpitem->hbmpItem)
-            {
-                POPUPMENU *menu = MENU_GetMenu(hmenu);
-                if (menu->dwStyle & MNS_CHECKORBMP)
-                    rc.left += menu->maxBmpSize.cx - check_bitmap_width;
-                else
-                    rc.left += menu->maxBmpSize.cx;
-            }
-            /* Draw the check mark
-             *
-             * FIXME:
-             * Custom checkmark bitmaps are monochrome but not always 1bpp.
-             */
-            bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit;
-            if (bm)  /* we have a custom bitmap */
-            {
-                HDC hdcMem = CreateCompatibleDC( hdc );
-                SelectObject( hdcMem, bm );
-                BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
-                        check_bitmap_width, check_bitmap_height,
-                        hdcMem, 0, 0, SRCCOPY );
-                DeleteDC( hdcMem );
-            }
-            else if (lpitem->fState & MF_CHECKED)  /* standard bitmaps */
-            {
-                RECT r;
-                HBITMAP bm = CreateBitmap( check_bitmap_width, check_bitmap_height, 1, 1, NULL );
-                HDC hdcMem = CreateCompatibleDC( hdc );
-                SelectObject( hdcMem, bm );
-                SetRect( &r, 0, 0, check_bitmap_width, check_bitmap_height );
-                DrawFrameControl( hdcMem, &r, DFC_MENU,
-                                  (lpitem->fType & MFT_RADIOCHECK) ?
-                                  DFCS_MENUBULLET : DFCS_MENUCHECK );
-                BitBlt( hdc, rc.left, (y - r.bottom) / 2, r.right, r.bottom,
-                        hdcMem, 0, 0, SRCCOPY );
-                DeleteDC( hdcMem );
-                DeleteObject( bm );
-            }
-            if (lpitem->hbmpItem)
-            {
-                HBITMAP hbm = lpitem->hbmpItem;
+            POPUPMENU *menu = MENU_GetMenu(hmenu);
+            if (menu->dwStyle & MNS_CHECKORBMP)
+                rc.left += menu->maxBmpSize.cx - check_bitmap_width;
+            else
+                rc.left += menu->maxBmpSize.cx;
+        }
+        /* Draw the check mark
+         *
+         * FIXME:
+         * Custom checkmark bitmaps are monochrome but not always 1bpp.
+         */
+        bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit;
+        if (bm)  /* we have a custom bitmap */
+        {
+            HDC hdcMem = CreateCompatibleDC( hdc );
+            SelectObject( hdcMem, bm );
+            BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
+                    check_bitmap_width, check_bitmap_height,
+                    hdcMem, 0, 0, SRCCOPY );
+            DeleteDC( hdcMem );
+        }
+        else if (lpitem->fState & MF_CHECKED)  /* standard bitmaps */
+        {
+            RECT r;
+            HBITMAP bm = CreateBitmap( check_bitmap_width, check_bitmap_height, 1, 1, NULL );
+            HDC hdcMem = CreateCompatibleDC( hdc );
+            SelectObject( hdcMem, bm );
+            SetRect( &r, 0, 0, check_bitmap_width, check_bitmap_height );
+            DrawFrameControl( hdcMem, &r, DFC_MENU,
+                              (lpitem->fType & MFT_RADIOCHECK) ?
+                              DFCS_MENUBULLET : DFCS_MENUCHECK );
+            BitBlt( hdc, rc.left, (y - r.bottom) / 2, r.right, r.bottom,
+                    hdcMem, 0, 0, SRCCOPY );
+            DeleteDC( hdcMem );
+            DeleteObject( bm );
+        }
+        if (lpitem->hbmpItem)
+        {
+            HBITMAP hbm = lpitem->hbmpItem;
 
-                if (hbm == HBMMENU_CALLBACK)
-                {
-                    DRAWITEMSTRUCT drawItem;
-                    POINT origorg;
-                    drawItem.CtlType = ODT_MENU;
-                    drawItem.CtlID = 0;
-                    drawItem.itemID = lpitem->wID;
-                    drawItem.itemAction = odaction;
-                    drawItem.itemState = (lpitem->fState & MF_CHECKED)?ODS_CHECKED:0;
-                    drawItem.itemState |= (lpitem->fState & MF_DEFAULT)?ODS_DEFAULT:0;
-                    drawItem.itemState |= (lpitem->fState & MF_DISABLED)?ODS_DISABLED:0;
-                    drawItem.itemState |= (lpitem->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
-                    drawItem.itemState |= (lpitem->fState & MF_HILITE)?ODS_SELECTED:0;
-                    drawItem.hwndItem = (HWND)hmenu;
-                    drawItem.hDC = hdc;
-                    drawItem.rcItem = lpitem->rect;
-                    drawItem.itemData = lpitem->dwItemData;
-                    /* some applications make this assumption on the DC's origin */
-                    SetViewportOrgEx( hdc, lpitem->rect.left, lpitem->rect.top, &origorg);
-                    OffsetRect( &drawItem.rcItem, - lpitem->rect.left, - lpitem->rect.top);
-                    SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
-                    SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
+            if (hbm == HBMMENU_CALLBACK)
+            {
+                DRAWITEMSTRUCT drawItem;
+                POINT origorg;
+                drawItem.CtlType = ODT_MENU;
+                drawItem.CtlID = 0;
+                drawItem.itemID = lpitem->wID;
+                drawItem.itemAction = odaction;
+                drawItem.itemState = (lpitem->fState & MF_CHECKED)?ODS_CHECKED:0;
+                drawItem.itemState |= (lpitem->fState & MF_DEFAULT)?ODS_DEFAULT:0;
+                drawItem.itemState |= (lpitem->fState & MF_DISABLED)?ODS_DISABLED:0;
+                drawItem.itemState |= (lpitem->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
+                drawItem.itemState |= (lpitem->fState & MF_HILITE)?ODS_SELECTED:0;
+                drawItem.hwndItem = (HWND)hmenu;
+                drawItem.hDC = hdc;
+                drawItem.rcItem = lpitem->rect;
+                drawItem.itemData = lpitem->dwItemData;
+                /* some applications make this assumption on the DC's origin */
+                SetViewportOrgEx( hdc, lpitem->rect.left, lpitem->rect.top, &origorg);
+                OffsetRect( &drawItem.rcItem, - lpitem->rect.left, - lpitem->rect.top);
+                SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
+                SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
 
-                } else {
-                    MENU_DrawBitmapItem(hdc, lpitem, &rect, FALSE);
-                }
+            } else {
+                MENU_DrawBitmapItem(hdc, lpitem, &rect, FALSE);
             }
         }
-
-	  /* Draw the popup-menu arrow */
-	if (lpitem->fType & MF_POPUP)
-	{
-	    HDC hdcMem = CreateCompatibleDC( hdc );
-	    HBITMAP hOrigBitmap;
-
-	    hOrigBitmap = SelectObject( hdcMem, get_arrow_bitmap() );
-	    BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
-		      (y - arrow_bitmap_height) / 2,
-		      arrow_bitmap_width, arrow_bitmap_height,
-		      hdcMem, 0, 0, SRCCOPY );
-            SelectObject( hdcMem, hOrigBitmap );
-	    DeleteDC( hdcMem );
-	}
+	/* Draw the popup-menu arrow */
+        if (lpitem->fType & MF_POPUP)
+            draw_popup_arrow( hdc, rect, arrow_bitmap_width,
+                    arrow_bitmap_height);
 
 	rect.left += check_bitmap_width;
 	rect.right -= arrow_bitmap_width;
     }
-    else if( lpitem->hbmpItem && !(lpitem->fType & MF_OWNERDRAW))
+    else if( lpitem->hbmpItem)
     {   /* Draw the bitmap */
 	MENU_DrawBitmapItem( hdc, lpitem, &rect, menuBar);
     }
-    /* Done for owner-drawn */
-    if (lpitem->fType & MF_OWNERDRAW)
-        return;
     /* process text if present */
     if (lpitem->text)
     {
@@ -4279,16 +4288,19 @@ static BOOL GetMenuItemInfo_common ( HME
     
     if( lpmii->fMask & MIIM_TYPE) {
         if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
+            WARN("invalid combination of fMask bits used\n");
+            /* this does not happen on Win9x/ME */
             SetLastError( ERROR_INVALID_PARAMETER);
             return FALSE;
         }
 	lpmii->fType = menu->fType & ~MF_POPUP;
         if( menu->hbmpItem) lpmii->fType |= MFT_BITMAP;
-	lpmii->hbmpItem = menu->hbmpItem;
+	lpmii->hbmpItem = menu->hbmpItem; /* not on Win9x/ME */
         if( lpmii->fType & MFT_BITMAP) {
 	    lpmii->dwTypeData = (LPWSTR) menu->hbmpItem;
 	    lpmii->cch = 0;
         } else if( lpmii->fType & (MFT_OWNERDRAW | MFT_SEPARATOR)) {
+            /* this does not happen on Win9x/ME */
 	    lpmii->dwTypeData = 0;
 	    lpmii->cch = 0;
         }
@@ -4327,8 +4339,11 @@ static BOOL GetMenuItemInfo_common ( HME
                     lpmii->cch--;
                 else
                     lpmii->cch = len;
-            else /* return length of string */
+            else {
+                /* return length of string */
+                /* not on Win9x/ME if fType & MFT_BITMAP */
                 lpmii->cch = len;
+            }
         }
     }
 
@@ -4346,8 +4361,11 @@ static BOOL GetMenuItemInfo_common ( HME
 
     if (lpmii->fMask & MIIM_SUBMENU)
 	lpmii->hSubMenu = menu->hSubMenu;
-    else
-        lpmii->hSubMenu = 0; /* hSubMenu is always cleared */
+    else {
+        /* hSubMenu is always cleared 
+         * (not on Win9x/ME ) */
+        lpmii->hSubMenu = 0;
+    }
 
     if (lpmii->fMask & MIIM_CHECKMARKS) {
 	lpmii->hbmpChecked = menu->hCheckBit;
@@ -4433,10 +4451,12 @@ static BOOL SetMenuItemInfo_common(MENUI
 {
     if (!menu) return FALSE;
 
-    debug_print_menuitem("MENU_SetItemInfo_common from: ", menu, "");
+    debug_print_menuitem("SetmenuItemInfo_common from: ", menu, "");
 
     if (lpmii->fMask & MIIM_TYPE ) {
         if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
+            WARN("invalid combination of fMask bits used\n");
+            /* this does not happen on Win9x/ME */
             SetLastError( ERROR_INVALID_PARAMETER);
             return FALSE;
         }


More information about the wine-patches mailing list