Fix calculation of the margins for owner-drawn menu items.
Take into account the widths of the bitmaps properly. Closes #11268. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63222 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		@@ -120,6 +120,14 @@ private:
 | 
			
		||||
    wxAcceleratorArray m_accels;
 | 
			
		||||
#endif // wxUSE_ACCEL
 | 
			
		||||
 | 
			
		||||
#if wxUSE_OWNER_DRAWN
 | 
			
		||||
    // true if the menu has any ownerdrawn items
 | 
			
		||||
    bool m_ownerDrawn;
 | 
			
		||||
 | 
			
		||||
    // the max width of menu items bitmaps
 | 
			
		||||
    int m_maxBitmapWidth;
 | 
			
		||||
#endif // wxUSE_OWNER_DRAWN
 | 
			
		||||
 | 
			
		||||
    DECLARE_DYNAMIC_CLASS_NO_COPY(wxMenu)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										114
									
								
								src/msw/menu.cpp
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								src/msw/menu.cpp
									
									
									
									
									
								
							@@ -106,7 +106,27 @@ void SetDefaultMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu),
 | 
			
		||||
    {
 | 
			
		||||
        wxLogLastError(wxT("SetMenuItemInfo"));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
#endif // !__WXWINCE__
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// make the given menu item owner-drawn
 | 
			
		||||
void SetOwnerDrawnMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu),
 | 
			
		||||
                           UINT WXUNUSED_IN_WINCE(id),
 | 
			
		||||
                           ULONG_PTR WXUNUSED_IN_WINCE(data))
 | 
			
		||||
{
 | 
			
		||||
#ifndef __WXWINCE__
 | 
			
		||||
    MENUITEMINFO mii;
 | 
			
		||||
    wxZeroMemory(mii);
 | 
			
		||||
    mii.cbSize = sizeof(MENUITEMINFO);
 | 
			
		||||
    mii.fMask = MIIM_FTYPE | MIIM_DATA;
 | 
			
		||||
    mii.fType = MFT_OWNERDRAW;
 | 
			
		||||
    mii.dwItemData = data;
 | 
			
		||||
 | 
			
		||||
    if ( !::SetMenuItemInfo(hmenu, id, FALSE, &mii) )
 | 
			
		||||
    {
 | 
			
		||||
        wxLogLastError(wxT("SetMenuItemInfo"));
 | 
			
		||||
    }
 | 
			
		||||
#endif // !__WXWINCE__
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __WXWINCE__
 | 
			
		||||
@@ -125,7 +145,7 @@ UINT GetMenuState(HMENU hMenu, UINT id, UINT flags)
 | 
			
		||||
}
 | 
			
		||||
#endif // __WXWINCE__
 | 
			
		||||
 | 
			
		||||
bool IsLessThanStdSize(const wxBitmap& bmp)
 | 
			
		||||
