diff --git a/include/wx/msw/menuitem.h b/include/wx/msw/menuitem.h index d76bd11950..f0f87d7a51 100644 --- a/include/wx/msw/menuitem.h +++ b/include/wx/msw/menuitem.h @@ -118,6 +118,12 @@ private: // helper function for draw std menu check mark void DrawStdCheckMark(WXHDC hdc, const tagRECT* rc, wxODStatus stat); + // helper function to determine if the item must be owner-drawn + bool MustUseOwnerDrawn(); + + // helper function to get a handle of bitmap associated with item + WXHBITMAP GetHBitmapForMenu(bool checked = true); + #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 @@ -141,6 +147,9 @@ private: m_bmpDisabled; #endif // wxUSE_OWNER_DRAWN + // Give wxMenu access to our MustUseOwnerDrawn() and GetHBitmapForMenu(). + friend class wxMenu; + DECLARE_DYNAMIC_CLASS_NO_COPY(wxMenuItem) }; diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index e5552c9fa9..00421693cf 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -236,12 +236,6 @@ UINT GetMenuState(HMENU hMenu, UINT id, UINT flags) } #endif // __WXWINCE__ -inline bool IsGreaterThanStdSize(const wxBitmap& bmp) -{ - return bmp.GetWidth() > ::GetSystemMetrics(SM_CXMENUCHECK) || - bmp.GetHeight() > ::GetSystemMetrics(SM_CYMENUCHECK); -} - } // anonymous namespace // ============================================================================ @@ -412,49 +406,6 @@ void wxMenu::UpdateAccel(wxMenuItem *item) namespace { -// helper of DoInsertOrAppend(): returns the HBITMAP to use in MENUITEMINFO -HBITMAP GetHBitmapForMenu(wxMenuItem *pItem, bool checked = true) -{ - // Under versions of Windows older than Vista we can't pass HBITMAP - // directly as hbmpItem for 2 reasons: - // 1. We can't draw it with transparency then (this is not - // very important now but would be with themed menu bg) - // 2. Worse, Windows inverts the bitmap for the selected - // item and this looks downright ugly - // - // So we prefer to instead draw it ourselves in MSWOnDrawItem().by using - // HBMMENU_CALLBACK when inserting it - // - // However under Vista using HBMMENU_CALLBACK causes the entire menu to be - // drawn using the classic theme instead of the current one and it does - // handle transparency just fine so do use the real bitmap there -#if wxUSE_IMAGE - if ( wxGetWinVersion() >= wxWinVersion_Vista ) - { -#if wxUSE_OWNER_DRAWN - wxBitmap bmp = pItem->GetBitmap(checked); - if ( bmp.IsOk() ) - { - // we must use PARGB DIB for the menu bitmaps so ensure that we do - wxImage img(bmp.ConvertToImage()); - if ( !img.HasAlpha() ) - { - img.InitAlpha(); - pItem->SetBitmap(img, checked); - } - - return GetHbitmapOf(pItem->GetBitmap(checked)); - } -#endif // wxUSE_OWNER_DRAWN - //else: bitmap is not set - - return NULL; - } -#endif // wxUSE_IMAGE - - return HBMMENU_CALLBACK; -} - } // anonymous namespace bool wxMenu::MSWGetRadioGroupRange(int pos, int *start, int *end) const @@ -558,36 +509,9 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) if ( !m_ownerDrawn && !pItem->IsSeparator() ) { - // 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 - static const wxWinVersion winver = wxGetWinVersion(); - bool mustUseOwnerDrawn = winver < wxWinVersion_98 || - pItem->GetTextColour().IsOk() || - pItem->GetBackgroundColour().IsOk() || - pItem->GetFont().IsOk(); - - // Windows XP or earlier don't display menu bitmaps bigger than - // standard size correctly (they're truncated), so we must use - // owner-drawn items to show them correctly there. OTOH Win7 - // doesn't seem to have any problems with even very large bitmaps - // so don't use owner-drawn items unnecessarily there (Vista wasn't - // actually tested but I assume it works as 7 rather than as XP). - if ( !mustUseOwnerDrawn && winver < wxWinVersion_Vista ) - { - const wxBitmap& bmpUnchecked = pItem->GetBitmap(false), - bmpChecked = pItem->GetBitmap(true); - - if ( (bmpUnchecked.IsOk() && IsGreaterThanStdSize(bmpUnchecked)) || - (bmpChecked.IsOk() && IsGreaterThanStdSize(bmpChecked)) ) - { - mustUseOwnerDrawn = true; - } - } - // use InsertMenuItem() if possible as it's guaranteed to look // correct while our owner-drawn code is not - if ( !mustUseOwnerDrawn ) + if ( !pItem->MustUseOwnerDrawn() ) { WinStruct mii; mii.fMask = MIIM_STRING | MIIM_DATA; @@ -597,13 +521,13 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) if ( pItem->IsCheckable() ) { mii.fMask |= MIIM_CHECKMARKS; - mii.hbmpChecked = GetHBitmapForMenu(pItem, true); - mii.hbmpUnchecked = GetHBitmapForMenu(pItem, false); + mii.hbmpChecked = pItem->GetHBitmapForMenu(true); + mii.hbmpUnchecked = pItem->GetHBitmapForMenu(false); } else if ( pItem->GetBitmap().IsOk() ) { mii.fMask |= MIIM_BITMAP; - mii.hbmpItem = GetHBitmapForMenu(pItem); + mii.hbmpItem = pItem->GetHBitmapForMenu(); } mii.cch = itemText.length(); diff --git a/src/msw/menuitem.cpp b/src/msw/menuitem.cpp index 3c09d878fa..cd9cbe93ba 100644 --- a/src/msw/menuitem.cpp +++ b/src/msw/menuitem.cpp @@ -134,6 +134,12 @@ private: int m_modeOld; }; +inline bool IsGreaterThanStdSize(const wxBitmap& bmp) +{ + return bmp.GetWidth() > ::GetSystemMetrics(SM_CXMENUCHECK) || + bmp.GetHeight() > ::GetSystemMetrics(SM_CYMENUCHECK); +} + } // anonymous namespace // ============================================================================ @@ -1249,6 +1255,82 @@ void wxMenuItem::GetColourToUse(wxODStatus stat, wxColour& colText, wxColour& co wxOwnerDrawn::GetColourToUse(stat, colText, colBack); } } + +bool wxMenuItem::MustUseOwnerDrawn() +{ + // 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 + static const wxWinVersion winver = wxGetWinVersion(); + bool mustUseOwnerDrawn = winver < wxWinVersion_98 || + GetTextColour().IsOk() || + GetBackgroundColour().IsOk() || + GetFont().IsOk(); + + // Windows XP or earlier don't display menu bitmaps bigger than + // standard size correctly (they're truncated), so we must use + // owner-drawn items to show them correctly there. OTOH Win7 + // doesn't seem to have any problems with even very large bitmaps + // so don't use owner-drawn items unnecessarily there (Vista wasn't + // actually tested but I assume it works as 7 rather than as XP). + if ( !mustUseOwnerDrawn && winver < wxWinVersion_Vista ) + { + const wxBitmap& bmpUnchecked = GetBitmap(false), + bmpChecked = GetBitmap(true); + + if ( (bmpUnchecked.IsOk() && IsGreaterThanStdSize(bmpUnchecked)) || + (bmpChecked.IsOk() && IsGreaterThanStdSize(bmpChecked)) ) + { + mustUseOwnerDrawn = true; + } + } + + return mustUseOwnerDrawn; +} + +// returns the HBITMAP to use in MENUITEMINFO +HBITMAP wxMenuItem::GetHBitmapForMenu(bool checked) +{ + // Under versions of Windows older than Vista we can't pass HBITMAP + // directly as hbmpItem for 2 reasons: + // 1. We can't draw it with transparency then (this is not + // very important now but would be with themed menu bg) + // 2. Worse, Windows inverts the bitmap for the selected + // item and this looks downright ugly + // + // So we prefer to instead draw it ourselves in MSWOnDrawItem().by using + // HBMMENU_CALLBACK when inserting it + // + // However under Vista using HBMMENU_CALLBACK causes the entire menu to be + // drawn using the classic theme instead of the current one and it does + // handle transparency just fine so do use the real bitmap there +#if wxUSE_IMAGE + if ( wxGetWinVersion() >= wxWinVersion_Vista ) + { +#if wxUSE_OWNER_DRAWN + wxBitmap bmp = GetBitmap(checked); + if ( bmp.IsOk() ) + { + // we must use PARGB DIB for the menu bitmaps so ensure that we do + wxImage img(bmp.ConvertToImage()); + if ( !img.HasAlpha() ) + { + img.InitAlpha(); + SetBitmap(img, checked); + } + + return GetHbitmapOf(GetBitmap(checked)); + } +#endif // wxUSE_OWNER_DRAWN + //else: bitmap is not set + + return NULL; + } +#endif // wxUSE_IMAGE + + return HBMMENU_CALLBACK; +} + #endif // wxUSE_OWNER_DRAWN // ----------------------------------------------------------------------------