32
第 6 第第第 第第第第第第第 6.1 第第 6.2 第第第 6.3 第第第 6.4 第第第第第第第第第

第 6 章菜单、工具栏和状态栏

  • Upload
    amil

  • View
    117

  • Download
    0

Embed Size (px)

DESCRIPTION

第 6 章菜单、工具栏和状态栏. 6.1 菜单 6.2 工具栏 6.3 状态栏 6.4 交互对象的动态更新. 图 6.1 File 菜单. 6.1 菜单. 对于菜单的显示都遵循下列一些规则: 若点击某菜单项会弹出一对话框,那么在该菜单项文本后有 “ …” 。 若某项菜单有子菜单,那么在该菜单项文本后有 “  ” 。 菜单项需要助记符,用括号将带下划线的字母括起来。助记符与 Alt 构成一个组合键,当按住 “ Alt ” 键不放,再敲击该字母时,对应的菜单项就会被选中。 - PowerPoint PPT Presentation

Citation preview

Page 1: 第 6 章菜单、工具栏和状态栏

第 6 章菜单、工具栏和状态栏

6.1 菜单 6.2 工具栏 6.3 状态栏 6.4 交互对象的动态更新

Page 2: 第 6 章菜单、工具栏和状态栏

6.1 菜单

对于菜单的显示都遵循下列一些规则: 若点击某菜单项会弹出一对话框,那

么在该菜单项文本后有“…”。 若某项菜单有子菜单,那么在该菜单

项文本后有“”。 菜单项需要助记符,用括号将带下划

线的字母括起来。助记符与 Alt 构成一个组合键,当按住“ Alt” 键不放,再敲击该字母时,对应的菜单项就会被选中。

若某项菜单需要快捷键的支持,则一般将其列在相应菜单项文本之后。任何时候按下快捷键,相应的菜单命令都会被执行。 图 6.1 File 菜单

Page 3: 第 6 章菜单、工具栏和状态栏

6.1 菜单6.1.1 用编辑器设计菜单 编辑菜单

在菜单的空位置上双击鼠标左键,则出现它的属性对话框,如图。

图 6.2 菜单编辑器

菜单的空位置

Page 4: 第 6 章菜单、工具栏和状态栏

6.1 菜单

图 6.3 菜单属性对话框

Page 5: 第 6 章菜单、工具栏和状态栏

6.1 菜单需要注意的是: 当菜单项的属性中选中了 Pop_up 时,对话框中 ID 、 Separator 和 Prom

pt 项无效。 增加新的菜单项后,用户可以用鼠标将菜单项拖到其他位置,而当菜单项位

置改变时,其属性并没改变。

菜单项被拖动的位置

图 6.4 拖动菜单项

图 6.5 添加的菜单项

Page 6: 第 6 章菜单、工具栏和状态栏

6.1 菜单 菜单命令的消息映射

[ 例 Ex_Mmenu]“ 成绩输入”菜单项的映射。(1) 选择“ View” 菜单“ ClassWizard” 命令项或按 Ctrl+w 快捷键,则出现 MFC ClassWizard 对话框,切换到 Message Maps 页面。(2) 从“ Class name” 列表中选择 CMainFrame ,在 IDs 列表中选择 ID_SCORE_IN ,然后在 Messages 框中选择 COMMAND 消息,如图。

图 6.6 消息的选择

Page 7: 第 6 章菜单、工具栏和状态栏

6.1 菜单(3) 单击 [Add Function] 按钮或双击 COMMAND 消息,输入成员函数的名称。如图。(4) 单击 [OK] 。选择新增加的成员函数,单击 [Edit Code] 按钮 ( 或直接在函数名双击鼠标左键 ) ,就可以在此成员函数中添加一些代码。例如:void CMainFrame::OnScoreIn() { // TODO: Add your command handler code here

AfxMessageBox(" 现在就输入成绩吗? ");}(5) 编译并运行。在应用程序的顶层菜单上,单击“成绩输入”菜单项或按Alt+S 组合键,如图。

图 6.7 添加成员函数对话框图 6.8 菜单命令执行的结果

Page 8: 第 6 章菜单、工具栏和状态栏

6.1 菜单6.1.2 使用键盘快捷键

(1) 先打开上例的项目工作区窗口中 Accelerator 的资源项,双击 IDR_MAINFRAME ,如图。

