企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 4.9 控制条 控制条提供了一个比较直观而方便的方法来排列多个控件。目前有三种类型的控制条,分别是:菜单条,工具条和状态条,其中菜单条只能在frame窗口上使用,工具条和状态条通常也是在frame窗口上使用,不过它们也可以作为别的窗口的子窗口。 wxMenuBar 菜单条包含一系列的菜单,显示在frame窗口顶部标题栏的下方。你可以通过调用SetMenuBar函数覆盖frame窗口当前的菜单条,使用下面的代码创建一个菜单条: ``` wxMenuBar* menuBar = new wxMenuBar; wxMenu* fileMenu = new wxMenu; fileMenu->Append(wxID_OPEN, wxT("&Open..."), wxT("Opens a file")); fileMenu->AppendSeparator(); fileMenu->Append(wxID_EXIT, wxT("E&xit"), wxT("Quits the program")); menuBar->Append(fileMenu); frame->SetMenuBar(menuBar, wxT("&File")); ``` 上述代码创建了一个只有一个菜单的菜单条,如下图所示: ![](img/mht4E8D%281%29.tmp) 你可以给菜单增加子菜单,也可以在菜单上增加单选框和复选框,还可以给菜单项增加快捷键和加速键(请参考本章前一章节的内容)。 如果你提供了一个帮助字符创,那么默认的EVT_MENU_HIGHLIGHT函数会将其显示到frame的窗口的状态栏上(如果有的话)。 wxMenuBar的窗口类型 wxMenuBar拥有一个wxMB_DOCKABLE类型,在GTK+平台上允许菜单条从主窗口分离出来。 wxMenuBar事件 参考本章前一小节中的相关内容。 wxMenuBar成员函数 Append函数在菜单条的末尾增加一个菜单项,一旦菜单项被成功增加,那么它将被菜单条管理并且在合适的时候被释放。这个函数参数为要增加的菜单以及一个标签。Insert函数则在给定的位置插入一个菜单。 Enable函数允许或者禁止给定标识符的菜单项. 使用IsEnabled函数判断菜单项是否被允许. Check函数选中或者去选中一个复选框或者单选框菜单项. 使用IsChecked函数来获得当前的选择状态。 EnableTop函数允许或者禁止一整个菜单。参数为基于0的菜单索引。 FindMenu使用给定的标签字符串查找某个菜单,其中参数字符串可以带有前导字符也可以不带有前导字符.如果找不到则返回wxNOT_FOUND. FindMenuItem通过菜单名和菜单项返回菜单项的索引。 FindItem通过给定的菜单项标识符返回wxMenuItem类型的菜单项,如果这个菜单项是一个子菜单,那么第二个参数将会返回这个子菜单的指针。 GetHelpString和SetHelpString用来获取或者设置某个菜单项的帮助信息。 GetLabel和SetLabel用来设置某个菜单项的标签, GetLabelTop和 SetLabelTop用来获取和设置某个菜单在菜单条上的标签,参数为基于0的索引。 GetMenu根据索引返回对应菜单指针, GetMenuCount返回菜单条上所有菜单的个数, Refresh重画菜单条。 Remove移除一个菜单项并且返回对应的菜单指针,然后用户应该自己释放这个已经移除的菜单。 Replace函数则将某个位置的菜单使用新的菜单代替并且返回老的菜单的指针。 用户应该自己释放这个老的菜单, wxToolBar 工具条用来放置各种按钮和控件。工具条可以是水平的也可以是垂直的,其上的按钮可以是单选,复选以及push按钮。这些按钮可以显示标签也可以显示图片。如果你使用wxFrame::CreateToolBar函数创建工具条,或者使用wxFrame::SetToolBar函数将你创建的工具条和 frame窗口绑定,那么frame窗口将会管理这个工具条的位置和大小以及释放,并且工具条的大小也不算作frame的客户区大小。。任何其它方法创建的工具条,你都需要自己使用布局控件或者其它方法来来负责这个工具条的位置和大小, 下面是创建工具条以及和frame窗口绑定的例子代码: ``` #include "wx/toolbar.h" #include "open.xpm" #include "save.xpm" wxToolBar* toolBar = new wxToolBar(frame, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL|wxNO_BORDER); wxBitmap bmpOpen(open_xpm); wxBitmap bmpSave(save_xpm); toolBar->AddTool(wxID_OPEN, bmpOpen, wxT("Open")); toolBar->AddTool(wxID_SAVE, bmpSave, wxT("Save")); toolBar->AddSeparator(); wxComboBox* comboBox = new wxComboBox(toolBar, ID_COMBOBOX); toolBar->AddControl(comboBox); toolBar->Realize(); frame->SetToolBar(toolBar); ``` 在windows平台上的外观如下图所示: ![](img/mht4E90%281%29.tmp) 注意调用Realize之前,所有位于其上的按钮和控件应该已经被增加到了工具条中,否则工具条上将什么也不会显示。 你可以查看wxWidgets的samples/toolbar中的例子,来了解怎样更改工具条的方向,增加显示按钮上的标签以及更改按钮的大小等等其它方面的内容。 Windows平台上工具按钮上的图片的颜色 在windows平台上,wxWidgets试图将工具按钮上的图片的颜色映射到当前桌面风格下的标准颜色。通常来说,亮灰色(light gray)用来表示透明颜色。下表列出了所有这些颜色。事实上,工具按钮上的图片的颜色只需要接近于标准颜色。接近意味着RGB三原色的值和标准颜色的值差别在10个单位范围内。 | 颜色值 | 颜色名 | 用于 | |:--- |:--- |:--- | | wxColour(0, 0, 0) | 黑色 | 深色阴影 | | wxColour(128, 128, 128) | 深灰 | 亮物体的3维边缘的阴面 | | wxColour(192, 192, 192) | 亮灰 | 3维物体的表面(按钮背景), 表示透明区域 | | wxColour(255, 255, 255) | 白色 | 亮物体的3维边缘的高亮面 | 对于16色的图片来说,这中映射是没有问题的,但是如果你使用的是颜色更丰富的按钮图片甚至真彩图片,那么这种映射可能会让你的按钮上的图片变的非常丑陋,在这种情况下,你可以使用下面的代码禁止这种映射: ``` wxSystemOptions::SetOption(wxT("msw.remap"), 0); ``` 要使用上面的代码,你需要包含"wx/sysopt.h"头文件。 wxToolBar的窗口类型 | wxTB_HORIZONTAL | 创建水平工具条. | |:--- |:--- | | wxTB_VERTICAL | 创建垂直工具条. | | wxTB_FLAT | 给工具条一个浮动外观. Windows and GTK+ only. | | wxTB_DOCKABLE | 使得工具条可以支持浮动和放置. GTK+ only. | | wxTB_TEXT | 显示按钮上的标签;默认情况下只显示图标. | | wxTB_NOICONS | 不显示按钮上的图标;默认情况下是显示的. | | wxTB_NODIVIDER | 指示工具条上没有分割线. Windows only. | | wxTB_HORZ_LAYOUT | 指示文本显示在图片的旁边而不是下面. 仅适用于Windows和GTK+. 这个类型必须和wxTB_TEXT共同使用. | | wxTB_HORZ_TEXT | 是wxTB_HORZ_LAYOUT和wxTB_TEXT的组合. | wxToolBar的事件 工具条事件映射宏如下表所示。象前面说过的那样,工具条的事件宏和菜单的事件宏是完全一样的,你既可以使用EVT_MENU宏,也可以使用EVT_TOOL宏。它们的事件处理函数的参数类型都是wxCommandEvent。对于它们中的大多数来说,窗口标识符指的都是工具按钮的窗口标识符,只有EVT_TOOL_ENTER事件宏的窗口标识符指的是工具条的窗口标识符,而对应的工具按钮的窗口标识符要从wxCommandEvent事件中获取,这是因为在表示鼠标离开一个工具按钮的时候,窗口标识符可能为-1,而在wxWidgets的事件体系中是不允许标识符为-1的。 | EVT_TOOL(id, func) | 用于处理wxEVT_COMMAND_TOOL_CLICKED事件 (和wxEVT_COMMAND_MENU_SELECTED的值相同), 在用户点击工具按钮的时候产生. 在宏中使用工具按钮的标识符. | |:--- |:--- | | EVT_TOOL_RANGE(id1, id2, func) | 用于处理一组工具按钮标识符的wxEVT_COMMAND_TOOL_CLICKED事件. | | EVT_TOOL_RCLICKED(id, func) | 用于处理wxEVT_COMMAND_TOOL_RCLICKED事件,用户在工具按钮上点击右键的时候产生.使用工具按钮的窗口标识符. | | EVT_TOOL_RCLICKED_RANGE (id1, id2, func) | 用于处理一组工具按钮标识符的wxEVT_COMMAND_TOOL_RCLICKED事件. | | EVT_TOOL_ENTER(id, func) | 用于处理wxEVT_COMMAND_TOOL_ENTER事件, 用户的鼠标移入或者移出某个工具按钮的额时候产生,宏中使用工具条的窗口标识符,使用wxCommandEvent::GetSelection函数来获得移入的工具按钮的标识符,如果是移出则这个值是-1 | wxToolBar的成员函数 AddTool增加一个工具按钮:指定按钮的标识符,一个可选的标签,一个图片,一个帮助信息,以及按钮的类型(wxITEM_NORMAL, wxITEM_CHECK, 或者wxITEM_RADIO). 使用InsertTool在某个特定的位置插入一个工具按钮. 也可以使用AddCheckTool和AddRadioTool来避免指定wxITEM_CHECK或wxITEM_RADIO类型. AddSeparator 增加一个分割线,基于实现的不同,它可能显示为一条线或者一段空白. 使用InsertSeparator在某个特定的位置插入一个分割线,例如下面的代码将增加一个复选框工具按钮,它包含一个标签("Save"), 一个图片,一个帮助字符串 ("Toggle button 1"): ``` toolBar->AddTool(wxID_SAVE, wxT("Save"), bitmap, wxT("Toggle button 1"), wxITEM_CHECK); ``` AddControl增加一个控件,比如combo框. InsertControl在某个位置插入一个控件, DeleteTool删除给定标识符的工具按钮. DeleteToolByPos删除指定位置的按钮. RemoveTool移除给定位置的那个按钮但是并不释放它,而是将它的指针返回给. EnableTool用来允许或者禁止某个工具按钮,你可能想参考第9章中的方法,使用用户界面更新事件来更合理的作这个动作。 GetToolEnabled函数返回某个工具按钮的当前可用状态。 FindById和FindControl来通过窗口标识符寻找某个按钮或者某个控件。 如果你想使用非默认大小16x15的图标。你可以使用SetToolBitmapSize函数. 使用GetToolBitmapSize函数获得当前设置的图片尺寸. GetToolSize返回当前工具按钮整个的大小。 GetMargins和SetMargins用来获取和设置工具条的左右和上下的边界。 GetToolClientData和SetToolClientData通过窗口标识符获取和设置工具按钮绑定的某个继承自wxObject的类. GetToolLongHelp和SetToolLongHelp用来获取或者设置和工具按钮绑定的长的帮助信息。这个信息可以被显示在状态条或者别的什么位置。GetToolShortHelp则用来获取或者设置工具按钮的短的帮助信息。 GetToolPacking 和 SetToolPacking用来获取和设置两排工具按钮之间的间隔。如果是垂直工具条,则为水平工具按钮之间的间隔,如果为水平工具条,则为垂直工具按钮之间的间隔。 GetToolPosition返回某个由窗口标识符指定的工具按钮在工具条上的位置。 GetToolSeparation和 SetToolSeparation用来获取或者设置工具条上分割线的大小。 GetToolState和SetToolState用来获取或者设置某个单选框或者复选框的状态。 Realize必须在任何按钮被增加以后调用。 ToggleTool反选某个单选或者复选按钮的状态。 wxStatusBar 状态条是一个狭长的窗口,这个窗口通常被放置在一个Frame窗口的底部,用来提供一些状态信息。状态条可以包含一个或多个区域,区域可以拥有固定的或者可变的宽度。如果你使用wxFrame::CreateStatusBar或者wxFrame::SetStatusBar创建或者将某个状态条和frame窗口绑定,那么这个状态条的大小,位置以及其释放都由这个frame窗口负责,并且这个状态条的大小也不包含在frame窗口的客户区域内,反之,任何其它的方式创建的状态条,这些事情都要由你自己的代码去做。 下面是创建一个状态条的例子代码,这个状态条有三个区域,前两个的大小固定是60象素,第三个将使用剩余的区域: ``` #include "wx/statusbr.h" wxStatusBar* statusBar = new wxStatusBar(frame, wxID_ANY, wxST_SIZEGRIP); frame->SetStatusBar(statusBar); int widths[] = { 60, 60, -1 }; statusBar->SetFieldWidths(WXSIZEOF(widths), widths); statusBar->SetStatusText(wxT("Ready"), 0); ``` 这段代码产生的结果如下图所示: ![](img/mht4EA3%281%29.tmp) 如果你想,你甚至可以在状态条的区域里面放置一些小的控件。这需要你自己管理它们的尺寸和大小,例如在你继承自wxStatusBar的新类的size事件的处理函数中。 wxStatusBar的窗口类型,注意你可以使用SetStatusStyles函数设置某个区域的类型 |:--- |:--- | | wxST_SIZEGRIP | 在状态条的右边显示一个小的修饰. | wxStatusBar的事件 没有特别的事件。 wxStatusBar的成员函数 GetFieldRect返回某个区域的内部的大小和位置. GetFieldsCount返回当前区域的个数. SetFieldsCount用来设置区域的个数。 GetStatusText返回当前某个区域的文本, SetStatusText用来设置某个区域的文本. PushStatusText保存当前的区域的文本到一个堆栈中,并且把参数的字符串显示在状态条上. PopStatusText则将堆栈中最顶层的字符串显示在状态条上。 SetMinHeight设置状态条最小的合理高度。 SetStatusWidths采用一个整数数组来设置各个区域的宽度。其中整数代表绝对值,而负数则代表比例,比如说,如果你希望创建一个有三个区域的状态条,其中最右边的区域固定为100个象素,左边的两个区域按照2/3和1/3的比例瓜分剩下的区域,则你应该使用一个包含-2,- 1,100三个整数的数组作为这个函数的参数。 SetStatusStyles使用区域个数和一组整数的类型数组来给各个区域设置不同的类型,这些整数的类型决定了区域的外观。其中 wxSB_NORMAL用来显示标准的拥有三维边界的下沉区域,而wxSB_FLAT显示一个没有边框的区域,而wxSB_RAISED则显示一个鼓起的拥有三维边框的区域。