继《wxWidgets窗体:掌握wxFrame创建与使用技巧》之后,我们将关注wxWidget窗体wxFrame的交互性设计相关的内容。wxWidgets教程完整目录
工具栏是一个由按钮或其他控件组成的条状控件,通常位于窗口菜单栏的下方,也可以位于窗口左、右和底部。
一、创建工具栏
调用wxFrame的wxToolBar* CreateToolBar(long style = -1, wxWindowID winid = wxID_ANY, const wxString& name = wxASCII_STR(wxToolBarNameStr))函数可以创建一个由窗口管理的工具栏。尤其是Pocket PC下,您应该始终使用该函数创建工具栏,以便wxWidget可以使用组合菜单栏和工具栏。
style为工具栏的样式。
表 5工具栏样式
| 位置 | wxTB_RIGHT | 位于窗口右侧 |
| wxTB_BOTTOM | 位于窗口底部 | |
| 方向 | wxTB_VERTICAL | 垂直方向 |
| wxTB_HORIZONTAL | 水平方向 | |
| 停靠 | wxTB_DOCKABLE | 工具栏可停靠(仅支持GTK) |
| 文本 图标 | wxTB_TEXT | 显示工具栏项文本 |
| wxTB_NOICONS | 不显示工具栏项图标 | |
| wxTB_HORZ_LAYOUT | 文本与图标水平排列,与wxTB_TEXT同时使用 | |
| wxTB_HORZ_TEXT | wxTB_HORZ_LAYOUT|wxTB_TEXT | |
| 外观 | wxTB_FLAT | 外观平坦 |
| wxTB_NODIVIDER | 在工具栏上方显示一条分隔线 | |
| 提示 | wxTB_NO_TOOLTIPS | 不显示工具项提示内容 |
| 默认 | wxTB_DEFAULT_STYLE | wxTB_HORIZONTAL |
默认情况下,CreateToolBar()返回的是wxToolBar的实例。若要使用其他类,则可重载OnCreateToolBar()。
也可以按照一般控件的方式来创建和处理wxToolBar,即先创建一个工具栏对象实例,然后void wxFrame::SetToolBar(wxToolBar *toolbar)与特定的窗体关联。
使用此函数创建或使用SetToolBar() 关联的工具栏,wxFrame将接管工具栏并调整wxWindow::GetClientSize()的返回值,以反映应用程序窗口客户区的实际空间。
二、添加工具栏项
工具项为工具栏的基本组成元素,wxToolBar支持4种类型的工具项。
(一)按纽
跟wxMenu一样,不必创建wxButton,wxToolBar提供了创建按纽工具项的函数AddTool()。
wxToolBarToolBase *AddTool(int toolid,const wxString& label,
const wxBitmapBundle& bitmap,
const wxBitmapBundle& bmpDisabled,
wxItemKind kind = wxITEM_NORMAL,
const wxString& shortHelp = wxEmptyString,
const wxString& longHelp = wxEmptyString,
wxObject *clientData = NULL)
toolId:唯一标识符。
label:显示的文本
bmpNormal: 正常显示的位图。可在创建之后通过void SetToolNormalBitmap(int id, const wxBitmapBundle&bitmap) 设置。
bmpDisabled:禁用时显示的位图。可创建之后通过void SetToolDisabledBitmap ( int id, const wxBitmapBundle& bitmap ) 设置。
kind:工具项类型,共有四种类型。
表 6 wxItemKind定义
| 类型 | 描述 |
| wxITEM_NORMAL | 正常按纽 |
| wxITEM_CHECK | Checkbox按纽 |
| wxITEM_RADIO | Radio按纽 |
| wxITEM_DROPDOWN | 带下拉菜单的按纽 |
shortHelp:工具提示消息。可在创建之后通过void SetToolShortHelp(int id,const wxString& helpString)设置。
longHelp:显示在状态栏中的提示消息,可在创建之后通过void SetToolLongHelp(int id,const wxString&helpString)设置。
clientData:用户自定义数据,可以通过wxObject* GetToolClientData(int id)获取。也可在创建工具栏之后void SetToolClientData(int id,const wxObject* clientData)设置。
针对kind为wxITEM_CHECK的情况,wxToolBar提供了AddCheckTool()函数。
wxToolBarToolBase *AddCheckTool(int toolid,
const wxString& label,
const wxBitmapBundle& bitmap,
const wxBitmapBundle& bmpDisabled= wxBitmapBundle(),
const wxString& shortHelp = wxEmptyString,
const wxString& longHelp = wxEmptyString,
wxObject *clientData =NULL)
针对kind为wxITEM_RADIO的情况,wxToolBar也提供了类似的AddRadioTool()函数。
wxToolBarToolBase *AddRadioTool(int toolid,
const wxString& label,
const wxBitmapBundle& bitmap,
const wxBitmapBundle& bmpDisabled = wxBitmapBundle(),
const wxString& shortHelp = wxEmptyString,
const wxString& longHelp = wxEmptyString,
wxObject *clientData = NULL)
与其它类型的工具栏按纽相比,Radio按纽稍微复杂一点,需要指定按纽的分组信息,wxWidgets设置分组的方式较为隐晦,约定连续创建的Radio按纽为一个组。
tbarMenu->AppendSeparator();
tbarMenu->AppendRadioItem(POS_TOP,
"Set toolbar at the top\tCtrl-Up",
"Set toolbar at the top of the window");
tbarMenu->AppendRadioItem(POS_LEFT,
"Set toolbar at the left\tCtrl-Left",
"Set toolbar at the left of the window");
tbarMenu->AppendRadioItem(POS_BOTTOM,
"Set toolbar at the bottom\tCtrl-Down",
"Set toolbar at the bottom of the window");
tbarMenu->AppendRadioItem(POS_RIGHT,
"Set toolbar at the right\tCtrl-Right",
"Set toolbar at the right edge of the window");
tbarMenu->AppendSeparator();
tbarMenu->AppendRadioItem(ALIGN_LEFT,
"Set toolbar at the bottom\tCtrl-Down",
"Set toolbar at the bottom of the window");
tbarMenu->AppendRadioItem(ALIGN_RIGHT,
"Set toolbar at the right\tCtrl-Right",
"Set toolbar at the right edge of the window");
tbarMenu->AppendSeparator();
上例中定义了两组Radio按纽,其中ID为POS_xxx的4个连接工具项为一组,ALIGN_xxx的2个连接工具项为另一组,同一组的按纽同一时间只有一个按纽选中。
还有一类带下拉菜单的工具项按纽,通过bool SetDropdownMenu(int toolid, wxMenu *menu) 设置其下拉菜单。需要注意的是,如果您定义了EVT_TOOL_DROPDOWN的事件处理函数,需要在该函数中调用wxEvent::Skip才能显示方法设置的菜单。
(二)控件
工具栏还可以添加从wxControl派生的各类控件,添加函数为wxToolBarToolBase *AddControl(wxControl*control, const wxString& label = wxEmptyString)。此函数能够将继承至wxContro的所有控件作为工具栏中的项。
(三)分隔符
wxToolBarToolBase* AddSeparator()可向工具栏中插入分隔符,分隔符用于工具项的分组。其外观取决于平台,在MSW或某些版本的GTK,是一条垂直线,在另外一些平台中,也可以是一个空白空间或其他形状。
分隔符的宽度默认为5,您可以使用void SetToolSeparation(int separation) 自由设置分隔符的宽度。
(四)可拉伸空间
可拉伸空间会自动填充工具栏中剩余的区域。该方法最常用的用法是在工具栏中应该右对齐的项目之前添加一个可拉伸的空间,也可以在工具栏的开头和结尾添加可拉伸空间,以使所有工具栏项目居中。
wxToolBarToolBase* AddStretchableSpace()可向工具栏中加入一个可拉伸的空间区域。需要注意的是,在添加或插入工具项之后,需要调用bool Realize()才能在工具栏上显示该工具项。但删除工具项时无需调用此函数。
三、插入工具栏项
工具栏会按AddTool的调用顺序显示添加的工具项,而InsertTool则可以指定工具项在工具栏中的具体位置。
针对AddXxx的每一个方法,wxToolBar都提供了对应的InsertXxx方法,除增加了一个指示插入位置的pos参数外,其余参数相同。
例如,插入按纽工具项的Insert函数是:
wxToolBarToolBase *InsertTool(size_t pos,int toolid,
const wxString& label,
const wxBitmapBundle& bitmap,
const wxBitmapBundle& bmpDisabled = wxBitmapBundle(),
wxItemKind kind = wxITEM_NORMAL,
const wxString& shortHelp = wxEmptyString,
const wxString& longHelp = wxEmptyString,
wxObject *clientData =NULL)
四、删除工具栏项
有多种方式可以将一个工具项从工具栏中移除。bool DeleteTool(int toolid) 使您可以按ID删除一个工具项。bool DeleteToolByPos(size_t pos) 可按位置删除工具项。如果有需要,您也可以使用void ClearTools() 一次性删除所有工具项。
上面的删除函数会将工具项从工具栏中移除并删除工具项对象。如果想保留工具项对象,可以使用wxToolBarToolBase *RemoveTool(int toolid) 函数。
五、访问工具栏
有时为了操作工具项,您需要访问它的对象实例。wxToolBarToolBase *FindById(int toolid) 可根据ID获取工具项。如果工具项是一个控件,则使用wxControl *FindControl( int toolid ) 。也可以通过工具项在工具栏中的索引值访问,访问函数为wxToolBarToolBase *GetToolByPos(int pos) 。
在除wxGTK外的其他平台中,还可以通过鼠标位置获取工具项的引用,函数为wxToolBarToolBase *FindToolForPosition(wxCoord x,wxCoord y) 。
遍历工具栏需要知道工具项的总数,由size_t GetToolsCount()返回。
六、设置间隔与大小
工具项之间的距离可以通过void SetMargins(int x, int y) 自定义,其中:
x:左边距、右边距和工具栏间的间隔。
y:上边距、下边距和工具栏间的间隔。
该函数只影响在调用它之后添加的工具栏的间距。
您可以根据需要通过void SetToolBitmapSize(const wxSize& size) 改变工具项位图的默认大小。但通常不需要调用此函数,因为工具项总会自动以适应所使用位图的大小。此外。调用该函数会强制wxToolBar按指定大小缩放位图,而不是让wxBitmapBundle确定最合适的大小,这可能会导致外观不佳。若您确实调用了它,则必须在调用Realize之前。
下面的代码演示了使用此函数设置位图为32像素宽和高:
toolbar->SetToolBitmapSize(FromDIP(wxSize(32, 32)));
toolbar->AddTool(wxID_NEW, "New", wxBitmapBundle::FromXXX(...));
...
toolbar->Realize();
有时同一个方向可能有多个工具栏,工具栏之间的间隔通过void SetToolPacking(int packing) 设置。
七、事件处理
(一)事件处理函数
工具栏的主要作用是接受用户输入,触发相应事件,并通过wxWidgets的事件处理机制调用对应的处理例程,工具栏事件例程func的原型为:
void handlerFuncName(wxCommandEvent& event)
(二)事件类型
支持以下事件宏:
EVT_TOOL(id, func):鼠标单击工具栏按纽时触发。
EVT_MENU(id, func):鼠标单击工具栏按纽下拉菜单时触发。
EVT_TOOL_RANGE(id1, id2, func):EVT_TOOL的批量版。
EVT_MENU_RANGE(id1, id2, func):EVT_MENU的批量版。
EVT_TOOL_RCLICKED(id, func):鼠标右键单击触发
EVT_TOOL_RCLICKED_RANGE(id1, id2, func):EVT_TOOL_RCLICKED的批量版。
EVT_TOOL_ENTER:鼠标进出工具按纽时触发。当鼠标进入时,wxCommandEvent::GetSelection()返回工具项的ID,当鼠标离开时,wxCommandEvent::GetSelection()返回-1。
EVT_TOOL_DROPDOWN(id, func):点击弹出下拉菜单时触发,如果未设置该事件处理函数,则自动弹出wxToolBar::SetDropdownMenu()设置的菜单。
工具栏事件处理机制与菜单栏相同,因此,也可以对菜单项和工具栏按钮使用一个EVT_MENU()宏。事件处理程序函数采用wxCommandEvent参数。对于大多数事件宏,会传递工具的标识符,但对于EVT_TOOL_ENTER(),会传递工具栏窗口标识符,并从wxCommandEvent中检索工具标识符。这是因为当鼠标离开工具时,标识符可能是wxID_ANY,并且wxID_ANY不允许作为事件系统中的标识符。
对于wxControl类型的工具栏,其事件处理与对应控件的事件处理相同。
八、总结
示例基于静态绑定的方式演示菜单事件处理,事实上,您也可以采用动态绑定的方法。相关文档可参考《wxWidgets窗体:事件处理之动态绑定》一文。
2102

被折叠的 条评论
为什么被折叠?



