wxWidgets apps show the help strings for normal menu items in the status bar of the main window. Unfortunately, it doesn't seem to show them for menus invoked with the wxWindow::PopupMenu
command, and I need it to.
I've tried adding an EVT_MENU_HIGHLIGHT_ALL
handler to the parent window, but it's not getting called.
There's got to be some way to handle or redirect the messages to show the help text. What am I missing?
I tried invoking it via the wxFrame
instead of the current window (a wxListCtrl
). That helped, but not much: it would clear the status bar when the mouse moved over a popup menu item, but wouldn't show the help text for it.
When I dug into the wxWidgets source code, I discovered the reason: my popup menu's items weren't on the menu bar. wxWidgets sends the ID of the menu item to the menu bar to fetch the text, which obviously fails in this case.
It took some doing, but I figured out a way around the problem:
////////////////////////////////////////////////////////////////////////////
// In a header file...
class PopupMenu: public wxMenu {
public: //
PopupMenu(): mPushed(false) { }
void OnOpen(wxMenuEvent &evt);
void OnClose(wxMenuEvent &evt);
void OnShowMenuHelp(wxMenuEvent &evt);
private: //
bool mPushed;
DECLARE_EVENT_TABLE()
};
////////////////////////////////////////////////////////////////////////////
// In a cpp file...
BEGIN_EVENT_TABLE(PopupMenu, wxMenu)
EVT_MENU_OPEN(PopupMenu::OnOpen)
EVT_MENU_CLOSE(PopupMenu::OnClose)
EVT_MENU_HIGHLIGHT(wxID_ANY, PopupMenu::OnShowMenuHelp)
END_EVENT_TABLE()
void PopupMenu::OnOpen(wxMenuEvent &evt) {
if (!mPushed) {
// Clear it
findStatusBar()->PushStatusText(wxString());
mPushed = true;
}
}
void PopupMenu::OnClose(wxMenuEvent &evt) {
if (mPushed) {
findStatusBar()->PopStatusText();
mPushed = false;
}
}
void PopupMenu::OnShowMenuHelp(wxMenuEvent &evt) {
if (mPushed) {
findStatusBar()->SetStatusText(GetHelpString(evt.GetMenuId()));
} else {
findStatusBar()->PushStatusText(GetHelpString(evt.GetMenuId()));
mPushed = true;
}
}
(findStatusBar
is a convenience function that locates the program's frame window and calls GetStatusBar
on it.)
Now I just derive a class from PopupMenu
for any popups that I need. The results are perfect.
There may be an easier way around this problem, but without putting the popup's items on the menu bar, I wasn't able to find it.