【wxWidgets教程】窗体:菜单与菜单栏

《wxWidgets窗体:掌握wxFrame创建与使用技巧》之后,我们将关注wxWidget窗体wxFrame的交互性设计相关的内容。wxWidgets教程完整目录

菜单与菜单栏是传统窗口程序的界面元素之一,交互式设计的重要用户接口。

一、类图

在wxWidgets中,菜单与菜单栏的类图结构如下:

菜单栏wxMenuBar是菜单wxMenu的容器,wxMenu是菜单项wxMenuItem的容器。菜单栏通常位于窗口顶部,响应菜单选择。

菜单会触发事件wxMenuEvent,wxMenu和wxMenuBar都派生自wxEvtHandler,具有事件处理能力。

二、窗体口添加菜单

(一)创建菜单栏

可以使用wxMenuBar(long style=0)创建一个空白的菜单栏,然后再依据需要逐个创建菜单wxMenu并调用wxMenuBar::Append()添加至菜单栏中。

示例如下:

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, wxID_ANY, title, pos, size){
    ...
    //创建菜单File
   wxMenu *menuFile = new wxMenu;
    //在菜单中添加菜单项
    menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
        "Help string shown in status bar for this menu item");
    //在菜单中添加菜单分隔栏
    menuFile->AppendSeparator();
    //在菜单中添加预定义菜单“Exit”
    menuFile->Append(wxID_EXIT);
    //创建菜单Help
    wxMenu *menuHelp = new wxMenu; 
    //创建预定义菜单项“About”
    wxMenuItem* item=menuHelp->Append(wxID_ABOUT);
    //为预定义菜单项“About”设置图标
    wxBitmap* bmpAbout=new wxBitmap(“about.png”,wxBITMAP_TYPE_PNG);
    item->SetBitmap(bmpAbout);
    //创建菜单栏,依次加入上面创建的菜单
    wxMenuBar *menuBar = new wxMenuBar;
    menuBar->Append( menuFile, "&File" );    
    menuBar->Append( menuHelp, "&Help" );
    //为窗体设置菜单栏
    SetMenuBar( menuBar ); 
    ...
}

此外,还可以使用构造函数wxMenuBar   (size_t n, wxMenu * menus[], const wxString titles[], long style = 0 )创建,其中:

        n:菜单个数;

        menus[]:需要装载的菜单对象;

        titles[]:menus[]中菜单对象对应的菜单名称;

        style:菜单样式,默认为0,在GTK系统中可以设置为wxMB_DOCKABLE,使菜单栏具备停靠功能。

菜单栏创建成功后,通过wxFrame的void SetMenuBar(wxMenuBar *menubar) 将其添加至窗口中。

两种创建菜单栏的方式区别在于创建wxMenuBar之前是否需要全部确定需要装载的菜单。通常第一种方式更灵活,而第二种方式更高效。

(二)上下文菜单

菜单wxMenu是菜单项wxMenuItem的容器。菜单可以在菜单栏中使用,也可以用在上下文菜单中,下面的代码在窗口鼠标右键响应函数中弹出一个上下文菜单。

void MyWindow::OnRightClick(wxMouseEvent& event){
    if(contextMenu==nullptr){
        contextMenu=new wxMenu;
        contextMenu->Append(wxID_TASK_CREATE,
        _("Create"),_("Create a transfer task"));
    }
    ...
    this->PopupMenu(popMenu,event.GetPosition());
}

三、菜单项

菜单项wxMenuItem是菜单命令的直接执行项,在wxWidgets中通常可以不用直接构建wxMenuItem实例的方式来创建菜单项,wxMenu::Append()提供更快捷的创建方式。下面的代码将创建一个菜单项,并设置菜单项的图标:

wxMenuItem* item=menu->Append(wxID_NEW, wxT("&New...\tCtrl+N"));
item->SetBitmap(bmp);

(一)预定义菜单项

在上面的示例中,wxID_ABOUT和wxID_EXIT是由wxWidgets预定义的,具有特殊含义,因此使用这些id的条目将从OS X下的正常菜单中取出,并插入到系统菜单中(遵循适当的OS X接口指南)

(二)自定义菜单项

自定义菜单项可以是普通项、checkbox项或radiobutton选项。普通项没有任何特殊属性,而checkbox项有一个与之关联的布尔标志,并且在设置该标志时,它们在菜单中显示一个复选标记。wxWidgets在单击项时自动切换标志值,可以使用wxMenu的wxMenu::IsChecked()方法或wxMenuBar本身来检索其值,或者在获取有关项的菜单通知时使用wxEvent::IsChecked()。

wxMenuItem* item=menu->AppendCheckItem(wxID_NEW, wxT("&New...\tCtrl+N")); 

