职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 302|回复: 0

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

[复制链接]
江南枫 发表于 2011-9-24 14:11 | 显示全部楼层 |阅读模式
  现在我发现使用Visual Studio的资源编辑器进行编辑资源有着诸多的不便:首先是任何资源的变动一般变动代码,不利于系统维护,其次Visual Studio的资源编辑器的本身的功能有限,也不利于界面美化,三是不利于人员分工,开发人员既要忙实现功能,又要忙准备好的界面素材。对界面实现文件配置化正是解决上面问题的好方法。这次我实现了使用XML文件配置工具栏。这里所谓配置就是工具栏的界面信息如工具栏标题、按钮图片、是否为分隔符都在XML文件保存,程序通过解析XML文件来获取工具栏信息来创建工具栏。这样一旦发现界面不合适可以随时修改配置文件,同时利于人员分工。
  具体的做法如下:
   在工程的输出目录下有一个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表示按钮是分隔符。

   通过解析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:arseXml(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:oadImageList(ToolBar &MyToolbar)
  {
  // 获取按钮图片的个数
  int nBmpNum = MyToolbar.m_MenuItemVec.size();
  HBITMAP hBitmap = NULL;
  // 打开所有位图,将其加进图像列表
  for(int i=0; i<nBmpNum; ++i)
  {
  if (MyToolbar.m_MenuItemVec.m_bIsSeparator)
  {
  continue;
  }
  string strBinPath;
  GetOutputPath(strBinPath);
  string strBmpPath = strBinPath + string(_T("Toolbar\\"));
  strBmpPath = strBmpPath + MyToolbar.m_MenuItemVec.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.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;
  }
  }
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-4-20 10:27 , Processed in 0.127920 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表