zoukankan      html  css  js  c++  java
  • 在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类添加两个数据成员:

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

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

         然后实现如下函数:

    复制代码
        /*!
        *  rief 获取exe所在的文件夹。
        *
        *  param [in][out]strBinPath exe程序所在的文件夹。
        *   eturn 无。
        
    */
        
    void CMainFrame::GetOutputPath(string &strBinPath)
    {
        TCHAR szModulePath[_MAX_PATH];
        ::GetModuleFileName(NULL,szModulePath,_MAX_PATH);
        strBinPath 
    = szModulePath;
        strBinPath 
    = strBinPath.substr(0,strBinPath.rfind('\')+1);
    }
        
    /*!
        *  rief 解析系统配置文件,获取工具栏信息。
        *
        *  param [in][out]MyToolbar 工具栏信息。
        *   eturn 无。
        
    */
    void CMainFrame::ParseXml(ToolBar &MyToolbar)
    {
        
    string strBinPath;
        GetOutputPath(strBinPath);
        
    string strXmlPath = strBinPath + string(_T("SysConfig.xml"));
        m_SysSetting.OpenXml(strXmlPath);
      
        m_SysSetting.GetToolbarInfo(MyToolbar);
    }
        
    /*!
        *  rief 根据工具栏图片信息加载工具栏图像列表。
        *
        *  param [in]MyToolbar 工具栏信息。
        *   eturn 是否成功。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, 00, LR_DEFAULTCOLOR|LR_LOADFROMFILE);
            
    if (NULL==hBitmap)
            {
                
    return FALSE;
            }
            CBitmap        bmp;
            bmp.Attach(hBitmap);
            m_imgToobar.Add(
    &bmp, RGB(000));
            bmp.DeleteObject();
        }

        
    return TRUE;
    }

        
    /*!
        *  rief 设置工具栏按钮风格。
        *
        *  param [in]MyToolbar 工具栏信息。
        *   eturn 无。
        
    */
    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(
    "未能创建工具栏 ");
            
    return -1;      // 未能创建
        }

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

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

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

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

        
    return 0;
    }
    复制代码

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

      

    复制代码
        /*!
        *  rief 工具栏按钮响应事件。
        *
        *  param [in]nID 工具栏按钮ID。
        *   eturn 无。
        
    */
    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实现 多风格真彩色大图标工具栏按钮 (感谢万连文大侠提供)

  • 相关阅读:
    操作系统复习
    你不知道的JS(2)深入了解闭包
    剑指offer(66)机器人的运动范围
    剑指offer(65)矩阵中的路径
    剑指offer(64)滑动窗口中的最大值
    剑指offer(63)数据流中的中位数
    剑指offer(62)二叉搜索树的第K个节点
    剑指offer(61)序列化二叉树
    剑指offer(60)把二叉树打印成多行
    让 Laravel API 永远返回 JSON 格式响应!
  • 原文地址:https://www.cnblogs.com/lidabo/p/3651333.html
Copyright © 2011-2022 走看看