X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8a9e5d85906675820d7f30ff250b8b1c2b44b693..a56a99abe859f37615251c865bc807bf13e8b180:/src/msw/menu.cpp diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index 3cf48b33d3..46346acca8 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -39,6 +39,8 @@ #include "wx/ownerdrw.h" #endif +#include "wx/ptr_scpd.h" + #include "wx/msw/private.h" #include "wx/msw/wrapcctl.h" // include "properly" @@ -59,24 +61,6 @@ // other standard headers #include -//VC6 needs these defining, though they are in winuser.h -#ifndef MIIM_BITMAP -#define MIIM_STRING 0x00000040 -#define MIIM_BITMAP 0x00000080 -#define MIIM_FTYPE 0x00000100 -#define HBMMENU_CALLBACK ((HBITMAP) -1) -typedef struct tagMENUINFO -{ - DWORD cbSize; - DWORD fMask; - DWORD dwStyle; - UINT cyMax; - HBRUSH hbrBack; - DWORD dwContextHelpID; - DWORD dwMenuData; -} MENUINFO, FAR *LPMENUINFO; -#endif - #if wxUSE_OWNER_DRAWN #include "wx/dynlib.h" #endif @@ -103,9 +87,12 @@ static const UINT idMenuTitle = (UINT)-3; // private functions // ---------------------------------------------------------------------------- +namespace +{ + // make the given menu item default -static void SetDefaultMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu), - UINT WXUNUSED_IN_WINCE(id)) +void SetDefaultMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu), + UINT WXUNUSED_IN_WINCE(id)) { #ifndef __WXWINCE__ MENUITEMINFO mii; @@ -133,7 +120,18 @@ UINT GetMenuState(HMENU hMenu, UINT id, UINT flags) wxLogLastError(wxT("GetMenuItemInfo")); return info.fState; } -#endif +#endif // __WXWINCE__ + +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 + // need to use here + return bmp.GetWidth() < ::GetSystemMetrics(SM_CXMENUCHECK) + 4 && + bmp.GetHeight() < ::GetSystemMetrics(SM_CYMENUCHECK) + 4; +} + +} // anonymous namespace // ============================================================================ // implementation @@ -446,91 +444,100 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) #if wxUSE_OWNER_DRAWN if ( pItem->IsOwnerDrawn() ) { - // is the item owner-drawn just because of the [checked] bitmap? - if ( (pItem->GetBitmap(false).Ok() || pItem->GetBitmap(true).Ok()) && - !pItem->GetTextColour().Ok() && - !pItem->GetBackgroundColour().Ok() && - !pItem->GetFont().Ok() ) - { - // try to use InsertMenuItem() as it's guaranteed to look correct - // while our owner-drawn code is not #ifndef __DMC__ - // DMC at march 2007 doesn't have HBITMAP hbmpItem tagMENUITEMINFOA /W - // MIIM_BITMAP only works under WinME/2000+ + // if the item is owner-drawn just because of the [checked] bitmap and + // the bitmap uses standard menu bitmap size we can avoid making it + // owner-drawn and use built-in support for menu bitmaps instead + bool mustUseOwnerDrawn = 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)) ) + { + mustUseOwnerDrawn = true; + } + } + + // MIIM_BITMAP only works under WinME/2000+ + if ( !mustUseOwnerDrawn && wxGetWinVersion() >= wxWinVersion_98 ) + { + // use InsertMenuItem() as it's guaranteed to look correct while + // our owner-drawn code is not WinStruct mii; - if ( wxGetWinVersion() >= wxWinVersion_98 ) + mii.fMask = MIIM_STRING | MIIM_DATA | MIIM_BITMAP; + if ( pItem->IsCheckable() ) { - mii.fMask = MIIM_STRING | MIIM_DATA | MIIM_BITMAP; - if ( pItem->IsCheckable() ) - { - // need to set checked/unchecked bitmaps as otherwise our - // MSWOnDrawItem() item is not called - mii.fMask |= MIIM_CHECKMARKS; - } + // need to set checked/unchecked bitmaps as otherwise our + // MSWOnDrawItem() item is not called + mii.fMask |= MIIM_CHECKMARKS; + } - mii.cch = itemText.length(); - mii.dwTypeData = wx_const_cast(wxChar *, itemText.wx_str()); + mii.cch = itemText.length(); + mii.dwTypeData = const_cast(itemText.wx_str()); - if (flags & MF_POPUP) - { - mii.fMask |= MIIM_SUBMENU; - mii.hSubMenu = (HMENU)pItem->GetSubMenu()->GetHMenu(); - } - else - { - mii.fMask |= MIIM_ID; - mii.wID = id; - } + if (flags & MF_POPUP) + { + mii.fMask |= MIIM_SUBMENU; + mii.hSubMenu = (HMENU)pItem->GetSubMenu()->GetHMenu(); + } + else + { + mii.fMask |= MIIM_ID; + mii.wID = id; + } - // 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 instead draw it ourselves in MSWOnDrawItem() - mii.dwItemData = wx_reinterpret_cast(ULONG_PTR, pItem); - if ( pItem->IsCheckable() ) - { - mii.hbmpChecked = - mii.hbmpUnchecked = HBMMENU_CALLBACK; - } - mii.hbmpItem = HBMMENU_CALLBACK; + // 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 instead draw it ourselves in MSWOnDrawItem() + mii.dwItemData = reinterpret_cast(pItem); + if ( pItem->IsCheckable() ) + { + mii.hbmpChecked = + mii.hbmpUnchecked = HBMMENU_CALLBACK; + } + mii.hbmpItem = HBMMENU_CALLBACK; - ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii); - if ( !ok ) - { - wxLogLastError(wxT("InsertMenuItem()")); - } - else // InsertMenuItem() ok + ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii); + if ( !ok ) + { + wxLogLastError(wxT("InsertMenuItem()")); + } + else // InsertMenuItem() ok + { + // we need to remove the extra indent which is reserved for + // the checkboxes by default as it looks ugly unless check + // boxes are used together with bitmaps and this is not the + // case in wx API + WinStruct mi; + + // don't call SetMenuInfo() directly, this would prevent + // the app from starting up under Windows 95/NT 4 + typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *); + + wxDynamicLibrary dllUser(_T("user32")); + wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser); + if ( pfnSetMenuInfo ) { - // we need to remove the extra indent which is reserved for - // the checkboxes by default as it looks ugly unless check - // boxes are used together with bitmaps and this is not the - // case in wx API - WinStruct mi; - - // don't call SetMenuInfo() directly, this would prevent - // the app from starting up under Windows 95/NT 4 - typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *); - - wxDynamicLibrary dllUser(_T("user32")); - wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser); - if ( pfnSetMenuInfo ) - { - mi.fMask = MIM_STYLE; - mi.dwStyle = MNS_CHECKORBMP; - if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) ) - wxLogLastError(_T("SetMenuInfo(MNS_NOCHECK)")); - } - - // tell the item that it's not really owner-drawn but only - // needs to draw its bitmap, the rest is done by Windows - pItem->ResetOwnerDrawn(); + mi.fMask = MIM_STYLE; + mi.dwStyle = MNS_CHECKORBMP; + if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) ) + wxLogLastError(_T("SetMenuInfo(MNS_NOCHECK)")); } + + // tell the item that it's not really owner-drawn but only + // needs to draw its bitmap, the rest is done by Windows + pItem->ResetOwnerDrawn(); } -#endif // __DMC__ } +#endif // __DMC__ if ( !ok ) { @@ -714,6 +721,15 @@ size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const return count; } +wxAcceleratorTable *wxMenu::CreateAccelTable() const +{ + const size_t count = m_accels.size(); + wxScopedArray accels(new wxAcceleratorEntry[count]); + CopyAccels(accels.get()); + + return new wxAcceleratorTable(count, accels.get()); +} + #endif // wxUSE_ACCEL // --------------------------------------------------------------------------- @@ -760,7 +776,7 @@ void wxMenu::SetTitle(const wxString& label) info.fMask = MIIM_TYPE; info.fType = MFT_STRING; info.cch = m_title.length(); - info.dwTypeData = wx_const_cast(wxChar *, m_title.wx_str()); + info.dwTypeData = const_cast(m_title.wx_str()); if ( !SetMenuItemInfo(hMenu, 0, TRUE, & info) ) { wxLogLastError(wxT("SetMenuItemInfo")); @@ -930,7 +946,7 @@ WXHMENU wxMenuBar::Create() if ( m_hMenu != 0 ) return m_hMenu; - wxToolMenuBar * const bar = wx_static_cast(wxToolMenuBar *, GetToolBar()); + wxToolMenuBar * const bar = static_cast(GetToolBar()); if ( !bar ) return NULL; @@ -1080,7 +1096,7 @@ void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label) info.fMask = MIIM_TYPE; info.fType = MFT_STRING; info.cch = label.length(); - info.dwTypeData = wx_const_cast(wxChar *, label.wx_str()); + info.dwTypeData = const_cast(label.wx_str()); if ( !SetMenuItemInfo(GetHmenu(), id, TRUE, &info) ) { wxLogLastError(wxT("SetMenuItemInfo")); @@ -1347,7 +1363,7 @@ void wxMenuBar::RebuildAccelTable() nAccelCount += (*it)->CopyAccels(&accelEntries[nAccelCount]); } - m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries); + SetAcceleratorTable(wxAcceleratorTable(nAccelCount, accelEntries)); delete [] accelEntries; }