在MFC程序中使用XML文件配置工具栏

现在我发现使用Visual Studio的资源编辑器进行编辑资源有着诸多的不便:首先是任何资源的变动一般变动代码,不利于系统维护,其次Visual Studio的资源编辑器的本身的功能有限,也不利于界面美化,三是不利于人员分工,开发人员既要忙实现功能,又要忙准备好的界面素材。对界面实现文件配置化正是解决上面问题的好方法。这次我实现了使用XML文件配置工具栏。这里所谓配置就是工具栏的界面信息如工具栏标题、按钮图片、是否为分隔符都在XML文件保存,程序通过解析XML文件来获取工具栏信息来创建工具栏。这样一旦发现界面不合适可以随时修改配置文件,同时利于人员分工。

 

具体的做法如下:

 

1.       在工程的输出目录下有一个SysConfig.xml,作为系统配置文件。其中关于工具栏的配置部分如下:

复制代码
        < AppToolbar  valid ="1"  caption ="基础工具" >
             < ToolButton  file ="Add.bmp"   />
             < ToolButton  separator ="true"   />
             < ToolButton  file ="Benchmark.bmp"   />
             < ToolButton  file ="Comment.bmp"   />
             < ToolButton  file ="Convert.bmp"   />
             < ToolButton  file ="Delete.bmp"   />
             < ToolButton  file ="Exit.bmp"   />
         </ AppToolbar >
复制代码

       

简单解释一下上面的节点意义:valid表示工具栏是否有效,caption表示工具栏标题,file节点为工具栏按钮所贴图片,separator表示按钮是分隔符。

 

2.       通过解析XML文件获取工具栏信息来创建工具栏。首先在CMainFrame类添加两个数据成员:

复制代码
       /* *
    * \brief 工具栏对应的图像列表。
     */
    CImageList        m_imgToobar;

     /* *
    * \brief 系统配置文件解析器,具体看我上传的代码。
     */
    CXmlParse m_SysSetting;
复制代码

 

     然后实现如下函数:

 

复制代码
     /* !
    *  \brief 获取exe所在的文件夹。
    *
    *  \param [in][out]strBinPath exe程序所在的文件夹。
    *  \return 无。
     */
     void  CMainFrame::GetOutputPath( string   & strBinPath)
{
    TCHAR szModulePath[_MAX_PATH];
    ::GetModuleFileName(NULL,szModulePath,_MAX_PATH);
    strBinPath  =  szModulePath;
    strBinPath  =  strBinPath.substr( 0 ,strBinPath.rfind( ' \\ ' ) + 1 );
}
     /* !
    *  \brief 解析系统配置文件,获取工具栏信息。
    *
    *  \param [in][out]MyToolbar 工具栏信息。
    *  \return 无。
     */
void  CMainFrame::ParseXml(ToolBar  & MyToolbar)
{
     string  strBinPath;
    GetOutputPath(strBinPath);
     string  strXmlPath  =  strBinPath  +   string (_T( " SysConfig.xml " ));
    m_SysSetting.OpenXml(strXmlPath);
  
    m_SysSetting.GetToolbarInfo(MyToolbar);
}
     /* !
    *  \brief 根据工具栏图片信息加载工具栏图像列表。
    *
    *  \param [in]MyToolbar 工具栏信息。
    *  \return 是否成功。true为成功,false表示失败。
     */
BOOL CMainFrame::LoadImageList(ToolBar  & MyToolbar)
{
     //  获取按钮图片的个数
     int  nBmpNum  =  MyToolbar.m_MenuItemVec.size();
    HBITMAP        hBitmap                 =  NULL;
     //  打开所有位图,将其加进图像列表
     for ( int  i = 0 ; i < nBmpNum;  ++ i)
    {
         if  (MyToolbar.m_MenuItemVec[i].m_bIsSeparator)
        {
             continue ;
        }
         string  strBinPath;
        GetOutputPath(strBinPath);
         string  strBmpPath  =  strBinPath  +   string (_T( " Toolbar\\ " ));
        strBmpPath  =  strBmpPath  +     MyToolbar.m_MenuItemVec[i].m_strBmpName;
        hBitmap  =  (HBITMAP)LoadImage(AfxGetResourceHandle(),strBmpPath.c_str(), IMAGE_BITMAP,  0 ,  0 , LR_DEFAULTCOLOR | LR_LOADFROMFILE);
         if  (NULL == hBitmap)
        {
             return  FALSE;
        }
        CBitmap        bmp;
        bmp.Attach(hBitmap);
        m_imgToobar.Add( & bmp, RGB( 0 ,  0 ,  0 ));
        bmp.DeleteObject();
    }

     return  TRUE;
}

     /* !
    *  \brief 设置工具栏按钮风格。
    *
    *  \param [in]MyToolbar 工具栏信息。
    *  \return 无。
     */
