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

发布于 2024-11-03 10:26:32 字数 201 浏览 2 评论 0原文

wxWidgets 应用程序在主窗口的状态栏中显示普通菜单项的帮助字符串。不幸的是,它似乎没有显示使用 wxWindow::PopupMenu 命令调用的菜单,但我需要它。

我尝试将 EVT_MENU_HIGHLIGHT_ALL 处理程序添加到父窗口,但它没有被调用。

必须有某种方法来处理或重定向消息以显示帮助文本。我缺少什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

喜爱纠缠 2024-11-10 10:26:32

我尝试通过 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 派生一个类来获取我需要的任何弹出窗口。结果很完美。

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

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.

后来的我们 2024-11-10 10:26:32

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

Head Geek's solution didn't work for me for wxWidgets 3.0.2, but I found a different one: Use Bind to temporarily register a wxEVT_MENU_HIGHLIGHT event handler on the wxFrame containing the clicked control. Full example:

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 ...
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文