1.3 工具栏应用实例

工具栏是应用程序界面的重要组成元素之一,它包含了一组命令按钮,用于执行某些菜单项的功能。通常情况下,将应用程序中常用的功能放置在工具栏中,这样可以方便用户操作,省去了在级联菜单中层层查找菜单项的困扰。在MFC类库中,CToolBar类封装了工具栏的基本功能,在本节中,将详细介绍利用CToolBar类设计各种工具栏。

工具栏在开发应用程序时经常用到,本节将介绍几种特色工具栏的实现方法。

实例007 带图标的工具栏

这是一个可以启发思维的实例

实例位置:光盘\mingrisoft\01\007

实例说明

默认情况下,MFC中提供的工具栏只能显示简单的图像。本实例实现了一个带有图标的工具栏按钮,效果如图1.8所示。

图1.8 带图标的工具栏

技术要点

工具栏CToolBar提供了一个GetToolBarCtrl方法,用于获得一个CToolBarCtrl对象,该对象提供了一个SetImageList方法,用于设置与工具栏关联的图像列表控件。只要在程序中创建一个图像列表,并向图像列表中添加图标,将其与工具栏关联,那么工具栏按钮就会显示出图像。

实现过程

(1)新建一个文档/视图结构的应用程序。

(2)在框架类中定义一个CImageList对象m_Imagelist。

(3)在框架类的OnCreate方法中创建图像列表,并向图像列表中添加图标。创建工具栏,将工具栏与图像列表关联,设置工具栏按钮的大小,代码如下:

        int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
        {
          if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
          //创建图像列表,向图像列表中添加图标
          m_Imagelist.Create(32,32,ILC_COLOR24|ILC_MASK,0,1);
          for (int i=0;i<9;i++)
          {
            m_Imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON1+i)); //加载图标资源
          }
          //创建工具栏
          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
          }
          m_wndToolBar.GetToolBarCtrl().SetImageList(&m_Imagelist); //管理图像列表
          m_wndToolBar.GetToolBarCtrl().SetButtonSize(CSize(40,40)); //设置按钮大小
          m_wndToolBar.GetToolBarCtrl().SetBitmapSize(CSize(30,30)); //设置图像大小
          if (!m_wndStatusBar.Create(this) ||
            !m_wndStatusBar.SetIndicators(indicators,
        sizeof(indicators)/sizeof(UINT)))
          {
            TRACE0("Failed to create status bar\n");
            return-1;     //fail to create
          }
          m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
          EnableDocking(CBRS_ALIGN_ANY);
          DockControlBar(&m_wndToolBar);
          return 0;
        }

举一反三

根据本实例,读者可以:

实现具有热点效果的工具栏。

实例008 带下拉菜单的工具栏

本实例可以美化界面、简化操作

实例位置:光盘\mingrisoft\01\08

实例说明

本实例是对工具栏功能的扩充,可以将工具栏上按钮的并列项以菜单的形式显示,方便用户操作。运行程序,单击工具栏按钮旁边的下三角按钮,将弹出一个下拉菜单,如图1.9所示。

图1.9带下拉菜单的工具栏

技术要点

下三角按钮是通过CToolBar类的SetButtonStyle方法和CToolBarCtrl类的SetExtendedStyle方法实现的。

SetButtonStyle方法用来设置工具栏按钮的风格,语法如下:

void SetButtonStyle( int nIndex, UINT nStyle );

参数说明:

● nIndex:按钮的索引。

● nStyle:按钮的风格。可以有以下取值。

■ TBBS_BUTTON:标准按钮。

■ TBBS_SEPARATOR:分隔线。

■ TBBS_CHECKBOX:复选风格。

■ TBBS_GROUP:按钮组。

■ TBBS_CHECKGROUP:复选按钮组。

SetExtendedStyle方法用于设置工具栏控件的扩展风格,语法如下:

DWORD SetExtendedStyle( DWORD dwExStyle ) const;

参数说明:

● dwExStyle:系统定义的工具栏控件风格,取值TBSTYLE_EX_DRAWDDARROWS,可以实现下三角按钮功能。

实现过程

(1)新建一个MFC的单文档结构应用程序,命名为ToolbarWithMenu。

