【问题标题】:Using native c++ wrappers for ncurses, How can I create a menu/submenu system?对 ncurses 使用本机 c++ 包装器,如何创建菜单/子菜单系统?
【发布时间】:2019-05-20 07:37:42
【问题描述】:

去年我学习了 C++(使用 C++ Primer 作为 https://stackoverflow.com/a/388282/1440199 的推荐材料)。我想学习使用 ncurses 来制作我的第一个单独飞行程序。尽管 NCurses 是基于 C 的,但 native ncurses C++ wrappers exist 或多或少并不为人所知。但是,它们的文档几乎不存在;我一直在使用一个 demo.cc 文件作为基础,还有一个 few places around the web。无论如何,我已经完成了我的期末考试,可以这么说,理解和使用这些包装器。

我遇到的问题属于“最佳编程实践”类型:由于缺乏记录示例,我不确定从演示的initial menu system 创建子菜单的最佳方法。

我能想到的最好的办法是使用example wayattach ncurses++'s NCursesUserItem to a menu itemUser Pointer 会是指向前一个菜单类的指针吗?在 NCurses 中,您可以发布和取消发布菜单,所以我还假设我想在新菜单“发布”时“取消发布”上一个菜单,这就是为什么我想要在显示新菜单时指向上一个菜单的原因。

将用户数据(用于 set_item_userptr)附加到菜单项的类型安全示例方法:

template<class T> class SubMenu : public NCursesUserItem<T>
{
  public:
    SubMenu (const char* p_name,
             const T* p_UserData)
            : NCursesUserItem<T>(p_name, static_cast<const char*>(0), p_UserData){}

    virtual ~SubMenu() {}

    bool action() {
        // I believe I want to unpost the previous menu here
        //  before posting the new submenu?
        NCursesUserItem<T>::UserData()->prev_menu()->unpost();
        //This doesn't work, but its kind of what I want to do.
        NCursesUserItem<T>::UserData()->post();
        return FALSE;
    }
};

主菜单对象。我在这里创建了 Submenu 对象并将“this”(主菜单指针)作为参数传递给它。

class MainMenu : public NCursesMenu
{
  private:
    NCursesMenuItem** I;
    Choice0Menu* u;
#define n_items 3
  public:
    MainMenu ()
    : NCursesMenu (n_items+2, 25, (lines()-5)/2, (cols()-23)/2), I(0), u(0)
    {
        u = new Choice0Menu(this);
        I = new NCursesMenuItem*[1+n_items];
        I[0] = new SubMenu<Choice0Menu> ("Choice 0", u);
        I[1] = new PadAction("Choice 1");
        I[2] = new QuitItem();
        I[3] = new NCursesMenuItem();

        InitMenu(I, TRUE, TRUE);
    }
};

Choice0Menu 类,应包含返回主菜单的后退按钮 (I[2])

class Choice0Menu : public NCursesMenu
{
  private:
    NCursesMenuItem** I;
    MainMenu* w;
#define n_items 3

  public:
    Choice0Menu (MainMenu* prev)
    : NCursesMenu (n_items+2, 25, (lines()-5)/2, (cols()-23)/2), I(0), w(prev)
{
    I = new NCursesMenuItem*[1+n_items];
    I[0] = new ScanAction("Submenu Choice 0");
    I[1] = new PadAction("Submenu Choice 1");
    I[2] = new MainMenuAction("Go Back");
    I[3] = new NCursesMenuItem();

    InitMenu(I, TRUE, TRUE);

    // returns the pointer to the prev object
    MainMenu* prev_menu() const{
        return w;
    }
};

我只是对这种做法有很多疑问,例如,也许我在创建子菜单时不必将整个“this”指针传递给主菜单,只需要 post 和 unpost 成员。而且 MainMenu 和 Choice0Menu 类在功能上非常相似,所以甚至可以将其合并为一个模板类?由于 Choice0Menu 将 MainMenu 作为参数,因此可能应该是 T* 来获取任何菜单类型..

我的方法似乎不是解决问题的“干净”方法。

感谢您的帮助。我已经研究这个问题将近 2 周了...

【问题讨论】:

    标签: c++ menu ncurses


    【解决方案1】:

    说实话,我不会使用原生 C++ 接口。我也进入了 ncurses 并看到了本机 C++ 接口,但它只是一个愚蠢的包装器。没有类型检查,全部使用原始指针(没有 std::shared_ptr 系统),它比 Windows 中的 ATL 最差。

    老实说,我只是继续重建其中的一些类,因为这些类本身是非常松散的包装器。我确实喜欢他们尝试摆脱所有宏并将它们更改为内联函数的方式,但是如果没有某种指针管理,甚至只是使用 string_view,这真的没有意义。

    【讨论】:

      猜你喜欢
      • 2019-02-20
      • 2011-09-08
      • 2018-11-23
      • 2019-10-20
      • 2014-07-19
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多