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

时间: 2024-10-02 17:18:17

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

javaweb-springmvc项目中springmvc.xml文件配置错误?

问题描述 springmvc项目中springmvc.xml文件配置错误? org.springframework.beans.factory. BeanCreationException: Error creating bean with name 'houseChangeInfoController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.facto

web xml-web项目中xml 文件配置错误,求大神们指教

问题描述 web项目中xml 文件配置错误,求大神们指教 源码是别人的,我导入户就现身错误 HTMLManager/html/* 下划线的地方是 /html/* 401/401.jsp 下划线的地方是 .jsp 怎么改呢. 解决方案 你能把问题具体化吗?

Android系统中AndroidManifest.xml文件解析

一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它位于整 个项目的根目录,描述了package中暴露的组件(activities, services, 等等),他们各自的实现类,各种 能被处理的数据和启动位置. 除了能声明程序中的Activities, ContentProviders, Services, 和Intent Receivers,还能指定permissions和instrumentation(安全控制和测

在非MFC程序中引用CString

CString在当今软件设计界里还是小有名气的,说它是MFC中使用的最多的类一点也不过,然而在使用sdk编windows程序的时候,确不能利用CString类,只能用sdk的运行时库,比如strlen,strcpy,strstr等等,本文讨论的是在非mfc程序中使用CString类的方法,算是个引子,如果有更好的实现方法,欢迎大家讨论. 为了使用CString类,首先源文件必须是以cpp结尾的,这是因为vc默认对不同的扩展名采用不同的编译方法和错误检查,mfc的支持文件Afx.h只有由cpp为扩

treeview-MFC中 解析XML文件,并用tree control 显示,如何进行对xml文件的增删改查?

问题描述 MFC中 解析XML文件,并用tree control 显示,如何进行对xml文件的增删改查? 如题,我利用tree control 显示了一个xml文件,然而不知道如何进行修改数据,就是点击了树形结构的节点,但是不知道如何定位点击的节点位置在原xml文件的位置? 解决方案 http://www.codeproject.com/Articles/11244/XML-TreeView-Control 解决方案二: simpleXML怎样解析一个xml文件,并对xml进行增删改查 过程Li

struts2.0 中struts.xml文件中的错误

问题描述 开发环境:jdk5.0 + myeclipse6.0 + tomcat5.5struts.xml文件配置如下:<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.

Android 中Manifest.xml文件详解

Android 中Manifest.xml文件详解 每一个Android项目都包含一个清单(Manifest)文件--AndroidManifest.xml,它存储在项目层次中的最底层.清单可以定义应用程序及其组件的结构和元数据. 它包含了组成应用程序的每一个组件(活动.服务.内容提供器和广播接收器)的节点,并使用Intent过滤器和权限来确定这些组件之间以及这些组件和其他应用程序是如何交互的. 它还提供了各种属性来详细地说明应用程序的元数据(如它的图标或者主题)以及额外的可用来进行安全设置和单

在android程序中打开HPROF文件时出错

问题描述 在android程序中打开HPROF文件时出错 当我用Memory Analyzer打开HPROF文件时(由Debug.dumpHprofData创建),得到的是以下的异常: java.io.IOException: Unknown HPROF Version (JAVA PROFILE 1.0.3) at org.eclipse.mat.hprof.AbstractParser.readVersion(AbstractParser.java:124) at org.eclipse.m

SQL Server中读取XML文件的简单做法

SQL Server 2000使得以XML导出数据变得更加简单,但在SQL Server 2000中导入XML数据并对其进行处理则有些麻烦. 如果你参考Books Online(BOL),你会发现有相关的条目,包括OPENXML以及 OPENROWSET.所有的这些例子都支持将XML文本作为已经声明的变量,这对于经常处理文本的用户来说非常方便,但对于希望在开发中读取XML文件并进行相应处理的开发人员来说就不是这样了.处理这样的问题,或许最好从内到外来对其进行分析. OPENXML是一个rowse