现在我发现使用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实现 多风格真彩色大图标工具栏按钮 (感谢万连文大侠提供)

在MFC程序中使用XML文件配置工具栏的更多相关文章

  1. 在应用程序中使用Xml文件

    用于操作Xml的文档主要有XmlNode.XmlDocument.XmlComment.XmlElement.XmlAttribute.XmlText.XmlNodeList 下面用一段代码来具体说明 ...

  2. maven中pom.xml文件配置

    <properties>                <spring.version>4.3.18.RELEASE</spring.version>        ...

  3. Struts框架中struts-config.xml文件配置小结

    弄清楚struts-config.xml中各项元素的作用,对于我们构建web项目有莫大的好处.<struts-config>是struts的根元素,它主要有8个子元素,DTD定义 如下: ...

  4. maven构建SSM框架中pom.xml文件配置

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  5. Java程序中的Log文件配置

    log4j.properties文件 log4j.rootLogger=info,stdout,logfile #stdout log4j.appender.stdout=org.apache.log ...

  6. Spring框架入门之基于xml文件配置bean详解

    关于Spring中基于xml文件配置bean的详细总结(spring 4.1.0) 一.Spring中的依赖注入方式介绍 依赖注入有三种方式 属性注入 构造方法注入 工厂方法注入(很少使用,不推荐,本 ...

  7. c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程

    c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...

  8. web.xml 文件配置01

    web.xml 文件配置01   前言:一般的web工程中都会用到web.xml,方便开发web工程.web.xml主要用来配置Filter.Listener.Servlet等.但是要说明的是web. ...

  9. Struts2 web.xml文件配置

    在导入了项目需要使用的核心jar包之后需要在web.xml中配置Struts. 1. Struts2的知识点普及: Struts2共有5类配置文件,分别罗列如下: 1), Web.xml; 在没有使用 ...

随机推荐

  1. sass玩转颜色总结笔记

    变量: $color:#f00; 1.变浅和加深颜色,sass使用HSL标准来变浅或加深颜色 lighten($color,10%); darken($color,30%);             ...

  2. Linux命令: ln

    每天一个linux命令(35):ln 命令 实例1:给文件创建软链接 命令: ln -s log2013.log link2013 输出: [root@localhost test]# ll -rw- ...

  3. 简单字符串处理 hdu2532 Engine

    本来可以把这篇文章放入上一篇文章里,不过做这个题花了一点时间,也有一点收获,同时觉得网上的这个题目可供参考的文章有些少,那么就单独成篇吧. 首先分析下题目思路: 这个题目是个模拟题,步骤也很清晰. 首 ...

  4. Python字符串原理剖析------万恶的+号

    字符串原理剖析pyc文件,执行python代码时,如果导入了其他的.py文件,那么执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器变异之后产生的字节码 PS:代码经过编译可 ...

  5. HDOJ 4007 Dave【最大覆盖集】

    Dave Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submis ...

  6. fg、bg、jobs、&、nohup、ctrl + z命令

    fg.bg.jobs.&.nohup.ctrl + z命令 一.& 加在一个命令的最后,可以把这个命令放到后台执行,如gftp &, 二.ctrl + z 可以将一个正在前台执 ...

  7. BNU Box of Bricks

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=1596 这个题一开始以为要求最少移动次数,把我吓到了,原来只要求最少移动几个方块就行了..这一下就变简 ...

  8. 如何在Eclipse配置Tomcat服务器

    链接地址:http://jingyan.baidu.com/article/3065b3b6efa9d7becff8a4c6.html 要想在Eclipse运行jsp文件,首先需要指定对应的服务器,即 ...

  9. UVa 11045 My T-shirt suits me / 二分图

    二分图建图 判断是否是完全匹配就行 最大流也行 #include <cstdio> #include <cstring> const int MAX = 300; int a[ ...

  10. 利用Ihttpmodel实现网站缓存,解决Server.Transfer 直接输出HTML源代码的问题

    今天在用.NET利用IHttpModel实现网站静态缓存的时候,不知道最后为什么用 Server.Transfer(html)的时候结果输出的是HTML的源代码. 贴上源代码 using System ...