今天介绍下类 CResourceManager , 本帖基于的 Duilib 版本为 “Duilib 开源项目圈2群” 中下载的版本,有些版本可以没有这部分代码。
这个类主要分为两大作用:
加载控件的文字, 具体的实现方式也有两种:
在 xml 中定义界面文字,像如下代码:
<?xml version="1.0" encoding="utf-8"?> <Res> <Text id="lantext" value="切换到英文" /> </Res>
之后通过调用
BOOL LoadLanguage(LPCTSTR pstrXml)
将 xml 中定义的文字加载到成员m_mTextResourceHashMap
中。在实际想使用事先定义好的文字时,需要先为控件属性添加resourcetext="true"
, 且控件的text
需定义为 xml 的某个id
参考如下代码:CDuiString CControlUI::GetText() const { if (!IsResourceText()) return m_sText; return CResourceManager::GetInstance()->GetText(m_sText); }
只有在设置了此属性后才会从
CResourceManager
中加载文字。第二种方式是从代码中动态加载文字,这种方式是在上述方法未读取到文字的情况下才进行, 也就是说已经定义了
resourcetext="true"
, 但是控件的text
属性的值却未在 xml 定义过。 此时会调用如下代码:CDuiString CResourceManager::GetText(LPCTSTR lpstrId, LPCTSTR lpstrType) { if(lpstrId == NULL) return _T(""); CDuiString *lpstrFind = static_cast<CDuiString *>(m_mTextResourceHashMap.Find(lpstrId)); if (lpstrFind == NULL && m_pQuerypInterface) { lpstrFind = new CDuiString(m_pQuerypInterface->QueryControlText(lpstrId, lpstrType)); m_mTextResourceHashMap.Insert(lpstrId, (LPVOID)lpstrFind); } return lpstrFind == NULL ? lpstrId : *lpstrFind; }
上述代码第 5 行,在从 xml 中读取失败的情况下,会调用
m_pQuerypInterface->QueryControlText(lpstrId, lpstrType)
读取文字。 我们可以让某个类继承自IQueryControlText
实例化方法LPCTSTR QueryControlText(LPCTSTR lpstrId, LPCTSTR lpstrType)
即可,在这个方法中定义文字的id
和value
。 用这种方法加载成功后,会将此值补充到m_mTextResourceHashMap
中
加载控件的图片或者加载界面所需 xml
xml 定义如下所示
<?xml version="1.0" encoding="utf-8"?>
<Res>
<Image id="sysbtn_menu_normal" path="sysbtn/btn_menu_normal.png" />
<Image id="sysbtn_menu_hot" path="sysbtn/btn_menu_highlight.png" />
<Image id="sysbtn_menu_pushed" path="sysbtn/btn_menu_down.png" />
<Xml id="XML_MAIN" path="main.xml"/>
<Xml id="XML_MSG" path="msg.xml"/>
</Res>
然后通过调用 BOOL LoadResource(STRINGorID xml, LPCTSTR type = NULL)
将此 xml 加载到 m_mImageHashMap
和 m_mXmlHashMap
中,之后,我们平时在创建控件时传入 xml 的地方,和定义控件图片相关属性时,都可以定义为 xml 中的 id。 然后再实际创建控件或者读取图片路径的时候,会首先根据参数从 m_mImageHashMap
和 m_mXmlHashMap
中读取,未读取到的情况下,直接读取传入的参数,参考如下代码:
CControlUI* CDialogBuilder::Create(STRINGorID xml, LPCTSTR type, IDialogBuilderCallback* pCallback,
CPaintManagerUI* pManager, CControlUI* pParent)
{
//资源ID为0-65535,两个字节;字符串指针为4个字节
//字符串以<开头认为是XML字符串,否则认为是XML文件
if(HIWORD(xml.m_lpstr) != NULL && *(xml.m_lpstr) != _T('<')) {
LPCTSTR xmlpath = CResourceManager::GetInstance()->GetXmlPath(xml.m_lpstr);
if (xmlpath != NULL) {
xml = xmlpath;
}
}
......
}
上段代码第 7 行,首先从 CResourceManager
加载 xml。然后是加载图片的代码:
TImageInfo* CRenderEngine::LoadImage(LPCTSTR pStrImage, LPCTSTR type, DWORD mask, HINSTANCE instance)
{
if(pStrImage == NULL) return NULL;
CDuiString sStrPath = pStrImage;
if( type == NULL ) {
sStrPath = CResourceManager::GetInstance()->GetImagePath(pStrImage);
if (sStrPath.IsEmpty()) sStrPath = pStrImage;
else {
/*if (CResourceManager::GetInstance()->GetScale() != 100) {
CDuiString sScale;
sScale.Format(_T("@%d."), CResourceManager::GetInstance()->GetScale());
sStrPath.Replace(_T("."), sScale);
}*/
}
}
return LoadImage(STRINGorID(sStrPath.GetData()), type, mask, instance);
}
上段代码第 7 行,首先从 CResourceManager
中加载。
这个类到此介绍完了,是一个工具类,实际使用过程中,我们可能会采取各种方法来加载文字,或者图片xml,这里提供了一种方式,用的上的朋友可以使用下。