图 6.9 示例 Ex_Sdi 的加速键资源

最下端的空行

Page 9: 第 6 章菜单、工具栏和状态栏

6.1 菜单(2) 要建立一新的加速键,双击加速键列表的最下端的空行,如图,其中可设置的属性如表 (3) 在上述对话框中,选择在 Ex_Sdi 示例中添加的“成绩输入”菜单项的 ID 号 ID_SCORE_IN 作为要联用的加速键的 ID 号,单击 [Next Key Typed] ,按下 Ctrl+1 作为此加速键的键值。

图 6.10 “Accel Properities” 对话框

Page 10: 第 6 章菜单、工具栏和状态栏

6.1 菜单6.1.3 菜单的编程控制 菜单的基本操作

(1) 创建菜单CMenu 类的 CreateMenu 和 CreatePopupMenu 用来创建一个菜单或子菜单框架,原型如下:BOOL CreateMenu( ); // 产生一个空菜单BOOL CreatePopupMenu( ); // 产生一个空的弹出式子菜单(2) 装入菜单将菜单从资源装入应用程序中,需调用 CMenu 成员函数 LoadMenu ,或者用 SetMenu 对应用程序菜单进行重新设置。BOOL LoadMenu( LPCTSTR lpszResourceName );BOOL LoadMenu( UINT nIDResource ); (3) 添加菜单项菜单创建后,可调用 AppendMenu 或 InsertMenu 函数添加一些菜单项。 AppendMenu 是将菜单项添加在菜单的末尾处, InsertMenu 在菜单的指定位置处插入菜单项,并将后面的菜单项依次下移。BOOL AppendMenu( UINT nFlags, UINT nIDNewItem = 0,LPCTSTR lpszNewItem = NULL );BOOL AppendMenu( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0,

LPCTSTR lpszNewItem = NULL );BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

Page 11: 第 6 章菜单、工具栏和状态栏

6.1 菜单需要注意的是: nFlags 为 MF_BYPOSITION 时, nPosition 表示新菜单项要插入的具体位

置,为 0时表示第一个菜单项,为 -1 时,将菜单项添加菜单的末尾处。 nFlags 的标志中,可以用“ |”( 按位或 ) 来组合,例如 MF_CHECKED|MF

_STRING等。有些组合是不允许的,例如 MF_DISABLED 、 MF_ENABLED和 MF_GRAYED , MF_STRING、 MF_OWNERDRAW 、 MF_SEPARATOR和位图, MF_CHECKED 和 MF_UNCHECKED 都不能组合在一起。

当菜单项增加后,不管菜单依附的窗口是否改变,都应调用 CWnd::DrawMenuBar 来更新菜单。

Page 12: 第 6 章菜单、工具栏和状态栏

6.1 菜单(4)删除菜单项调用 DeleteMenu 函数可将指定的菜单项删除,需要注意的是:调用该函数后,不管菜单依附的窗口是否改变,都应调用 CWnd::DrawMenuBar使菜单更新。函数 DeleteMenu 的原型如下:BOOL DeleteMenu( UINT nPosition, UINT nFlags );nPosition 表示要删除的菜单项位置,它由 nFlags进行说明。若当 nFlags 为MF_BYCOMMAND 时, nPosition 表示菜单项的 ID 号,而当 nFlags 为 MF_BYPOSITION 时, nPosition 表示菜单项的位置 (第一个菜单项位置为 0) 。 (5)获取菜单项下面的三个 CMenu 成员函数分别获得菜单的项数、菜单项的 ID 号以及弹出式子菜单的句柄。UINT GetMenuItemCount( ) const;该函数用来获得菜单的菜单项数,调用失败后返回 -1 。UINT GetMenuItemID( int nPos ) const;该函数用来获得由 nPos指定菜单项位置 ( 以 0为基数 ) 的菜单项的标识号,若 nPos 是 SEPARATOR ,则返回 -1 。CMenu* GetSubMenu( int nPos ) const;该函数获得指定菜单的弹出式菜单的菜单句柄。该弹出式菜单位置由参数 nPos指定,开始的位置为 0。若菜单不存在,则创建一个临时的菜单指针。

Page 13: 第 6 章菜单、工具栏和状态栏

6.1 菜单 给系统菜单添加一个菜单项

