如何显示wxWidgets弹出菜单的帮助字符串?

3
应用程序通常会在主窗口的状态栏中显示普通菜单项的帮助字符串。不幸的是,对于使用wxWindow::PopupMenu命令调用的菜单,它似乎不会显示它们,而我需要它来实现这个功能。
我尝试将EVT_MENU_HIGHLIGHT_ALL处理程序添加到父窗口,但它没有被调用。
肯定有一些方法来处理或重定向消息以显示帮助文本。我错过了什么吗?
2个回答

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 派生一个类来处理需要的弹出菜单。结果很完美。

也许有一种更简单的方法解决这个问题,但是如果没有将弹出菜单的项目放在菜单栏上,我就找不到它。


这段代码是否适用于弹出菜单中的任何菜单项?我无法为弹出菜单上的每个选项管理高亮事件。 - jgsogo
据我所知,应该可以。不过那是使用较旧版本的wxWidgets,当前版本可能有所改变。 - Head Geek

0

Head Geek的解决方案对于我使用的wxWidgets 3.0.2无效,但我找到了另一种方法:使用Bind在被点击控件所在的wxFrame上临时注册一个wxEVT_MENU_HIGHLIGHT事件处理程序。完整示例:

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 ...
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接