inline bool IsLessThanStdSize(const wxBitmap& bmp)
 | 
			
		||||
{
 | 
			
		||||
    // FIXME: these +4 are chosen so that 16*16 bitmaps pass this test with
 | 
			
		||||
    //        default SM_CXMENUCHECK value but I have no idea what do we really
 | 
			
		||||
@@ -244,6 +264,11 @@ void wxMenu::Init()
 | 
			
		||||
    m_doBreak = false;
 | 
			
		||||
    m_startRadioGroup = -1;
 | 
			
		||||
 | 
			
		||||
#if wxUSE_OWNER_DRAWN
 | 
			
		||||
    m_ownerDrawn = false;
 | 
			
		||||
    m_maxBitmapWidth = 0;
 | 
			
		||||
#endif // wxUSE_OWNER_DRAWN
 | 
			
		||||
 | 
			
		||||
    // create the menu
 | 
			
		||||
    m_hMenu = (WXHMENU)CreatePopupMenu();
 | 
			
		||||
    if ( !m_hMenu )
 | 
			
		||||
@@ -470,25 +495,9 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 | 
			
		||||
#if wxUSE_OWNER_DRAWN
 | 
			
		||||
    // Under older systems mixing owner-drawn and non-owner-drawn items results
 | 
			
		||||
    // in inconsistent margins, so we force this one to be owner-drawn if any
 | 
			
		||||
    // other items already are. Later we might want to use a boolean in the
 | 
			
		||||
    // wxMenu to avoid search. Also we might make this fix unnecessary by
 | 
			
		||||
    // getting the correct margin using NONCLIENTMETRICS.
 | 
			
		||||
    static const wxWinVersion winver = wxGetWinVersion();
 | 
			
		||||
    if ( winver < wxWinVersion_XP &&
 | 
			
		||||
            !pItem->IsOwnerDrawn() && !pItem->IsSeparator() )
 | 
			
		||||
    {
 | 
			
		||||
        // Check if any other items are ownerdrawn, and make ownerdrawn if so
 | 
			
		||||
        wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
 | 
			
		||||
        while (node)
 | 
			
		||||
        {
 | 
			
		||||
            if (node->GetData()->IsOwnerDrawn())
 | 
			
		||||
            {
 | 
			
		||||
    // other items already are.
 | 
			
		||||
    if ( m_ownerDrawn && !pItem->IsSeparator() )
 | 
			
		||||
        pItem->SetOwnerDrawn(true);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            node = node->GetNext();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif // wxUSE_OWNER_DRAWN
 | 
			
		||||
 | 
			
		||||
    // check if we have something more than a simple text item
 | 
			
		||||
@@ -496,17 +505,23 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 | 
			
		||||
    if ( pItem->IsOwnerDrawn() )
 | 
			
		||||
    {
 | 
			
		||||
#ifndef __DMC__
 | 
			
		||||
 | 
			
		||||
        if ( !m_ownerDrawn )
 | 
			
		||||
        {
 | 
			
		||||
            // MIIM_BITMAP only works under WinME/2000+ so we always use owner
 | 
			
		||||
        // drawn item under the previous versions and we also have to use them
 | 
			
		||||
        // in any case if the item has custom colours or font
 | 
			
		||||
            // drawn item under the previous versions and we also have to use
 | 
			
		||||
            // them in any case if the item has custom colours or font
 | 
			
		||||
            static const wxWinVersion winver = wxGetWinVersion();
 | 
			
		||||
            bool mustUseOwnerDrawn = winver < wxWinVersion_98 ||
 | 
			
		||||
                                     pItem->GetTextColour().Ok() ||
 | 
			
		||||
                                     pItem->GetBackgroundColour().Ok() ||
 | 
			
		||||
                                     pItem->GetFont().Ok();
 | 
			
		||||
 | 
			
		||||
            if ( !mustUseOwnerDrawn )
 | 
			
		||||
            {
 | 
			
		||||
                const wxBitmap& bmpUnchecked = pItem->GetBitmap(false),
 | 
			
		||||
                                bmpChecked   = pItem->GetBitmap(true);
 | 
			
		||||
 | 
			
		||||
                if ( (bmpUnchecked.Ok() && !IsLessThanStdSize(bmpUnchecked)) ||
 | 
			
		||||
                     (bmpChecked.Ok()   && !IsLessThanStdSize(bmpChecked)) )
 | 
			
		||||
                {
 | 
			
		||||
@@ -514,8 +529,8 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        // use InsertMenuItem() if possible as it's guaranteed to look correct
 | 
			
		||||
        // while our owner-drawn code is not
 | 
			
		||||
            // use InsertMenuItem() if possible as it's guaranteed to look
 | 
			
		||||
            // correct while our owner-drawn code is not
 | 
			
		||||
            if ( !mustUseOwnerDrawn )
 | 
			
		||||
            {
 | 
			
		||||
                WinStruct<MENUITEMINFO> mii;
 | 
			
		||||
@@ -585,6 +600,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 | 
			
		||||
                    pItem->SetOwnerDrawn(false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif // __DMC__
 | 
			
		||||
 | 
			
		||||
        if ( !ok )
 | 
			
		||||
@@ -592,6 +608,56 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 | 
			
		||||
            // item draws itself, pass pointer to it in data parameter
 | 
			
		||||
            flags |= MF_OWNERDRAW;
 | 
			
		||||
            pData = (LPCTSTR)pItem;
 | 
			
		||||
 | 
			
		||||
            bool updateAllMargins = false;
 | 
			
		||||
 | 
			
		||||
            // get size of bitmap always return valid value (0 for invalid bitmap),
 | 
			
		||||
            // so we don't needed check if bitmap is valid ;)
 | 
			
		||||
            int uncheckedW = pItem->GetBitmap(false).GetWidth();
 | 
			
		||||
            int checkedW   = pItem->GetBitmap(true).GetWidth();
 | 
			
		||||
 | 
			
		||||
            if ( m_maxBitmapWidth < uncheckedW )
 | 
			
		||||
            {
 | 
			
		||||
                m_maxBitmapWidth = uncheckedW;
 | 
			
		||||
                updateAllMargins = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ( m_maxBitmapWidth < checkedW )
 | 
			
		||||
            {
 | 
			
		||||
                m_maxBitmapWidth = checkedW;
 | 
			
		||||
                updateAllMargins = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // make other item ownerdrawn and update margin width for equals alignment
 | 
			
		||||
            if ( !m_ownerDrawn || updateAllMargins )
 | 
			
		||||
            {
 | 
			
		||||
                wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
 | 
			
		||||
                while (node)
 | 
			
		||||
                {
 | 
			
		||||
                    wxMenuItem* item = node->GetData();
 | 
			
		||||
 | 
			
		||||
                    if ( !item->IsSeparator() )
 | 
			
		||||
                    {
 | 
			
		||||
                        if ( !item->IsOwnerDrawn() )
 | 
			
		||||
                        {
 | 
			
		||||
                            item->SetOwnerDrawn(true);
 | 
			
		||||
                            SetOwnerDrawnMenuItem(GetHmenu(), item->GetMSWId(),
 | 
			
		||||
                                                  reinterpret_cast<ULONG_PTR>(item));
 | 
			
		||||
                        }
 | 
			
		||||
                        item->SetMarginWidth(m_maxBitmapWidth);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    node = node->GetNext();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // set menu as ownerdrawn
 | 
			
		||||
                m_ownerDrawn = true;
 | 
			
		||||
            }
 | 
			
		||||
            // only update our margin for equals alignment to other item
 | 
			
		||||
            else if ( !updateAllMargins )
 | 
			
		||||
            {
 | 
			
		||||
                pItem->SetMarginWidth(m_maxBitmapWidth);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user