[ 例 Ex_SysMenu] 向应用系统菜单中添加一个菜单项。(1) 打开一个单文档应用程序项目,若没有可按前面提及的方法进行创建。(2) 选择“ View” 菜单“ Resource Symbols…” 命令,如图。(3) 单击 [New] ,如图。在 Name 框中,可以指定一个用于菜单项的 ID 号。在 Value 框中,可以定义该 ID 的值,系统要求定义的 ID 值应大于 15(0X000F) 而小于 61440(0XF000) 。选择默认的 ID 值 101 ,单击 [OK] 按钮。

图 6.11 “Resource Symbols” 对话框

图 6.12 “New Symbol” 对话框

Page 14: 第 6 章菜单、工具栏和状态栏

6.1 菜单(4) 在 CMainFrame::OnCreate 函数体 ( 或自定义的函数 ) 中加入代码:int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){ ...

CMenu* pSysMenu = GetMenu(); // 获得主菜单句柄CMenu* pSubMenu = pSysMenu->GetSubMenu(1);// 获得第二个子菜单的句

柄CString StrMenuItem(" 新的菜单项 ");

pSubMenu->AppendMenu(MF_SEPARATOR); // 增加一水平分隔线 pSubMenu->AppendMenu(MF_STRING,ID_NEW_MENUITEM,StrMenuItem);

// 允许使用 ON_UPDATE_COMMAND_UI 或 ON_COMMAND 的菜单项m_bAutoMenuEnable = FALSE; // 使添加的菜单处于允许状态,默认为灰显

pSysMenu->EnableMenuItem(ID_NEW_MENUITEM,MF_BYCOMMAND|MF_ENABLED);

DrawMenuBar(); // 更新菜单return 0;

}(5)使用 ClassWizard处理 OnCommand 消息并检测用户菜单的 nID参数。BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) { // wParam 的低字节表示菜单、控件、加速键的命令 ID

if (LOWORD(wParam) == ID_NEW_MENUITEM) MessageBox("你选中了新的菜单项 ");return CFrameWnd::OnCommand(wParam, lParam);

}(6) 编译运行并测试。

Page 15: 第 6 章菜单、工具栏和状态栏

6.1 菜单6.1.4 使用快捷菜单

用资源编辑器和 MFC库的 CMenu::TrackPopupMenu 函数创建这样的菜单,CMenu::TrackPopupMenu 函数原型如下:BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL ); x 和 y 表示菜单的水平坐标和菜单的顶端的垂直坐标。 pWnd 表示弹出菜单的窗口。 lpRect 是一个 RECT结构或 CRect 对象指针,表示一个矩形区域,单击这个区域时,弹出菜单不消失。当 lpRect 为 NULL 时,若击在菜单外面,菜单立刻消失。

Page 16: 第 6 章菜单、工具栏和状态栏

6.1 菜单[ 例 Ex_Menu] 创建弹出菜单。(1) 选择“ Insert” 菜单“ Resource” 命令或按 Ctrl+R 快捷键,向应用程

序项目添加一个新的菜单资源 (默认的 ID 号为 IDR_MENU1) 。(2) 用菜单编辑器,为该菜单资源中的顶层菜单的第一项加一任意标题 (实际上

该标题无用 ) ,在此菜单项下依次添加如下表所示的菜单项。 (3) 将此菜单资源 ID 号改为 IDR_MYFLOATMENU。(4) 按 Ctrl+W 快捷键打开 ClassWizard ,将出现一对话框,询问是“选择一个已存在的类”,还是“创建一个新类”。选择“选择一个已存在的类”项并选定 CMainFrame 类。

Page 17: 第 6 章菜单、工具栏和状态栏

6.1 菜单(5) 在 CMainFrame 类中,选择上表中所列的菜单 ID ,双击 COMMAND 消息。这是仅为菜单 ID_MENU_SCOREIN 映射 COMMAND 消息,添加代码:void CMainFrame::OnMenuScorein() { AfxMessageBox(" 现在就输入成绩吗? "); }(6) 在 CMainFrame 类加入 WM_CONTEXTMENU消息处理函数,代码。void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint point) { CMenu menu;

menu.LoadMenu(IDR_MYFLOATMENU);menu.GetSubMenu(0)

->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this);}(7) 运行并测试。在应用程序的窗口客户区中单击鼠标右键,弹出如图菜单。 “成绩打印”菜单命令没有消息处理函数,因此它是灰显的,用户不能使用它们。若用户选中“成绩输入”菜单命令,则会执行相应的代码。