radiobutton项与checkbox项类似,只是在检查单选项时,同一个单选组中的所有其他项都未选中。radiogroup由一个连续的radio项目范围构成,即它从这类的第一个项目开始,以另一类的第一个项目(或菜单的结尾)结束。请注意,由于radiogroup是根据项目位置定义的,因此在包含radiogroup菜单中插入或删除项目可能会导致无法正常工作。如下例所示,定义了两个Radio菜单项,通过wxID_ANY的普通菜单项和一个分隔栏分开。如果程序动态删除ID为wxID_ANY或分隔栏的菜单项,则多个radiogroup将合并成一个。

menuFile->AppendSeparator();
menuFile->AppendRadioItem(ID_R0,"R0");
menuFile->AppendRadioItem(ID_R1,"R1");
menuFile->AppendSeparator();
menuFile->AppendRadioItem(ID_R2,"R2");
menuFile->AppendRadioItem(ID_R3,"R3");
menuFile->Append(wxID_ANY,"dive radio group");
menuFile->AppendRadioItem(ID_R9,"R9");
menuFile->AppendRadioItem(ID_RA,"RA");
menuBar->Append(menuFile,"&File");

有时也可以直接创建wxMenuItem来构建菜单。

wxMenuItem(wxMenu *parentMenu NULL,
int id wxID_SEPARATOR,
const wxStringtext wxEmptyString,
const wxStringhelp wxEmptyString,
wxItemKind kind wxITEM_NORMAL,
wxMenu *subMenu NULL)

parentMenu指向包含它的菜单,可以先设置为空,然后再调用wxMenuItem* wxMenu::Append(wxMenuItem* menuItem)将菜单项加入菜单中。

菜单项可以是标准菜单项或自定义菜单项。对于标准菜单项(例如打开文件、退出程序等的命令),只需指定内置ID,其余参数使用默认值即可。一些平台(目前仅wxGTK)也会显示内置菜单项的标准位图。实际上,wxWidgets建议内置菜单项的文本参数text和helpString使用默认值,因为这将使菜单具有用户熟悉的外观和键盘界面(包括标准加速器)。

//使用预定义菜单项
helpMenu->Append(wxID_ABOUT);
//使用预定义菜单项的标签文本与快捷键和自定义帮助字符串
helpMenu->Append(wxID_ABOUT, "", "My custom help string");
//使用预定义菜单项,自定义图标
wxMenuItem *mymenu = new wxMenuItem(helpMenu, wxID_ABOUT);
mymenu->SetBitmap(wxArtProvider::GetBitmap(wxART_WARNING));
//将菜单项添加至菜单中
helpMenu->Append(mymenu);

对于自定义(非内置)菜单项,必须指定text,虽然helpString可能为空,但建议在此参数中传递项描述(当选择菜单项时会自动在状态栏中显示)。

响应菜单事件,需要在包含菜单栏的窗口事件处理表中添加EVT_MENU的处理函数。

enum{
    ID_Hello = 1
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(ID_Hello, MyFrame::OnHello) 
    EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()

四、事件处理

(一)事件处理函数

菜单项的事件处理函数具有如下两种形式:

void handlerFuncName(wxCommandEvent& event)

void handlerFuncName(wxMenuEvent& event)

(二)事件类型

与菜单相关其它事件宏:

EVT_MENU(func):处理菜单点击事件,用户点击菜单时触发。事件对象wxCommandEvent

EVT_MENU_RANGE(id1, id2, func):处理id在[id1,id2]范围内的菜单的点击事件,事件对象为wxCommandEvent

EVT_MENU_OPEN(func):用来处理wxEVT_MENU_OPEN事件,在一个菜单即将被打开的时候产生。在windows平台上主菜单上每次遍历只会导致一次该事件产生。事件对象为wxMenuEvent。

EVT_MENU_CLOSE(func):用来处理wxEVT_MENU_CLOSE事件,它在某个菜单被关闭的时候产生。事件对象为wxMenuEvent。

EVT_MENU_HIGHLIGHT(id, func):用来处理wxEVT_MENU_HIGHLIGHT事件,当某个菜单项被高亮显示的时候产生,通常用来在主程序的状态栏上产生关于这个菜单项的帮助信息。事件对象为wxMenuEvent。

EVT_MENU_HIGHLIGHT_ALL(func):用来处理wxEVT_MENU_HIGHLIGHT事件,在任何一个菜单项被高亮显示的时候产生。事件对象为wxMenuEvent。

菜单项具有与其关联的整数ID,可用于标识所选内容或以某种方式更改菜单项。具有特殊标识符wxID_SEPARATOR分隔符的菜单项是分隔项,没有关联命令,只是在菜单中出现分隔线。

五、总结

示例基于静态绑定的方式演示菜单事件处理,事实上,您也可以采用动态绑定的方法。相关文档可参考《wxWidgets窗体:事件处理之动态绑定》一文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万法若空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值