(2)在工程中添加Menu资源,设置ID属性为IDR_MENU1,为菜单添加两个子菜单项。

(3)主要程序代码如下:

        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;
          }
          if (!m_wndStatusBar.Create(this) ||
            !m_wndStatusBar.SetIndicators(indicators,
                sizeof(indicators)/sizeof(UINT)))
          {
            TRACE0("Failed to create status bar\n");
            return -1;
          }
          m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
          EnableDocking(CBRS_ALIGN_ANY);
          DockControlBar(&m_wndToolBar);
          m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS); //设置工具栏具有下拉按钮
        //获得添加下拉按钮的工具栏打开按钮风格
          DWORD dwStyle= m_wndToolBar.GetButtonStyle(m_wndToolBar.CommandToIndex(ID_FILE_OPEN));
          dwStyle|=TBSTYLE_DROPDOWN;                                   //添加下拉按钮风格
          m_wndToolBar.SetButtonStyle(m_wndToolBar.CommandToIndex(ID_FILE_OPEN),
          dwStyle);    //设置下拉按钮风格
          return 0;
        }
        void CMainFrame::OnToolbarDropdown(NMTOOLBAR*pnmh,LRESULT*plr)  //按下下拉按钮
        {
          CWnd*pWnd;
          switch(pnmh->iItem)
          {
          case ID_FILE_OPEN:                                       //如果是工具栏打开按钮
            pWnd=&m_wndToolBar;                                   //获得工具栏窗口指针
            break;
          default:
            return;
          }
          CMenu menu;
          menu.LoadMenu(IDR_MENU1);                               //加载菜单资源
          CMenu*pPopup=menu.GetSubMenu(0);                        //获得子菜单
          ASSERT(pPopup);
          CRect rc;
          pWnd->SendMessage(TB_GETRECT,pnmh->iItem,(LPARAM)&rc);  //获得区域
          pWnd->ClientToScreen(&rc);                              //转换为屏幕坐标系区域
          pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,rc.left
                  ,rc.bottom,this,&rc);                           //显示弹出菜单
        }
        void CMainFrame::OnSubmenu()                               //菜单项单击时间
        {
          AfxMessageBox("你按下的是子菜单");                      //弹出消息提示框
        }
        void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint point)
        {
          CMenu menu;
          menu.LoadMenu(IDR_LMENU);                               //加载菜单资源
          CMenu*pPopup=menu.GetSubMenu(0);                        //获得子菜单
          pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,point.x,point.y,
          this,NULL);                                             //显示弹出菜单
        }

举一反三

根据本实例,读者可以:

开发右击客户区弹出菜单程序;

实现右击工具栏弹出菜单。

实例009 可调整按钮位置的工具栏

本实例可以美化界面、简化操作

实例位置:光盘\mingrisoft\01\09

实例说明

本实例实现了工具栏上两个按钮互换位置的功能。运行程序,选择菜单“查看”/“改变按钮位置”,程序会将“新建”按钮和“保存”按钮进行位置调换。调换前、后的效果分别如图1.10和图1.11所示。

图1.10 调换前

图1.11 调换后

技术要点

本实例通过CToolBar类的SetButtonInfo方法实现,SetButtonInfo方法用来设置工具栏按钮的相关信息,语法如下:

void SetButtonInfo( int nIndex, UINT nID, UINT nStyle, int iImage );

参数说明:

● nIndex:工具栏上按钮的位置。

● nID:工具栏按钮在工程中的资源ID值。

● nStyle:工具栏按钮的风格。

● iImage:工具栏按钮的图片索引值。

实现过程

(1)新建名为ToolbarAjustBtn的单文档MFC工程。

(2)修改Menu资源IDR_MAINFRAME,在菜单“查看”下新建子菜单,设置ID属性为ID_VIEW,设置Caption属性为“改变按钮位置”。

(3)主要程序代码。

菜单ID_VIEW的实现函数,实现调用MoveButton函数完成工具栏按钮的调整,代码如下:

        void CMainFrame::OnView()
        {
          this->MoveButton(0,2);                        //调用MoveButton函数调整工具栏按钮位置
        }

