wxWidgets应用程序在主窗口的状态栏中显示正常菜单项的帮助字符串。不幸的是,它似乎没有显示使用wxWindow::PopupMenu
命令调用的菜单,我需要它。
我尝试在父窗口中添加EVT_MENU_HIGHLIGHT_ALL
处理程序,但它没有被调用。
必须有一些方法来处理或重定向消息以显示帮助文本。我错过了什么?
答案 0 :(得分:1)
我尝试通过wxFrame
而不是当前窗口(wxListCtrl
)调用它。这有所帮助,但并不多:当鼠标移动到弹出菜单项时,它会清除状态栏,但不会显示它的帮助文本。
当我挖掘wxWidgets源代码时,我发现了原因:我的弹出菜单项不在菜单栏上。 wxWidgets将菜单项的ID发送到菜单栏以获取文本,在这种情况下显然会失败。
花了一些时间,但我想出了解决问题的方法:
////////////////////////////////////////////////////////////////////////////
// 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
是一个便利函数,用于定位程序的框架窗口并在其上调用GetStatusBar
。)
现在我只是从PopupMenu
派生一个类来获取我需要的任何弹出窗口。结果很完美。
可能有一种更简单的方法来解决这个问题,但是如果没有将弹出菜单项放在菜单栏上,我就无法找到它。
答案 1 :(得分:0)
Head Geek的解决方案对于wxWidgets 3.0.2并不适合我,但我发现了另一个:使用Bind
临时注册wxEVT_MENU_HIGHLIGHT
事件处理程序wxFrame
包含点击的控件。完整的例子:
class FunctionMenuWindow : public wxWindow
{
public:
int option;
FunctionMenuWindow(wxWindow *parent) : wxWindow(parent, -1), option(0), mPushed(false)
{
this ->Bind(wxEVT_MENU , &FunctionMenuWindow::OnMenu , this, wxID_ANY);
theMainWin->Bind(wxEVT_MENU_OPEN , &FunctionMenuWindow::OnOpen , this, wxID_ANY);
theMainWin->Bind(wxEVT_MENU_CLOSE , &FunctionMenuWindow::OnClose , this, wxID_ANY);
theMainWin->Bind(wxEVT_MENU_HIGHLIGHT, &FunctionMenuWindow::OnHighlight, this, wxID_ANY);
}
~FunctionMenuWindow()
{
theMainWin->Unbind(wxEVT_MENU_OPEN , &FunctionMenuWindow::OnOpen , this, wxID_ANY);
theMainWin->Unbind(wxEVT_MENU_CLOSE , &FunctionMenuWindow::OnClose , this, wxID_ANY);
theMainWin->Unbind(wxEVT_MENU_HIGHLIGHT, &FunctionMenuWindow::OnHighlight, this, wxID_ANY);
}
private:
void OnMenu(wxCommandEvent& event)
{
option = event.GetId();
}
void OnOpen(wxMenuEvent &evt)
{
this->mMenu = evt.GetMenu();
if (!mPushed)
{
theMainWin->GetStatusBar()->PushStatusText(wxString());
mPushed = true;
}
}
void OnClose(wxMenuEvent &evt)
{
if (mPushed)
{
theMainWin->GetStatusBar()->PopStatusText();
mPushed = false;
}
}
const wxString GetHelpString(wxMenuEvent &evt)
{
if (evt.GetMenuId() < 0)
return wxString();
else
return mMenu->GetHelpString(evt.GetMenuId());
}
void OnHighlight(wxMenuEvent &evt)
{
if (mPushed)
theMainWin->GetStatusBar()->SetStatusText(GetHelpString(evt));
else
{
theMainWin->GetStatusBar()->PushStatusText(GetHelpString(evt));
mPushed = true;
}
}
bool mPushed;
wxMenu* mMenu;
};
///////////////////////////////////////////////////////////////////
void ShowMenu()
{
FunctionMenuWindow funcWindow(theMainWin);
wxMenu *menu = new wxMenu;
// ... set up wxMenu ...
funcWindow.PopupMenu(menu);
switch(funcWindow.option)
{
// ... switch by wxID as usual ...
}
}