"/>

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

来源:网络时间:2011-08-04

  现在我发现使用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, 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;

  }

  /*!

  * 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(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("未能创建状态栏 ");

  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;

  }

  }

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

意见反馈
发表评论

最新评论(共2条)

2345市网友

请问CXMLParse的源码在哪里下载?谢谢

2012-03-11 0

回复@2345网友:

  • 取消

2345市网友

支持支持支持

2012-01-17 0

回复@2345网友:

  • 取消