函数MoveButton实现工具栏上不同位置的按钮相互调换,代码如下:

        void CMainFrame::MoveButton(int oldpos,int newpos)
        {
          UINT newID,oldID;
          newID=m_wndToolBar.GetItemID(newpos);               //获得工具栏按钮ID
          oldID=m_wndToolBar.GetItemID(oldpos);               //获得工具栏按钮ID
          m_wndToolBar.SetButtonInfo(oldpos,newID,0,newpos);  //设置工具栏按钮信息
          m_wndToolBar.SetButtonInfo(newpos,oldID,0,oldpos);  //设置工具栏按钮信息
        }

举一反三

根据本实例,读者可以:

控制工具栏按钮的显示。

实例010 动态设置是否显示工具带栏按钮文本

本实例可以美化界面、简化操作

实例位置:光盘\mingrisoft\01\010

实例说明

工具栏中的按钮并不一定是都显示按钮文本的,用户可以根据当前的操作随时变化,这样可以提高程序的应用性。本实例根据用户的操作来调整工具栏按钮文本的显示。程序首先创建一个新的工具栏,然后根据数据库中的数据来决定哪个工具栏按钮可以显示。工具栏转换前如图1.12所示,转换后如图1.13所示。

图1.12 不显示工具栏按钮文本

图1.13 显示工具栏按钮文本

技术要点

本实例中涉及创建工具栏、设置工具栏高度等技术。在程序中可以使用CToolBar来定义一个工具栏对象,通过GetToolBarCtrl方法来获取CToolBarCtrl类对象。通过CToolBarCtrl类对象可以关联图像列表。要设置工具栏按钮高度可以通过SetHeight方法来实现,语法如下:

void SetHeight( int cyHeight );

参数说明:

● cyHeight:要设置的工具栏高度。

实现过程

(1)新建一个基于对话框的应用程序。

(2)在工程中导入8个图标资源,并向对话框中添加一个按钮控件。

(3)在对话框的头文件中声明变量,代码如下:

            CToolBar       m_ToolBar;         //工具栏对象
            CimageList     m_ImageList;       //列表视图对象
            BOOL           m_bText;           //是否显示按钮文本

(4)在对话框初始化时创建工具栏,代码如下:

        BOOL CToolTipDlg::OnInitDialog()
        {
            CDialog::OnInitDialog();
            // …系统代码省略
            //创建图像列表
            m_ImageList.Create(16,16,ILC_COLOR24|ILC_MASK,1,1);
            //向图像列表中添加图标
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON3));
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON4));
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON5));
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON6));
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON7));
            m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON8));
            UINT array[11];
            for(int i=0;i<11;i++)
            {
                if(i==3 || i==7 || i==9)
                      array[i] = ID_SEPARATOR; //第4、8、10个按钮为分隔条
                else
                      array[i] = i+1001;
            }
            CString str[]={"新建","打开","保存","","剪切","复制","粘贴","","打印","","帮助"};
            //创建工具栏
            m_ToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD | WS_VISIBLE | CBRS_TOP
                | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_SIZE_DYNAMIC | CBRS_BORDER_TOP);
            m_ToolBar.SetButtons(array,11);                               //设置工具栏按钮
            for(i=0;i<11;i++)
            {
                m_ToolBar.SetButtonText(i,str[i]);                        //设置工具栏按钮文本
            }
            m_ToolBar.GetToolBarCtrl().SetImageList(&m_ImageList);        //关联图像列表
            m_ToolBar.SetSizes(CSize(24,24),CSize(16,16));                //设置按钮和图标的大小
            RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
            m_bText = FALSE;
            return TRUE;
        }

(5)添加UpdateToolBar函数,该函数用于设置是否显示工具栏按钮文本,代码如下:

        void CToolTipDlg::UpdateToolBar(BOOL bUpdate)
        {
            if(bUpdate)
            {
                m_ToolBar.SetSizes(CSize(32,32),CSize(16,16)); //设置按钮和图标的大小
                m_ToolBar.SetHeight(36);                 //设置工具栏高度
                RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
            }
            else
            {
                m_ToolBar.SetSizes(CSize(24,24),CSize(16,16)); //设置按钮和图标的大小
                  m_ToolBar.SetHeight(28);                 //设置工具栏高度
                  RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
        }
        }

