工具条/栏(tool bar)和状态条/栏(status bar)是构建友好GUI程序的通用标准,但它们并不是Windows API的标准部件,而是由应用程序框架(MFC)增加的一类控件。
CObject → CCmdTarget → CWnd → CControlBar → CToolBar / CStatusBar
<!--[if !vml]--><!--[endif]-->
<!--[if !vml]--><!--[endif]-->
<!--[if !vml]--><!--[endif]-->
BUTTON ID_FILE_NEW
BUTTON ID_FILE_OPEN
BUTTON ID_FILE_SAVE
BUTTON ID_EDIT_CUT
BUTTON ID_EDIT_COPY
BUTTON ID_EDIT_PASTE
BUTTON ID_FILE_PRINT
BUTTON ID_APP_ABOUT
<!--[if !supportLists]-->l <!--[endif]-->在VC项目工作区的资源视图页中展开“Student/Student.rc”中的“Toolbar”资源列表,双击IDR_MAINFRAME打开工具栏编辑器(见下图)
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]-->l <!--[endif]-->选择当前按钮:单击位于VS窗口中部的工具条编辑窗口上部工具条栏中的所需按钮;
<!--[if !supportLists]-->l <!--[endif]-->修改位图:对当前按钮,可以利用“图像”菜单、图像编辑器工具条和(位于属性窗口上部的)颜色窗口,在中部的图像编辑器窗口中绘制和修改当前按钮的位图;
<!--[if !supportLists]-->l <!--[endif]-->修改属性:在属性窗口中可以
<!--[if !supportLists]-->n <!--[endif]-->选择该按钮所对应的(菜单项)ID
<!--[if !supportLists]-->n <!--[endif]-->修改该按钮位图的宽和高
<!--[if !supportLists]-->n <!--[endif]-->键入/修改该按钮所对应的提示文本(/n后的为按钮的浮动提示文本)
<!--[if !supportLists]-->l <!--[endif]-->删除按钮:将按钮拖离工具条即可
<!--[if !supportLists]-->l <!--[endif]-->添加按钮:
<!--[if !supportLists]-->n <!--[endif]-->将工具条最右边的空白按钮拖到你想加入按钮的位置
<!--[if !supportLists]-->n <!--[endif]-->用“图像”菜单、图像编辑器工具条和颜色窗口来绘制按钮的位图(在空白按钮上绘图后,VS会自动在其右边添加一个新的空白按钮)
<!--[if !supportLists]-->n <!--[endif]-->在属性窗口中选择该按钮所对应的(菜单项)ID
<!--[if !supportLists]-->n <!--[endif]-->还可以修改该按钮位图的宽和高、键入/修改该按钮所对应的提示文本
<!--[if !supportLists]-->l <!--[endif]-->分组:左/右拖动按钮半个按钮宽度,可将其
<!--[if !supportLists]-->n <!--[endif]-->与右边/左边的按钮分开成不同的组
<!--[if !supportLists]-->n <!--[endif]-->与左边/右边的按钮合并成同一个组
<!--[if !vml]--><!--[endif]-->
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]-->① <!--[endif]-->在使用应用程序向导创建程序时,在“MFC 应用程序向导”对话框的“用户界面功能”页的“工具栏”选项中,没有选“标准停靠”单选钮,则需要自己加入工具条;
<!--[if !supportLists]-->② <!--[endif]-->或者原有的工具条不够用,需要加入第2个工具条;
<!--[if !supportLists]-->③ <!--[endif]-->或者在程序运行当中需要在多个工具条中切换;
<!--[if !supportLists]-->l <!--[endif]-->在项目工作区的“资源视图”页中的Toolbar资源表项上单击鼠标右键,在弹出的浮动菜单中选“插入Toolbar”菜单项,VS会自动创建一个ID为IDR_TOOLBAR1的空工具条
<!--[if !supportLists]-->l <!--[endif]-->可在该工具条中加入若干图形按钮(如Z、L、W)
<!--[if !supportLists]-->l <!--[endif]-->在属性窗口中修改工具条的ID(如IDR_MYTB),选择按钮对应的ID(如ID_NAME_ZS、ID_NAME_LS、ID_NAME_WW)
<!--[if !supportLists]-->l <!--[endif]-->创建新工具条资源
<!--[if !supportLists]-->l <!--[endif]-->打开头文件MainFrm.h,在CMainFrame类中加入工具条类CToolBar的对象m_ToolBar作为公共数据成员:(缺省的工具条对象为CToolBar m_wndToolBar;)
<!--[if !supportLists]-->l <!--[endif]-->在CMainFrame类中WM_CREATE消息响应函数OnCreate(若无该函数则创建它)中的return 0;语句之前加入下列代码:
CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |
if (!m_ToolBar.Create(this)) {// 创建工具条
return -1; // 创建失败
if (!m_ToolBar.LoadToolBar(IDR_MYTB)) { // 装入工具条
return -1; // 装入失败
m_ToolBar.SetBarStyle(m_ToolBar.GetBarStyle() | CBRS_GRIPPER | CBRS_TOOLTIPS |
<!--[if !supportLists]-->② <!--[endif]-->在框架窗口中加入多个工具条:
<!--[if !supportLists]-->l <!--[endif]-->创建新工具条资源
<!--[if !supportLists]-->l <!--[endif]-->打开头文件MainFrm.h,在CMainFrame类中加入工具条类CToolBar的对象m_ToolBar作为公共数据成员:
<!--[if !supportLists]-->l <!--[endif]-->在原有的OnCreate函数内加入似①的创建与装入工具条的代码,但要注意代码的顺序,且不需重复语句EnableDocking(CBRS_ALIGN_ANY); 参见下面代码的红色部分(其余部分为自动生成的缺省代码):
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
return -1; // 未能创建
if (!m_ToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |
return -1; // 未能创建
if (!m_wndStatusBar.Create(this) ||
return -1; // 未能创建
// TODO: 如果不需要工具栏可停靠,则删除这三行
return 0;
<!--[if !supportLists]-->③ <!--[endif]-->显示/隐藏/切换工具条:
<!--[if !supportLists]-->l <!--[endif]-->似②创建若干工具条资源
<!--[if !supportLists]-->l <!--[endif]-->在OnCreate函数内加入相应代码,来创建与装入工具条
<!--[if !supportLists]-->l <!--[endif]-->在这些代码后面,加上隐藏暂不显示的工具条的代码,如
ShowControlBar(&m_ToolBar, FALSE, FALSE);
void ShowControlBar( CControlBar* pBar, BOOL bShow, BOOL bDelay );
<!--[if !supportLists]-->l <!--[endif]-->在菜单资源中添加显示/隐藏/切换工具条的菜单项(如“视图/切换工具栏”ID_CHANGE_TOOL_BAR),在某一窗口派生类(如视图类CStudentView)中创建该菜单项的消息响应函数(如OnChangeToolBar),在该函数中隐藏/显示/切换工具条,例如:
CMainFrame *pFrmWnd = (CMainFrame*)GetTopLevelFrame();
pFrmWnd->ShowControlBar(&pFrmWnd->m_wndToolBar, FALSE, FALSE);
pFrmWnd->ShowControlBar(&pFrmWnd->m_ToolBar, TRUE, FALSE);
pFrmWnd->ShowControlBar(&pFrmWnd->m_ToolBar, FALSE, FALSE);
pFrmWnd->ShowControlBar(&pFrmWnd->m_wndToolBar, TRUE, FALSE);
void SetButtonInfo( int nIndex, UINT nID, UINT nStyle, int iImage );
<!--[if !supportLists]-->l <!--[endif]-->可在CStudenView类中设置一个整数型数据成员m_iAddNum (int m_iAddNum;)
<!--[if !supportLists]-->l <!--[endif]-->在类的构造函数中将该变量初始化为0 (m_iAddNum = 0;)
<!--[if !supportLists]-->l <!--[endif]-->在消息响应函数OnAdd中,将该变量加一 (m_iAddNum++;)
<!--[if !supportLists]-->l <!--[endif]-->在消息响应函数OnDel中,将该变量减一 (m_iAddNum--;)
<!--[if !supportLists]-->l <!--[endif]-->在“删除”菜单项的UI更新响应函数OnUpdateDel中,根据m_iAddNum的值设置“删除”按钮(和菜单项)的禁止与激活状态:
<!--[if !supportLists]-->l <!--[endif]-->在“添加”菜单项的UI更新响应函数OnUpdateAdd中,根据m_iAddNum的值设置“添加”按钮(和菜单项)的禁止与激活状态:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]-->l <!--[endif]-->可在CStudenView类中设置一个布尔型数据成员zs (bool zs;)
<!--[if !supportLists]-->l <!--[endif]-->在类的构造函数中将该变量初始化为假 (zs = false;)
<!--[if !supportLists]-->l <!--[endif]-->在消息响应函数OnNameZs中,切换该变量的真假 (zs = !zs;)
<!--[if !supportLists]-->l <!--[endif]-->在Z按钮(ID_NAME_ZS)UI更新响应函数OnUpdateNameZs中,根据zs的值来设置按钮是否按下:
<!--[if !vml]--><!--[endif]-->
缺省状态条在CMainFrame类中对应于保护型数据成员CStatusBar m_wndStatusBar; 在MainFrm.cpp文件的前面部分中有数组:
m_wndStatusBar.SetPaneText(0, L"Message line for first pane");
BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE );
<!--[if !supportLists]-->l <!--[endif]-->将CMainFrame类中的保护数据成员m_wndStatusBar改为公共的
<!--[if !supportLists]-->l <!--[endif]-->在头文件MainFrm.h中加入窗格ID的枚举变量。如
enum SBID {prompt, xName, xVal, yName, yVal};
<!--[if !supportLists]-->l <!--[endif]-->去掉原indicators数组中的三个状态指示窗格的ID,加入若干(n个)消息行窗格ID (ID_SEPARATOR),其中第1个(nIndex = 0)用于显示提示信息,其余的(n个)用作应用程序的数据显示。如
ID_SEPARATOR, // 提示 nIndex = 0
ID_SEPARATOR, // "x:" nIndex = 1
ID_SEPARATOR, // "y:" nIndex = 3
<!--[if !supportLists]-->l <!--[endif]-->在创建状态条的代码后(如在CMainFrame::OnCreate函数的尾部),用状态条的成员函数SetPaneInfo来设置每个窗格的ID、风格和宽度(单位似对话框,为1/4英文字母),其函数原型为
void SetPaneInfo( int nIndex, UINT nID, UINT nStyle, int cxWidth );
<!--[if !supportLists]-->n <!--[endif]-->SBPS_NOBORDERS 窗格周围无三维边框
<!--[if !supportLists]-->n <!--[endif]-->SBPS_POPOUT 窗格突出显示
<!--[if !supportLists]-->n <!--[endif]-->SBPS_DISABLED 不画文本
<!--[if !supportLists]-->n <!--[endif]-->SBPS_STRETCH 伸缩窗格以填满空间(每个状态条中只能有一个窗格可以被设置成伸缩的)
<!--[if !supportLists]-->n <!--[endif]-->SBPS_NORMAL 不伸缩、无边框、不凸显
<!--[if !supportLists]-->l <!--[endif]-->在应用程序中用函数SetPaneText动态修改窗格中的文本串。如
CMainFrame *pFrmWnd = (CMainFrame*)GetTopLevelFrame();
_itow_s(point.x, buf, 20, 10);
pFrmWnd->m_wndStatusBar.SetPaneText(pFrmWnd->xVal, buf);
_itow_s(point.y, buf, 20, 10);
pFrmWnd->m_wndStatusBar.SetPaneText(pFrmWnd->yVal, buf);
CView::OnMouseMove(nFlags, point);
<!--[if !vml]--><!--[endif]-->