menu.c: fix for items with HBMMENU_CALLBACK bitmap handle.

Rein Klazes wijn at wanadoo.nl
Tue Jul 5 12:10:47 CDT 2005


Hi,

Fixes for bug #3073,  "Icons are drawn incorrectly in menu - always at
very top of menu instead of being drawn near menu entries".

Changelog:

dlls/user	: menu.c

- when sending the WM_DRAWITEM message in case of a menu item with
hbmpItem = HBMMENU_CALLBACK, move the drawing origin to the top left of
the item rectangle;
- at the same time also make sure that the itemState field of the
DRAWITEMSTRUCT is properly initialized;
- Do the drawing of the check mark before sending the WM_DRAWITEM
message, some application likes to "overdraw" the checkmark.

Rein.
-------------- next part --------------
--- wine/dlls/user/menu.c	2005-06-21 10:01:33.000000000 +0200
+++ mywine/dlls/user/menu.c	2005-07-05 15:19:05.000000000 +0200
@@ -1285,39 +1285,16 @@ static void MENU_DrawMenuItem( HWND hwnd
 
         if (!(lpitem->fType & MF_OWNERDRAW))
         {
+            RECT rc;
+            rc = rect;
             /* New style MIIM_BITMAP */
             if (lpitem->hbmpItem)
             {
                 POPUPMENU *menu = MENU_GetMenu(hmenu);
-                HBITMAP hbm = lpitem->hbmpItem;
-
-                if (hbm == HBMMENU_CALLBACK)
-                {
-                    DRAWITEMSTRUCT drawItem;
-                    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;
-
-                    if (!(lpitem->fState & MF_CHECKED))
-                        SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
-
-                } else {
-                    MENU_DrawBitmapItem(hdc, lpitem, &rect, FALSE, TRUE);
-                }
                 if (menu->dwStyle & MNS_CHECKORBMP)
-                    rect.left += menu->maxBmpSize.cx - check_bitmap_width;
+                    rc.left += menu->maxBmpSize.cx - check_bitmap_width;
                 else
-                    rect.left += menu->maxBmpSize.cx;
+                    rc.left += menu->maxBmpSize.cx;
             }
             /* Draw the check mark
              *
@@ -1329,7 +1306,7 @@ static void MENU_DrawMenuItem( HWND hwnd
             {
                 HDC hdcMem = CreateCompatibleDC( hdc );
                 SelectObject( hdcMem, bm );
-                BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
+                BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
                         check_bitmap_width, check_bitmap_height,
                         hdcMem, 0, 0, SRCCOPY );
                 DeleteDC( hdcMem );
@@ -1344,11 +1321,43 @@ static void MENU_DrawMenuItem( HWND hwnd
                 DrawFrameControl( hdcMem, &r, DFC_MENU,
                                   (lpitem->fType & MFT_RADIOCHECK) ?
                                   DFCS_MENUBULLET : DFCS_MENUCHECK );
-                BitBlt( hdc, rect.left, (y - r.bottom) / 2, r.right, r.bottom,
+                BitBlt( hdc, rc.left, (y - r.bottom) / 2, r.right, r.bottom,
                         hdcMem, 0, 0, SRCCOPY );
                 DeleteDC( hdcMem );
                 DeleteObject( bm );
             }
+            /* New style MIIM_BITMAP */
+            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);
+
+                } else {
+                    MENU_DrawBitmapItem(hdc, lpitem, &rect, FALSE, TRUE);
+                }
+            }
         }
 
 	  /* Draw the popup-menu arrow */


More information about the wine-patches mailing list