From a3da62503f389c1507d2d20fadd6e615b0b6a714 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 23 Mar 2014 15:18:37 +0000 Subject: [PATCH] Fix setting menu item bitmaps after appending them in wxMSW. Update the bitmap used by Windows when using non-owner-drawn items with bitmaps. Closes #9388. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76191 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/msw/menuitem.h | 14 ++++---- src/msw/menuitem.cpp | 70 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 0097a5c5a4..d4614c3acc 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -52,6 +52,7 @@ wxMSW: - Improve wxMimeTypesManager open command detection (Eric Jensen). - Make wxFILTER_INCLUDE_LIST in wxTextValidator actually usable. +- Fix setting menu item bitmaps after appending them (Artur Wieczorek). - Fix handling of selected images in wxBitmapButton (Artur Wieczorek). - Fix loading of bitmap with non-pre-multiplied alpha (Artur Wieczorek). - Support multiline strings in wxDC::DrawRotatedText() (Artur Wieczorek). diff --git a/include/wx/msw/menuitem.h b/include/wx/msw/menuitem.h index f0f87d7a51..4dbaee6761 100644 --- a/include/wx/msw/menuitem.h +++ b/include/wx/msw/menuitem.h @@ -77,18 +77,13 @@ public: void SetBitmaps(const wxBitmap& bmpChecked, const wxBitmap& bmpUnchecked = wxNullBitmap) { - m_bmpChecked = bmpChecked; - m_bmpUnchecked = bmpUnchecked; - SetOwnerDrawn(true); + DoSetBitmap(bmpChecked, true); + DoSetBitmap(bmpUnchecked, false); } void SetBitmap(const wxBitmap& bmp, bool bChecked = true) { - if ( bChecked ) - m_bmpChecked = bmp; - else - m_bmpUnchecked = bmp; - SetOwnerDrawn(true); + DoSetBitmap(bmp, bChecked); } void SetDisabledBitmap(const wxBitmap& bmpDisabled) @@ -124,6 +119,9 @@ private: // helper function to get a handle of bitmap associated with item WXHBITMAP GetHBitmapForMenu(bool checked = true); + // helper function to set/change the bitmap + void DoSetBitmap(const wxBitmap& bmp, bool bChecked); + #else // !wxUSE_OWNER_DRAWN // Provide stubs for the public functions above to ensure that the code // still compiles without wxUSE_OWNER_DRAWN -- it makes sense to just drop diff --git a/src/msw/menuitem.cpp b/src/msw/menuitem.cpp index cd9cbe93ba..ef6479cd11 100644 --- a/src/msw/menuitem.cpp +++ b/src/msw/menuitem.cpp @@ -740,6 +740,76 @@ void wxMenuItem::SetItemLabel(const wxString& txt) #if wxUSE_OWNER_DRAWN +void wxMenuItem::DoSetBitmap(const wxBitmap& bmp, bool bChecked) +{ + if ( bChecked ) + { + if ( m_bmpChecked.IsSameAs(bmp) ) + return; + + m_bmpChecked = bmp; + } + else + { + if ( m_bmpUnchecked.IsSameAs(bmp) ) + return; + + m_bmpUnchecked = bmp; + } + + // already marked as owner-drawn, cannot be reverted + if ( IsOwnerDrawn() ) + return; + + // assume owner-drawn state, will be reset if we can use Windows bitmap + // support instead of making the item owner-drawn + SetOwnerDrawn(true); + + if ( MustUseOwnerDrawn() ) + return; + + // the item can be not attached to any menu yet and SetBitmap() is still + // valid to call in this case and should do nothing else + if ( !m_parentMenu ) + return; + + HMENU hMenu = GetHMenuOf(m_parentMenu); + if ( !hMenu ) + return; + + const UINT id = GetMSWId(); + + const UINT state = ::GetMenuState(hMenu, id, MF_BYCOMMAND); + if ( state == (UINT)-1 ) + return; + + // update the bitmap of the native menu item + // don't set hbmpItem for the checkable items as it would + // be used for both checked and unchecked state + WinStruct mii; + if ( IsCheckable() ) + { + mii.fMask = MIIM_CHECKMARKS; + mii.hbmpChecked = GetHBitmapForMenu(true); + mii.hbmpUnchecked = GetHBitmapForMenu(false); + } + else + { + mii.fMask = MIIM_BITMAP; + mii.hbmpItem = GetHBitmapForMenu(); + } + + if ( !::SetMenuItemInfo(hMenu, id, FALSE, &mii) ) + { + wxLogLastError(wxT("SetMenuItemInfo")); + return; + } + + // No need to really make the item owner drawn, Windows will draw its + // bitmap(s) for us. + SetOwnerDrawn(false); +} + int wxMenuItem::MeasureAccelWidth() const { wxString accel = GetItemLabel().AfterFirst(wxT('\t'));