dui框架开发系列:XML解析和界面的动态创建

前端之家收集整理的这篇文章主要介绍了dui框架开发系列:XML解析和界面的动态创建前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

大家好,我要介绍的所有知识点都是WINCE/windows触摸屏DUI开源框架constvar(点击下载代码)开发过程中遇到的比较有讨论价值的问题。

 本文要讨论的是与界面解析加载相关的XML解析和动态创建界面。

XML是directui界面对象配置文件的最好选择,因为它的树形结构很适合描述同样是树形结构的对话框。从XML中可以很清晰的看清界面元素之间的层次关系。同时用XML可以很方便检测语法错误,以及很容易解析。有很多开源的解析XML的代码,这里我们选用的是CMARKUP。 因为它相当于是一个C++类,直接添加功能就能很简便的使用。

一般的DUI框架会带一些辅助工具来生成这个XML配置,CONSTVAR也是如此。生成和解析的代码原理大致相似。这里的是解析一个对话框的代码

动态创建对象则可以参考MFC的动态创建对象的实现,或者是搜索该关键词,相关的文章超多就不再累述了。

//解析res xml

CMarkupxml;

pRes->Parse(xml);

xml.ResetPos();

std::wstringstr;

std::wstringstrAtt;

CRuntimeClass*pCls = NULL;

//根据xml创建界面控件

//第一个结点已存在不需要创建,默认第一个结点为窗体根结点

xml.FindNode(CMarkup::MNT_ELEMENT);

//当前父结点

int nRtn = 0;

VtXmlNode vtNodesTag;

IterXmlNode IterNodesTag,IterPre;

SXmlNode xmlNode;

std::wstring strClsName;

if(pTribe!= m_pRoot)

{

pTribe->SetHeight(1);// 初始界面高度为

}

else

{

pTribe->SetHeight(0);

}

xmlNode.pNode= pTribe;

xmlNode.strTag= xml.GetTagName();

vtNodesTag.push_back(xmlNode);

strAtt= xml.GetAttrib(L"name");

xmlNode.pNode->SetName(strAtt);

xml.ResetPos();

intnRear = 1;

intnHead = 0;

while(nRear> nHead)

{

IterNodesTag= vtNodesTag.begin() + nHead;

if(nHead>= 1)

{

xml.RestorePos(IterNodesTag->strTag.c_str());

}

else

{

if(!xml.FindElem(IterNodesTag->strTag.c_str()))

{

nHead++;

continue;

}

}

xml.IntoElem();

while(1)

{

nRtn= xml.FindNode(CMarkup::MNT_ELEMENT);

if(0== nRtn)

{

break;

}

else

{

//增加会导致之前的iter失效

IterNodesTag= vtNodesTag.begin() + nHead;

xmlNode.strTag= xml.GetTagName();

//保存位置

xml.SavePos(xmlNode.strTag.c_str());

if(xmlNode.strTag.find(L"obj_")== 0)

{

strAtt= xml.GetAttrib(L"type");

//创建结点,并设置它的属性

strClsName= strAtt;

pCls= CRuntimeClass::LoadByName(strClsName);

if(NULL!= pCls)

{

// 动态创建对象

xmlNode.pNode=(CGroup*)pCls->CreateObject();

strAtt= xml.GetAttrib(L"name");

xmlNode.pNode->SetName(strAtt);

xmlNode.pNode->SetClassName(strClsName);

//附加属性

xmlNode.pNode->SetAdditionalAtt(xml);

//添加到父结点

IterNodesTag->pNode->AddNode(xmlNode.pNode);

vtNodesTag.push_back(xmlNode);

nRear++;

}

}

elseif(xmlNode.strTag.compare(L"style")==0)

{

strAtt= xml.GetAttrib(L"xyz");

intx,y,z,w,h;

swscanf(strAtt.c_str(),L"%d,%d,%d",&x,&y,&w,&h,&z);

if(pTribe== IterNodesTag->pNode)

{

//tribe用自己的z

IterNodesTag->pNode->InitPos(x,h,IterNodesTag->pNode->GetZ());

}

else

{

IterNodesTag->pNode->InitPos(x,z);

}

BOOLb;

DWORDdw;

strAtt= xml.GetAttrib(L"visible");

swscanf(strAtt.c_str(),L"%d",&b);

IterNodesTag->pNode->SetVisible(b);

strAtt= xml.GetAttrib(L"enable");

swscanf(strAtt.c_str(),&b);

IterNodesTag->pNode->SetEnable(b);

strAtt= xml.GetAttrib(L"message");

swscanf(strAtt.c_str(),&dw);

IterNodesTag->pNode->SetMsg(dw);

strAtt= xml.GetAttrib(L"alpha");

swscanf(strAtt.c_str(),&b);

IterNodesTag->pNode->SetAlpha(b);

………….

continue;

}

}

}

nHead++;

}

//对象已创建不再重新解析XML

pTribe->SetCreated(TRUE);

比较重要的一点是XML只加载了一遍后下次不再创建对象。这种做法的好处是省了解析XML的时间,但缺点也很明显,因为对象没有析构,对象的状态也就会被保持。即每次进入一个界面的时候都要针对性的初始化控件状态。因为运行之后的控件可能状态已经改变。为了达到像加载时的效果就必须手动初始化。

猜你在找的XML相关文章