图 6.13 快捷菜单

Page 18: 第 6 章菜单、工具栏和状态栏

6.2 工具栏 6.2.1 使用工具栏编辑器

选择“ File”“Open Workspace” ,将单文档应用程序 Ex_Sdi 调入或重新创建。在项目工作区窗口中选择 ResourceView 标签,双击“ Toolbar” 项中的 IDR_MAINFRAME ,则工具栏编辑器出现在主界面的右边,如图。

图 6.14 工具栏编辑器窗口

空按钮

Page 19: 第 6 章菜单、工具栏和状态栏

6.2 工具栏(1) 创建一个新的工具栏按钮在新建的工具栏中,最右端总有一个空按钮,双击该按钮弹出其属性对话框,在 ID 框中输入其标识符名称,则在其右端又出现一个新的空按钮。单击该按钮,在编辑器的视窗内进行编辑,这个编辑就是绘制一个按钮位图。 (2)移动一个按钮在工具栏中移动一个按钮,用鼠标左键点中它并拖动至相应位置即可。如果用户拖动它离开工具栏位置,则此按钮从工具栏中消失。若在移动一个按钮的同时,按下 Ctrl 键,则在新位置复制一个按钮,新位置可以是同一个工具栏中的其他位置,也可以在不同的工具栏中。 (3)删除一个按钮前面已提到过,将选取中的按钮拖离工具栏,则该按钮就消失了。但若选中按钮后,单击 Delete 键并不能删除一个按钮,只是将按钮中的图形全部以背景色填充。 (4) 在工具栏中插入空格

如果按钮前没有任何空格,拖动该按钮向右移动并当覆盖相邻按钮的一半以上时,释放鼠标键,则此按钮前出现空格。

如果按钮前有空格而按钮后没有空格,拖动该按钮向左移动并当按钮的左边界接触到前面按钮时,释放鼠标键,则此按钮后将出现空格。

如果按钮前后均有空格,拖动该按钮向右移动并当接触到相邻按钮时,则此按钮前的空格保留,按钮后的空格消失。相反,拖动该按钮向左移动并当接触到前一个相邻按钮时,则此按钮前面的空格消失,后面的空格保留。

Page 20: 第 6 章菜单、工具栏和状态栏

6.2 工具栏(5) 工具栏按钮属性的设置双击某按钮弹出其属性对话框,如图。

图 6.15 工具栏按钮属性对话框

Page 21: 第 6 章菜单、工具栏和状态栏

6.2 工具栏6.2.2 工具栏和菜单相结合

[ 例 Ex_T&M] 将菜单项 ID_SCORE_IN 与工具按钮相结合。(1) 将前面的单文档应用程序 Ex_Sdi 打开;(2)利用工具栏编辑器设计一个工具按钮,如图;(3) 双击刚才设计的钮工具按钮图形,弹出该工具按钮的属性对话框;(4) 在工具按钮的属性对话框中,将工具按钮的 ID 号设为 ID_SCORE_IN ,在 Prompt 框内键入“向系统输入学生成绩 \n 成绩输入”;(5)重新编译并运行程序。在 Ex_Sdi 工具栏上,将鼠标指针移至刚才设计的工具按钮处,这时在状态栏上显示出“向系统输入学生成绩”信息,若稍等片刻后,还会弹出提示小窗口,显示出“成绩输入”字样。

图 6.16 工具栏按钮的设计

Page 22: 第 6 章菜单、工具栏和状态栏

6.3 状态栏 6.3.1 状态栏的定义

用 AppWizard 创建的 SDI 或 MDI 应用程序框架中,有一个静态的 indicator 数组,它是在 MainFrm.cpp 文件中定义的,被 MFC 用作状态栏的定义。

Static UINT indicators[]={

ID_SEPARATOR,ID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,

}

图 6.17 indicators 数组的定义

Page 23: 第 6 章菜单、工具栏和状态栏

6.3 状态栏6.3.2 状态栏的常用操作 增加和减少窗格状态栏中的窗格可以分为信息行窗格和指示器窗格两类。若在状态栏中增加一个信息行窗格,则只需在 indicators 数组中的适当位置中增加一个 ID_SEPARATOR 标识;若在状态栏中增加一个用户指示器窗格,则在 indicators 数组中的适当位置增加一个在字符串表中定义过的资源 ID ,其字符串的长度表示用户指示器窗格的大小。若状态栏减少一个窗格,其操作与增加相类似,只需减少 indicators 数组元素。

