金山界面库分析(1)
来源:互联网 发布:燕十八mysql视频全套 编辑:程序博客网 时间:2024/05/01 20:09
通过XML创建界面---对象的动态创建以及属性的设置
为了界面可配置化和换肤,需要界面元素可以根据XML动态创建和设置属性。
在BKLib中,CBkObject类就完成了这样的功能,主要负责类的创建和属性的设置。因为对象都是从XML动态创建的,动态的创建是一个类最基本的属性,所以其他类都从CBkObject派生。
来看看这个类的四个方法:
BOOL IsClass(LPCSTR lpszName):判断是不是这个类的对象。纯虚方法,也就是从CBkObject继承来的类都要实现这个方法才行,同时,这个方法在不同的类上面会有不同的表现。所以上层定义接口,下层提供实现。这个方法可以在运行时检测类实例的实际类型。
LPCSTR GetObjectClass():同上一个方法,用于获取类的名字。
BOOL Load(TiXmlElement* pXmlElem):从XML中获取属性并将属性设置到对象中,在基类中仅仅是将一个XML元素的属性设置到对象中。当然,如果子类对象有更复杂的实现,比如一个对象对应的XML元素还有子节点,就需要Load其子节点,这些都可以在子类中通过覆盖父类方法来实现。
HRESULT SetAttribute(CStringAstrAttribName, CStringA strValue, BOOL bLoading):设置属性的方法,CBkObject是纯虚类,在XML中不会有对应的节点,自然也没有相应的属性,所以其实现仅仅放回了一个E_FAIL,没有其他操作。
接着我们就看到了在bkobject.h里面一大堆的宏定义:
宏定义一般是为了简洁,而这些宏的用途多为子类使用。
BKOBJ_DECLARE_CLASS_NAME:获取类名,判断是否是某个类的对象,还有CheckAndNew,用于动态创建
以下的宏定义主要用于属性的设置和映射(XML节点属性和对象属性的对应)
BKWIN_DECLARE_ATTRIBUTES_BEGIN
BKWIN_DECLARE_ATTRIBUTES_END
BKWIN_CHAIN_ATTRIBUTE
BKWIN_CUSTOM_ATTRIBUTE
BKWIN_INT_ATTRIBUTE
BKWIN_UINT_ATTRIBUTE
BKWIN_DWORD_ATTRIBUTE
BKWIN_STRING_ATTRIBUTE
BKWIN_TSTRING_ATTRIBUTE
BKWIN_HEX_ATTRIBUTE
BKWIN_COLOR_ATTRIBUTE
BKWIN_FONT_ATTRIBUTE
BKWIN_ENUM_ATTRIBUTE
BKWIN_ENUM_VALUE
BKWIN_ENUM_END
BKWIN_STYLE_ATTRIBUTE
BKWIN_SKIN_ATTRIBUTE
现在我们看一个例子,继承自CBkObject的控件对象CBkProgress是如何完成从XML动态创建的。
首先,在类的定义中包含宏BKOBJ_DECLARE_CLASS_NAME(CBkProgress,"progress"),将宏展开如下:
public: static CBkProgress* CheckAndNew(LPCSTR lpszName) { if (strcmp(GetClassName(), lpszName) == 0) return new CBkProgress; else return NULL; } //通过传入名称创建对应的类,在解析XML中按照节点名字创建对应类的实例 static LPCSTR GetClassName() { return “progress”; } virtual LPCSTR GetObjectClass() { return “progress”; } //覆盖父类方法,返回类实例对应的XML节点名字 virtual BOOL IsClass(LPCSTR lpszName) { return strcmp(GetClassName(), lpszName) == 0; } //覆盖父类方法,根据XML节点名字检查类实例是否是此节点
另外,包含设置节点属性的宏,如下
BKWIN_DECLARE_ATTRIBUTES_BEGIN()
BKWIN_SKIN_ATTRIBUTE("bgskin",m_pSkinBg,TRUE)
BKWIN_DWORD_ATTRIBUTE("min",m_dwMinValue,FALSE)
BKWIN_UINT_ATTRIBUTE("showpercent",m_bShowPercent,FALSE)
BKWIN_DECLARE_ATTRIBUTES_END()
将宏展开如下:
public: virtual HRESULT SetAttribute( CStringA strAttribName, CStringA strValue, BOOL bLoading) //添加SetAttribute方法,在Load中循环调用设置属性 { HRESULT hRet = __super::SetAttribute( //首先设置父类定义的属性 strAttribName, strValue, bLoading ); if (SUCCEEDED(hRet)) return hRet; if ("bgskin" == strAttribName) //属性名称是strAttribName { m_pSkinBg = BkSkin::GetSkin(strValue); //属性的值是strValue hRet = TRUE ? S_OK : S_FALSE; //是否全部重绘 } else if ("min" == strAttribName) { m_dwMinValue = (DWORD)::StrToIntA(strValue); hRet = FALSE ? S_OK : S_FALSE; } else if ("showpercent" == strAttribName) { m_bShowPercent = (UINT)::StrToIntA(strValue); hRet = FALSE ? S_OK : S_FALSE; } else return E_FAIL; return hRet; }
现在我们来看看CheckAndNew和SetAttribute这两个方法是如何被调用的,看调用栈:
1.在实窗口的Create方法中(DoModal中调用Create)调用实窗口的Load和SetXml方法装载XML,在SetXML方法中查找XML中存在的"header"、"body"、"footer"节点调用各自的Load方法并设置相应属性。这三个节点开始就是虚窗口了,调用其Load方法就进入了虚窗口的创建体系。
2.在这三者的调用中会调用CBkPanel::Load方法
virtual BOOLLoad(TiXmlElement*pTiXmlElem) { if (!CBkWindow::Load(pTiXmlElem)) //调用父类load方法,主要进行自身属性设置 returnFALSE; return LoadChilds(pTiXmlElem->FirstChildElement()); //load子节点}
在CBkPanel::LoadChilds方法中,顺序调用每个子节点的创建方法并调用Load方法。
3. 在CBkPanel::LoadChilds方法中进行了如下调用:
CBkWindow*pNewChildWindow =_CreateBkWindowByName(pXmlChild->Value());
在_CreateBkWindowByName函数根据从XML解析出的节点名称调用
pNewWindow= CBkDialog::CheckAndNew(lpszName); // CBkDialog为需要动态创建类的名称
创建出对应节点对象。安装我们展开的CheckAndNew方法,如果节点名称相同,创建类对象并返回,否则返回空。
至此,按照XML节点名称动态创建类对象的过程就完成了。
- 金山界面库分析(1)
- 金山界面库分析(2)
- 金山界面库分析(3)
- 金山界面库分析(4)
- 金山界面库分析(5)
- 金山界面库分析(6)
- 金山界面库分析(7)
- 金山界面库分析(8)
- 金山界面库分析(9)
- 金山界面库分析(10)
- 金山界面库分析(0)
- 金山界面库
- 金山界面库
- 金山界面库源码
- 金山界面库
- 金山卫士界面源码解读及界面库分离(1)
- 金山卫士界面源码解读及界面库分离(1)
- 金山卫士界面源码解读及界面库分离(1)
- 恢复gnome默认的面板命令
- 读入字符串
- 系统管理员设置了系统策略 禁止进行此安装
- 华为C语言编程规范(4)—标识符命名
- C语言实验——分割整数
- 金山界面库分析(1)
- 高级程序员装逼指南
- 华为C语言编程规范(5)—可读性
- Oracle日志的深入分析
- 头疼—工科转入IT学习
- 华为C语言编程规范(6)—变量、结构
- 线程、进程内核对象引用计数问题
- 华为C语言编程规范(7)—函数、过程
- eclipse插件开发的一点总结