一些网友经常出现的一个问题就是我下面的代码为什么在SOUI的xxx窗口中没有动态创建了新窗口:
SWindow *pWnd = new SWindow(); FindChildByName(L"xxx")->InsertChild(pWnd);
上面这样的代码有3个问题:
1、它并不会在界面中显示出来你new出来的子窗口。因为这个新插入的窗口没有指定布局属性。
2、这样做在程序退出时可能出现崩溃,因为内存分配和翻译可能不在相同的模块。
3、pWnd中的各种其它属性也没有被正常初始化。
正确的方法是使用SWindow::CreateChildren(LPCWSTR pszXml)这个方法来创建窗口。
pszXml必须是一个XML字符串。
SWindow::CreateChildren和上面代码有什么区别?先找到这个函数看下它的代码:
1 SWindow * SWindow::CreateChildren(LPCWSTR pszXml) 2 { 3 pugi::xml_document xmlDoc; 4 if(!xmlDoc.load_buffer(pszXml,wcslen(pszXml)*sizeof(wchar_t),pugi::parse_default,pugi::encoding_utf16)) return NULL; 5 BOOL bLoaded=CreateChildren(xmlDoc); 6 if(!bLoaded) return NULL; 7 else return m_pLastChild; 8 } 9 10 BOOL SWindow::CreateChildren(pugi::xml_node xmlNode) 11 { 12 TestMainThread(); 13 for (pugi::xml_node xmlChild=xmlNode.first_child(); xmlChild; xmlChild=xmlChild.next_sibling()) 14 { 15 if(xmlChild.type() != pugi::node_element) continue; 16 17 if(_wcsicmp(xmlChild.name(),KLabelInclude)==0) 18 {//在窗口布局中支持include标签 19 SStringT strSrc = S_CW2T(xmlChild.attribute(L"src").value()); 20 pugi::xml_document xmlDoc; 21 SStringTList strLst; 22 23 if(2 == ParseResID(strSrc,strLst)) 24 { 25 LOADXML(xmlDoc,strLst[1],strLst[0]); 26 }else 27 { 28 LOADXML(xmlDoc,strLst[0],RT_LAYOUT); 29 } 30 if(xmlDoc) 31 { 32 CreateChildren(xmlDoc.child(KLabelInclude)); 33 }else 34 { 35 SASSERT(FALSE); 36 } 37 }else if(!xmlChild.get_userdata())//通过userdata来标记一个节点是否可以忽略 38 { 39 SWindow *pChild = SApplication::getSingleton().CreateWindowByName(xmlChild.name()); 40 if(pChild) 41 { 42 InsertChild(pChild); 43 pChild->InitFromXml(xmlChild); 44 } 45 } 46 } 47 48 return TRUE; 49 }
注意上面代码的39行及43行。
39行意思是让SOUI系统new一个和标签匹配的SWindow对象,查看CreateWindowByName的代码,发现也是直接new一个对象,但这和在APP层new是不一样的,因为这个新的对象不做特别处理释放也是在SOUI模块内,所以APP层一般是不能直接new一个窗口对象的。
更重根的是第43行,你应该在XML里配置好布局属性及其它相关的皮肤属性。通过这一行SOUI把这些属性初始化到新创建的对象,系统才能正常显示新创建的控件。
时间: 2024-10-27 11:18:54