在状态栏上显示文本有三种办法可以在状态栏窗格显示文本信息:(1) 调用 CWnd::SetWindowText更新信息行窗格 ( 或窗格 0) 中的文本。由于状态栏也是一种窗口,故在使用时可直接调用。若状态栏变量为 m_wndStatusBar ,则 m_wndStatusBar. SetWindowText(“ 消息” )语句将在信息行窗格 ( 或窗格 0)内显示“消息”字样。(2)手动处理状态栏的 ON_UPDATE_COMMAND_UI更新消息,并在处理函数中调用 CCmdUI::SetText 函数。(3) 调用 CStatusBar::SetPaneText 函数更新任何窗格 (包括信息行窗格 )中的文本。此函数原型描述如下:BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE );

Page 24: 第 6 章菜单、工具栏和状态栏

6.3 状态栏[ 例 Ex_Status] 在状态栏的最右边两个窗格中显示出当前鼠标在窗口客户区的位置。(1) 将前面的单文档应用程序 Ex_Sdi 打开或重新创建;(2) 将项目工作区窗口切换到 ResourceView 页面,双击“ String Table” 项的“ String Table” 图标。在字符串列表的最后一行空项上双击鼠标左键,如图: (3) 该对话框中,可以指定相应的 ID 和字符串值,这里加入两个字符串资源 ID_LEFT 和 ID_RIGHT ,其字符的多少决定窗格的大小。如图:

图 6.17 字符串属性对话框添加的字符串

图 6.18 添加的字符串资源

Page 25: 第 6 章菜单、工具栏和状态栏

6.3 状态栏(4) 打开 MainFrm.cpp 文件,将原先的 indicators 数组修改如下:static UINT indicators[] ={ ID_SEPARATOR, // 第一个信息行窗格

ID_SEPARATOR, // 第二个信息行窗格ID_LEFT, // 第三个窗格ID_RIGHT, // 第四个窗格

};(5) 必须手工添加消息处理函数原型。打开 Ex_SdiView.h 文件,在 AFX_MSG内增加消息处理语句, ClassWizard 以后允许访问和编辑该代码。protected://{{AFX_MSG(CEx_SdiView)

afx_msg void OnUpdateXY(CCmdUI* pCmdUI);//}}AFX_MSGDECLARE_MESSAGE_MAP()(6) 打开 Ex_SdiView.cpp 文件,在其消息入口处添加消息映射函数:BEGIN_MESSAGE_MAP(CEx_SdiView, CView)

//{{AFX_MSG_MAP(CEx_SdiView)ON_UPDATE_COMMAND_UI(ID_LEFT, OnUpdateXY)ON_UPDATE_COMMAND_UI(ID_RIGHT, OnUpdateXY)//}}AFX_MSG_MAP

Page 26: 第 6 章菜单、工具栏和状态栏

6.3 状态栏(7) 增加修改状态栏指示器的消息映射函数代码,状态栏的窗格需要更新时,

应用程序框架自动调用此函数。void CEx_SdiView::OnUpdateXY(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); // 使窗格文本能被更新 }

(8) 用 ClassWizard 在 CEx_SdiView 类中加入 WM_MOUSEMOVE( 鼠标移动 )消息处理函数,并添加下列代码。该函数先获得状态栏对象的指针,然后调用 SetPaneText 函数更新第三和第四窗格中的文本。void CEx_SdiView::OnMouseMove(UINT nFlags, CPoint point) { CString str;

CMainFrame* pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd; CStatusBar* pStatus=&pFrame->m_wndStatusBar;

if (pStatus) { str.Format("X=%d",point.x);// 格式化文本

pStatus->SetPaneText(2,str);str.Format("Y=%d",point.y);pStatus->SetPaneText(3,str);

}CView::OnMouseMove(nFlags, point);

}

Page 27: 第 6 章菜单、工具栏和状态栏

6.3 状态栏(9) 将 MainFrm.h 文件中的受保护变量m_wndStatusBar 变成公共变量。(10) 在 Ex_SdiView.cpp 文件的开始处增加下列语句:

#include “MainFrm.h”(11) 编译并运行,如图。

图 6.19 鼠标的位置显示在状态栏上

Page 28: 第 6 章菜单、工具栏和状态栏

