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的时间,但缺点也很明显,因为对象没有析构,对象的状态也就会被保持。即每次进入一个界面的时候都要针对性的初始化控件状态。因为运行之后的控件可能状态已经改变。为了达到像加载时的效果就必须手动初始化。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |