JUCE复合控件之MenubarModel

实现主菜单功能离不开MenubarModel菜单栏模型抽象基类,同时需要两个辅助类:

  • PopupMenu弹出式菜单对象,代表菜单栏中的顶级菜单,用户点击了哪个顶级菜单的名称,该对象就添加哪个顶级菜单所需的菜单项,并自动模态显示在该顶级菜单名称的下面。该对象需由MenuBarModel的派生类在getMenuForIndex()中创建、添加菜单项或命令项,而后返回之。
  • ApplicationCommandManager程序命令管理器对象。PopupMenu添加菜单项时,可以直接添加该菜单项的文本和ID,也可添加程序命令,将程序命令作为菜单项。每个程序命令均有简略描述(作为菜单项或按钮所显示的文本),同时均有一个唯一性的ID,ApplicationCommandTarget将根据此ID在其perform()函数中执行对应的代码。

具体流程有三

1、自定义视图类(或者次顶级的内容组件类,或者干脆程序的DocumentWindow窗口框架类),继承MenubarModel类,实现该基类的3个纯虚函数:

  • getMenuBarNames () 设置主菜单的各个菜单名称,返回StringArray栈对象。
  • getMenuForIndex () 根据两个参数中的之一,返回所对应的PopupMenu栈对象。需临时定义PopupMenu栈对象,而后使用switch或if…else if…结构添加每个主菜单的各个菜单项。可直接添加,也可添加程序命令管理器中的命令项。
  • menuItemSelected () 每个菜单项所执行的代码在此定义。基于本函数的参数(菜单项的ID或主菜单的索引),采用switch结构。菜单项来源于命令项者,所执行的代码无需在此编程,ApplicationCommandTarget的派生类中会有定义。

2、打算使用主菜单的DocumentWindow类,调用setMenubar(主菜单对象)函数设置主菜单。无需布局定位,主菜单自动位于DocumentWindow的标题栏之下,客户区之上,且不计入窗口框架的可用区域。设置后,主菜单对象调用其成员函数setApplicationCommandManagerToWatch (命令管理器对象)时刻关注命令管理器中的命令是否有改变。

3、窗口框架类的析构函数中,先将主菜单设置为空,而后在销毁程序命令管理器对象之前先销毁主菜单对象:

setMenubar (nullptr);

#if JUCE_MAC  // 编译条件宏
    MenuBarModel::setMacMainMenu (nullptr);
#endif

// 销毁命令管理器之前,先销毁主菜单
deleteAndZero (主菜单对象);
deleteAndZero (命令管理器对象);

示例代码:(网站发布,略)

扩展阅读
MenuBarModel类是抽象基类,该类中又嵌套了一个抽象基类MenuBarModel::Listener,当MenuBarModel发生变化时,所产生的消息可被该类捕获并处理。该类的纯虚函数为:

  • menuBarItemsChanged () 菜单栏模型的菜单项改变时,自动回调此函数
  • menuCommandInvoked () 调用某个菜单项的程序命令时, 自动回调此函数