在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实现 多风格真彩色大图标工具栏按钮 (感谢万连文大侠提供)
在MFC程序中使用XML文件配置工具栏的更多相关文章
- 在应用程序中使用Xml文件
用于操作Xml的文档主要有XmlNode.XmlDocument.XmlComment.XmlElement.XmlAttribute.XmlText.XmlNodeList 下面用一段代码来具体说明 ...
- maven中pom.xml文件配置
<properties> <spring.version>4.3.18.RELEASE</spring.version> ...
- Struts框架中struts-config.xml文件配置小结
弄清楚struts-config.xml中各项元素的作用,对于我们构建web项目有莫大的好处.<struts-config>是struts的根元素,它主要有8个子元素,DTD定义 如下: ...
- maven构建SSM框架中pom.xml文件配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- Java程序中的Log文件配置
log4j.properties文件 log4j.rootLogger=info,stdout,logfile #stdout log4j.appender.stdout=org.apache.log ...
- Spring框架入门之基于xml文件配置bean详解
关于Spring中基于xml文件配置bean的详细总结(spring 4.1.0) 一.Spring中的依赖注入方式介绍 依赖注入有三种方式 属性注入 构造方法注入 工厂方法注入(很少使用,不推荐,本 ...
- c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程
c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...
- web.xml 文件配置01
web.xml 文件配置01 前言:一般的web工程中都会用到web.xml,方便开发web工程.web.xml主要用来配置Filter.Listener.Servlet等.但是要说明的是web. ...
- Struts2 web.xml文件配置
在导入了项目需要使用的核心jar包之后需要在web.xml中配置Struts. 1. Struts2的知识点普及: Struts2共有5类配置文件,分别罗列如下: 1), Web.xml; 在没有使用 ...
随机推荐
- UVA 10763 Foreign Exchange 出国交换 pair+map
题意:给出很多对数字,看看每一对(a,b)能不能找到对应的(b,a). 放在贪心这其实有点像检索. 用stl做,map+pair. 记录每一对出现的次数,然后遍历看看对应的那一对出现的次数有没有和自己 ...
- JS多维数组转一维
题目: var array = [1, [2, [3, 4], [5, 6]], 7, 8]; 写一个方法 flatArray(),得到数组 [1, 2, 3, 4, 5, 6, 7, 8] 解答: ...
- WebView使用详解
一.用WebView处理页面导航 可以加载本地资源也可以加载web资源,区别是我们要加载本地资源要实现在assets文件夹里添加一个.html资源.调取网页的时候可以用loadUrl方法把网址添加进去 ...
- eclipse如何设置成保护眼的背景色
链接地址:http://jingyan.baidu.com/article/2a138328b5d9ea074a134fc7.html 长时间的使用eclipse开发会很累吧 设置一个保护眼睛的豆沙 ...
- Linux开机启动十步骤
启动第一步--加载BIOS 启动第二步--读取MBR 启动第三步--Boot Loader 启动第四步--加载内核 启动第五步--用户层init依据inittab文件来设定运行等级 启动第六步--in ...
- 04-Foundation-NSSet、NSDictionary、block
目录: 一.NSSet集合 二.NSDictionary字典 三.block代码块 回到顶部 一.NSSet集合 1 NSSet是一个无序的,管理对个对象的集合类,最大特点是集合中不允许出现重复对象, ...
- c 中关于int,unsigned int , short 各种类型总结
int类型比较特殊,具体的字节数同机器字长和编译器有关.如果要保证移植性,尽量用__int16 __int32 __int64吧__int16.__int32这种数据类型在所有平台下都分配相同的字节. ...
- HNCU1330:算法3-1:八进制数
http://hncu.acmclub.com/index.php?app=problem_title&id=111&problem_id=1330 题目描述 将十进制数转换为八进制, ...
- MFC 只启动一个程序实例
问题描述: 我们开发过程中可能会经常遇到,只启动一个程序实例.即一个程序启动之后,如果再次执行该程序,将会恢复之前打开的程序,而不是打开一个新的程序. 实现原理:利用FindWindow/FindWi ...
- 社交舞 - 简介,释名,风格,舞步 - 金山词霸汉语 - HAPPY Life
社交舞 - 简介,释名,风格,舞步 - 金山词霸汉语 - HAPPY Life 社交舞 编辑词条 创建词条 内容来源 社交舞(英语:ballroom dance),又称交谊舞或交际舞,是来源于西方的一 ...