From 74daaf8c3635d7a8bb70547144a5e8ec37851b3c Mon Sep 17 00:00:00 2001 From: David Langhals Date: Fri, 11 Oct 2024 11:05:42 +0200 Subject: [PATCH 1/3] Let wxMenuEvent carry an optional wxMenuItem to be able to have access to more information about the event --- include/wx/event.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/wx/event.h b/include/wx/event.h index a7670bd0f5..42060febb5 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -45,6 +45,7 @@ class WXDLLIMPEXP_FWD_BASE wxEventFilter; #if wxUSE_GUI class WXDLLIMPEXP_FWD_CORE wxDC; class WXDLLIMPEXP_FWD_CORE wxMenu; + class WXDLLIMPEXP_FWD_CORE wxMenuItem; class WXDLLIMPEXP_FWD_CORE wxReadOnlyDC; class WXDLLIMPEXP_FWD_CORE wxWindow; class WXDLLIMPEXP_FWD_CORE wxWindowBase; @@ -2576,12 +2577,12 @@ private: class WXDLLIMPEXP_CORE wxMenuEvent : public wxEvent { public: - wxMenuEvent(wxEventType type = wxEVT_NULL, int winid = 0, wxMenu* menu = nullptr) + wxMenuEvent(wxEventType type = wxEVT_NULL, int winid = 0, wxMenu* menu = nullptr, wxMenuItem* menuItem = nullptr) : wxEvent(winid, type) - { m_menuId = winid; m_menu = menu; } + { m_menuId = winid; m_menu = menu; m_menuItem = menuItem; } wxMenuEvent(const wxMenuEvent& event) : wxEvent(event) - { m_menuId = event.m_menuId; m_menu = event.m_menu; } + { m_menuId = event.m_menuId; m_menu = event.m_menu; m_menuItem = event.m_menuItem; } // only for wxEVT_MENU_HIGHLIGHT int GetMenuId() const { return m_menuId; } @@ -2592,11 +2593,14 @@ public: // only for wxEVT_MENU_OPEN/CLOSE wxMenu* GetMenu() const { return m_menu; } + wxMenuItem* GetMenuItem() const { return m_menuItem; } + virtual wxEvent *Clone() const override { return new wxMenuEvent(*this); } private: - int m_menuId; - wxMenu* m_menu; + int m_menuId; + wxMenu* m_menu; + wxMenuItem* m_menuItem; wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxMenuEvent); }; From eb109358d0a60742dbb3f492790e25497ad6ef08 Mon Sep 17 00:00:00 2001 From: David Langhals Date: Fri, 11 Oct 2024 11:09:22 +0200 Subject: [PATCH 2/3] In case the wxMenuEvent parameter in wxFrameBase::OnMenuHighlight carries a wxMenuItem object, use the menu item's help text directly without looking up the item via its ID --- src/common/framecmn.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/common/framecmn.cpp b/src/common/framecmn.cpp index 3a7c667c8d..33ba2c44f0 100644 --- a/src/common/framecmn.cpp +++ b/src/common/framecmn.cpp @@ -343,7 +343,14 @@ void wxFrameBase::OnMenuHighlight(wxMenuEvent& event) { event.Skip(); - (void)ShowMenuHelp(event.GetMenuId()); + if( wxMenuItem* menuItem = event.GetMenuItem() ) + { + DoGiveHelp(menuItem->GetHelp(), true); + } + else + { + (void)ShowMenuHelp(event.GetMenuId()); + } } void wxFrameBase::OnMenuClose(wxMenuEvent& event) From c1e2acd9e6ed41690ec53248757df89b8800d729 Mon Sep 17 00:00:00 2001 From: David Langhals Date: Fri, 11 Oct 2024 11:16:37 +0200 Subject: [PATCH 3/3] MSW: Find a wxMenuItem object corresponding to a given ID by iterating through all menu entries in the MSW menu handle and pass the found wxMenuItem to the wxMenuEvent. This gives the wxMenuEvent access to all information stored in the wxMenuItem and not just its ID --- include/wx/msw/window.h | 4 ++++ src/msw/window.cpp | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index dcf558d559..e24d34a29d 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -574,6 +574,10 @@ public: // Find the menu corresponding to the given handle. virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu); + + // Find the the current menu item using the given handle and the item id + virtual wxMenuItem* MSWFindMenuItemFromHMENU(WXHMENU hMenu, int nItem); + #endif // wxUSE_MENUS && !__WXUNIVERSAL__ // Return the default button for the TLW containing this window or nullptr if diff --git a/src/msw/window.cpp b/src/msw/window.cpp index e882a5cdb7..971b182784 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2524,11 +2524,13 @@ wxWindowMSW::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu) // the top level menus of the menu bar, which can't be represented using // any valid identifier in wxMenuEvent so use an otherwise unused value for // them - if ( flags & (MF_POPUP | MF_SEPARATOR) ) + if ( flags & MF_SEPARATOR ) item = wxID_NONE; wxMenu* menu = MSWFindMenuFromHMENU(hMenu); - wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item, menu); + wxMenuItem* menuItem = MSWFindMenuItemFromHMENU(hMenu, item); + + wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item, menu, menuItem); if ( wxMenu::ProcessMenuEvent(menu, event, this) ) return true; @@ -2577,6 +2579,37 @@ wxMenu* wxWindowMSW::MSWFindMenuFromHMENU(WXHMENU hMenu) return nullptr; } +wxMenuItem* wxWindowMSW::MSWFindMenuItemFromHMENU(WXHMENU hMenu, int item) +{ + WinStruct mii; + mii.fMask = MIIM_ID | MIIM_DATA; // Include MIIM_DATA to access dwItemData + + const int count = ::GetMenuItemCount(hMenu); + for ( int i = 0; i < count; i++ ) + { + if ( ::GetMenuItemInfo(hMenu, i, TRUE, &mii) ) + { + wxMenuItem* menuItem = (wxMenuItem*)mii.dwItemData; + if ( mii.wID == (unsigned int)item && menuItem ) + { + return menuItem; + } + + // Check for submenus + if ( mii.hSubMenu ) + { + wxMenuItem* foundInSubmenu = MSWFindMenuItemFromHMENU(mii.hSubMenu, item); + if ( foundInSubmenu ) + { + return foundInSubmenu; + } + } + } + } + + return nullptr; // Not found +} + #endif // wxUSE_MENUS && !defined(__WXUNIVERSAL__) // ===========================================================================