6.3 状态栏 改变状态栏的风格

在 MFC 的 CStatusBar 类中,有两个成员函数可以改变状态栏风格,它们是:void SetPaneInfo( int nIndex, UINT nID, UINT nStyle, int cxWidth );void SetPaneStyle( int nIndex, UINT nStyle ); 参数 nIndex 表示要设置的状态栏窗格的索引, nID 用来为状态栏窗格指定新的 ID , cxWidth 表示窗格的像素宽度, nStyle 表示窗格的风格类型,用来指定窗格的外观,例如 SBPS_POPOUT 表示窗格是凸起来的,见表。

Page 29: 第 6 章菜单、工具栏和状态栏

6.4 交互对象的动态更新 为能使交互对象动态更新, MFC通过 ClassWizard 直接映射交互对象的更新命令消息来实现。自动将用户交互对象的 ID 号与 ON_UPDATE_COMMAND_UI宏相连接并产生处理更新消息的相应函数。例如代码:void CEx_SdiView::OnUpdateXY(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); // 使窗格文本能被更新}OnUpdateXY就是映射更新命令消息的消息函数。此消息处理函数只有一个参数,它是指向 CCmdUI 对象的指针。 CCmdUI 类仅用于 ON_UPDATE_COMMAND_UI处理函数,它的成员函数将对菜单项、工具按钮等用户交互对象起作用,如表。

Page 30: 第 6 章菜单、工具栏和状态栏

6.4 交互对象的动态更新[例 Ex_T&Mitem]菜单项和工具按钮的更新。(1) 将上例的单文档应用程序项目 Ex_Sdi 调入或重新创建。(2) 将项目工作区窗口切换到 ResourceView 页面,选中 Toolbar 资源 IDR_MAINFRAME ,然后按下 Ctrl 键不放,在资源 IDR_MAINFRAME 上单击鼠标左击后向下拖一下,这时该工具条资源就被复制,新的资源号为 IDR_MAINFRAME1 ,将其改为 IDR_NEWBAR 。(3) 打开 MainFrm.h 文件,在 CMainFrame 类中声明一个 CToolBar 类变量m_wndNewBar 。

Page 31: 第 6 章菜单、工具栏和状态栏

6.4 交互对象的动态更新(4) 在 CMainFrame::OnCreate 中添加下列代码: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) ||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)){ TRACE0("Failed to create toolbar\n");

return -1; // fail to create }if (!m_wndNewBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||!m_wndNewBar.LoadToolBar(IDR_NEWBAR)){ TRACE0("Failed to create newbar\n");

return -1; // fail to create }……m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);m_wndNewBar.EnableDocking(CBRS_ALIGN_ANY);EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_wndToolBar);DockControlBar(&m_wndNewBar);……return 0;

}

Page 32: 第 6 章菜单、工具栏和状态栏

6.4 交互对象的动态更新(5) 打开菜单资源 IDR_MAINFRAME ,在“查看”菜单下添加一个菜单项“新

工具栏 (&N)” , ID 号设定为 ID_VIEW_NEWBAR 。(6) 打开 Toolbar 资源 IDR_MAINFRAME ,将上例新增的工具按钮同 ID_VIEW

_NEWBAR 菜单关联起来。(7) 为 CMainFrame 类添加一个 BOOL 型的成员变量m_bNewBar 。(8) 用 ClassWizard 在 CMainFrame 类中添加菜单 ID_VIEW_NEWBAR 的 COM

MAND 和 UPDATE_COMMAND_UI两个消息处理函数,并添加下列代码:void CMainFrame::OnViewNewbar() { m_bNewBar = !m_bNewBar;

ShowControlBar( &m_wndNewBar, m_bNewBar, FALSE);}void CMainFrame::OnUpdateViewNewbar(CCmdUI* pCmdUI) { m_bNewBar = m_wndNewBar.IsWindowVisible();

pCmdUI ->SetCheck(m_bNewBar);}

(9) 编译运行并测试。打开“查看”菜单,可以看到“新工具栏”菜单前面有一个“√”,同时有一个工具按钮被选中,单击该工具按钮或选择“新工具栏”菜单,则新创建的工具栏不见,同时这个工具按钮恢复原状,而“新工具栏”菜单前面没有任何标记。若将代码中的 SetCheck改为 SetRadio ,则“√”变成了“•”,这就是交互对象的更新效果。