BOOL CMainFrame::SetStyleToolbar(ToolBar  & MyToolbar)
{
    CToolBarCtrl &     tbc     =  m_wndToolBar.GetToolBarCtrl();
     //  删除之前的按钮
     while (tbc.DeleteButton( 0 ));
     //  设置当前图像列表
    tbc.SetImageList( & m_imgToobar);
     int         i             =   0 ;
     int         nBtnNum     =  MyToolbar.m_MenuItemVec.size();

    UINT nBtnID  =  SYS_COMMAND_BEGIN;
     int  nImgIndex  =   0 ;
     //  根据按钮属性逐个添加按钮
     for (i = 0 ; i < nBtnNum;  ++ i)
    {
         if  (MyToolbar.m_MenuItemVec[i].m_bIsSeparator)
        {
            TBBUTTON tb  =  { - 1 , 0 ,TBSTATE_ENABLED,TBSTYLE_SEP, 0 , 0 };
            tbc.AddButtons( 1 ,  & tb);
        }
         else
        {
            TBBUTTON tb  =  {nImgIndex,nBtnID,TBSTATE_ENABLED,TBSTYLE_BUTTON, 0 , 0 };
            tbc.AddButtons( 1 ,  & tb);
            nImgIndex ++ ;
            nBtnID ++ ;
        }
    
    }
     return  TRUE;
}

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)) */

     //  解析系统配置文件,获取位图信息
    ToolBar AppToolbar;
    ParseXml(AppToolbar);

     if ( ! m_wndToolBar.CreateEx( this , TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
         | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC))
    {
        TRACE0( " 未能创建工具栏\n " );
         return   - 1 ;       //  未能创建
    }

    m_wndToolBar.SetWindowText(AppToolbar.m_strCaption.c_str());

     //  创建图像列表
    m_imgToobar.Create( 32 ,  32 , ILC_COLOR32 | ILC_MASK,  0 ,  0 );
     if (LoadImageList(AppToolbar))
    {
         //  添加工具栏按钮
         SetStyleToolbar(AppToolbar);
    }
    
     //  设置工具栏按钮大小
    m_wndToolBar.SetSizes(CSize( 32 + 7 ,  32 + 6 ), CSize( 32 ,  32 ));

     if  ( ! m_wndStatusBar.Create( this )  ||
         ! m_wndStatusBar.SetIndicators(indicators,
           sizeof (indicators) / sizeof (UINT)))
    {
        TRACE0( " 未能创建状态栏\n " );
         return   - 1 ;       //  未能创建
    }

     //  TODO: 如果不需要工具栏可停靠,则删除这三行
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar( & m_wndToolBar);

     return   0 ;
}
复制代码

 

      为使工具栏处于有效状态,还得添加一个简单的消息处理函数,简单如下:

  

复制代码
     /* !
    *  \brief 工具栏按钮响应事件。
    *
    *  \param [in]nID 工具栏按钮ID。
    *  \return 无。
     */
void  CMainFrame::OnButton(UINT nID)
{
    switch  (nID)
   {
    //  SYS_COMMAND_BEGIN为工具栏按钮的起始ID值
    case  SYS_COMMAND_BEGIN:
       AfxMessageBox(_T( " 你单击的是第一个按钮 " ));
           break ;
    case  SYS_COMMAND_BEGIN + 1 :
       AfxMessageBox(_T( " 你单击的是第二个按钮 " ));
        break ;
    case  SYS_COMMAND_BEGIN + 2 :
       AfxMessageBox(_T( " 你单击的是第三个按钮 " ));
        break ;
    case  SYS_COMMAND_BEGIN + 3 :
       AfxMessageBox(_T( " 你单击的是第四个按钮 " ));
        break ;
    case  SYS_COMMAND_BEGIN + 4 :
       AfxMessageBox(_T( " 你单击的是第五个按钮 " ));
        break ;
    case  SYS_COMMAND_BEGIN + 5 :
       AfxMessageBox(_T( " 你单击的是第六个按钮 " ));
        break ;
    default :
        break ;
   }
}
复制代码

  

开发环境为Visual C++ 2005 + sp1,Win XP + sp3。程序效果图如下:

 

 

 

     工程源码已上传到联合程序开发网,链接为:

源码下载

 

参考文献:

 来源:http://www.cnblogs.com/clever101

1. MFC实现 多风格真彩色大图标工具栏按钮 (感谢万连文大侠提供)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值