(6)处理“转换”按钮的单击事件,控制工具栏按钮是否显示,代码如下:

        void CToolTipDlg::OnButtonupdate()
        {
        m_bText = !m_bText;
        UpdateToolBar(m_bText);
        }

举一反三

根据本实例,读者可以:

根据需要设置工具栏按钮是否可用。

实例011 具有提示功能的工具栏

这是一个可以提高分析能力的实例

实例位置:光盘\mingrisoft\01\011

实例说明

在文档/视图结构的应用程序中,默认情况下,当鼠标在工具栏按钮上停留时,会出现一个工具提示条。运行本实例,将鼠标停留在工具栏的某一个按钮上,即可看到该工具按钮的提示信息,效果如图1.14所示。

图1.14 具有提示功能的工具栏

技术要点

使工具栏具有提示功能,需要同时具备两个条件。一是工具栏具有CBRS_TOOLTIPS风格,二是工具栏的父窗口需要处理TTN_NEEDTEXT通知消息。在MFC类库中,CFrameWnd默认处理了TTN_NEEDTEXT通知消息,因此,在文档/视图结构的应用程序中,只要工具栏具有CBRS_TOOLTIPS风格,就能够显示提示信息。

如果在对话框中添加TTN_NEEDTEXT通知消息,需要在消息映射部分添加如下代码:

ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify)

其中,OnToolTipNotify是处理TTN_NEEDTEXT消息的函数,函数原型如下:

OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult);

参数说明:

● id:是发送消息的控件ID,但此处没有用,因为控件ID可以来自于pNMHDR。

● pNMHDR:是一个NMHDR结构指针(实际应该是NMTTDISPINFO结构指针),NMHDR结构记录了发送消息的控件ID、句柄等信息。

● pResult:表示结果代码指针,TTN_NEEDTEXT消息可以忽略该参数。

实现过程

(1)新建一个基于对话框的应用程序。

(2)在对话框类中定义一个CToolBar变量m_wndToolBar。在工作区的资源视图中创建一个工具栏资源,如图1.15所示。

图1.15 工具栏资源设计

(3)在对话框的OnInitDialog方法中创建工具栏,代码如下:

          //创建工具栏
          if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
            | CBRS_GRIPPER | CBRS_TOOLTIPS |CBRS_SIZE_DYNAMIC|CBRS_BORDER_TOP ) ||
            !m_wndToolBar.LoadToolBar(IDR_TOOLBAR1))
          {
            TRACE0("Failed to create toolbar\n");
            return-1;     //fail to create
          }
          //设置图像和按钮的大小,以适合演示按钮文本
          m_wndToolBar.GetToolBarCtrl().SetBitmapSize(CSize(16,16)); //设置显示图像大小
          m_wndToolBar.GetToolBarCtrl().SetButtonSize(CSize(32,32)); //设置工具栏按钮大小
          //设置按钮文本
          m_wndToolBar.SetButtonText(0,"新建");
          m_wndToolBar.SetButtonText(1,"打开");
          m_wndToolBar.SetButtonText(2,"保存");
          m_wndToolBar.SetButtonText(4,"剪切");
          m_wndToolBar.SetButtonText(5,"复制");
          m_wndToolBar.SetButtonText(6,"粘贴");
          m_wndToolBar.SetButtonText(8,"打印");
          m_wndToolBar.SetButtonText(10,"帮助");

(4)在对话框的消息映射部分添加TTN_NEEDTEXT消息映射宏。

ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify)

(5)向对话框中添加OnToolTipNotify方法,代码如下:

        BOOL CToolHintDlg::OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
        {
            TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
            UINT nID=pNMHDR->idFrom;                                    //获取工具栏按钮ID
            int index=m_wndToolBar.GetToolBarCtrl().CommandToIndex(nID); //根据ID获取按钮索引
            m_wndToolBar.GetButtonText(index,m_ToolText);              //获取按钮文本
            pTTT->lpszText=m_ToolText.GetBuffer(0);                    //设置显示的提示信息
            pTTT->hinst = AfxGetResourceHandle();
            return(TRUE);
        }

举一反三

根据本实例,读者可以:

实现具有提示功能的各种控件。