0 引言
颜色、字体、图片、字符串都可以作为界面库的资源文件。资源管理的好坏,关系到界面库的性能和易用性。好的资源管理需要做到合理缓存、取用方便。缓存提高性能、取用方便提高易用性。
1 颜色管理
颜色资源可以保存在xml文件中,具体文件格式如下:
<ColorTable>
<Color Id="ID_COLOR_BLACK">255,60,60,60</Color>
<Color Id="ID_COLOR_SEARCH_TIPS">255,210,205,202</Color>
<Color Id="ID_COLOR_CAPTURE_IMAGE_BKG">150,0,0,0</Color>
<Color Id="ID_COLOR_CAPTURE_IMAGE_BORDER">255,248,100,24</Color>
<Color Id="ID_COLOR_MENU_BKG">255,244,244,244</Color>
<Color Id="ID_COLOR_CHAT_LINE">255,194,194,194</Color>
<Color Id="ID_COLOR_MENU_TEXT_CHECKED">255,85,195,236</Color>
<Color Id="ID_COLOR_BLUE_FONT">255,96,198,236</Color>
</ColorTable>
我们可以写一个颜色管理的单例类,通过ID获得颜色。具体代码如下:
#pragma once
class CColorManager
{
private:
CColorManager();
~CColorManager();
public:
static CColorManager* GetInstance();
static void ReleaseInstance();
public:
Color GetColor(const tstring& strColor);
protected:
void Load(const tstring& strXml);
private:
static CColorManager* s_inst;
private:
map<tstring, Color> m_mapColor;
};
CColorManager* CColorManager::s_inst = NULL;
CColorManager::CColorManager()
{
}
CColorManager::~CColorManager()
{
}
CColorManager* CColorManager::GetInstance()
{
if(!s_inst)
{
s_inst = new CColorManager();
if(s_inst)
{
s_inst->Load();
}
}
return s_inst;
}
void CColorManager::ReleaseInstance()
{
if(s_inst)
{
delete s_inst;
s_inst = NULL;
}
}
void CColorManager::Load(const tstring& strXml)
{
//从xml加载颜色值
}
Color CColorManager::GetColor(const tstring& strColor)
{
map<tstring, Color>::iterator iter = m_mapColor.find(strColor);
if(iter != m_mapColor.end())
{
return iter->second;
}
return Color::Red;
}
2 字体管理
字体资源可以保存在xml文件中,具体文件格式如下:
<FontFamily>
<Familys>
<Family>微软雅黑</Family>
<Family>新宋体</Family>
<Family>宋体</Family>
</Familys>
<Fonts>
<Font Id="ID_FONT_SMALL" Size="9" Bold="false" Italic="false" Strikeout="false" Underline="false"/>
<Font Id="ID_FONT_NORMAL" Size="10" Bold="false" Italic="false" Strikeout="false" Underline="false"/>
<Font Id="ID_FONT_HYPERLINK" Size="10" Bold="false" Italic="false" Strikeout="false" Underline="true"/>
<Font Id="ID_FONT_BOLD" Size="10" Bold="true" Italic="false" Strikeout="false" Underline="false"/>
<Font Id="ID_FONT_11" Size="11" Bold="false" Italic="false" Strikeout="false" Underline="false"/>
<Font Id="ID_FONT_BIG" Size="14" Bold="false" Italic="false" Strikeout="false" Underline="false"/>
<Font Id="ID_FONT_BOLD_BIG" Size="14" Bold="true" Italic="false" Strikeout="false" Underline="false"/>
<Font Id="ID_FONT_BOLD_BIG_BIG" Size="18" Bold="true" Italic="false" Strikeout="false" Underline="false"/>
</Fonts>
</FontFamily>
为了一致性的考虑,一个应用程序最好只用一种字体。这里定义了一个字体家族的列表,根据操作系统字体的安装情况,优先选择靠前的字体。字体的其他属性,比如大小、是否加粗、是否斜体、是否有下划线、是否有删除线,通过xml的节点属性指定。
我们可以写一个字体管理的单例类,通过ID获得字体。具体代码如下:
#pragma once
class CFontManager
{
private:
CFontManager();
~CFontManager();
public:
static CFontManager* GetInstance();
static void ReleaseInstance();
public:
Font* GetFont(const tstring& strFont);
protected:
void Load();
private:
static CFontManager* s_inst;
private:
tstring m_strFamily;
map<tstring, Font*> m_mapFont;
};
CFontManager* CFontManager::s_inst = NULL;
CFontManager* CFontManager::GetInstance()
{
if(!s_inst)
{
s_inst = new CFontManager();
if(s_inst)
{
s_inst->Load();
}
}
return s_inst;
}
void CFontManager::ReleaseInstance()
{
if(s_inst)
{
delete s_inst;
s_inst = NULL;
}
}
CFontManager::CFontManager()
{
}
CFontManager::~CFontManager()
{
}
void CFontManager::Load()
{
//从xml加载字体
}
Font* CFontManager::GetFont(const tstring& strFont)
{
map<tstring, Font*>::iterator iter = m_mapFont.find(strFont);
if(iter != m_mapFont.end())
{
return iter->second;
}
assert(false);
return NULL;
}
3 图片管理
png格式体积小、清晰度高、支持透明通道,是图片资源的不二之选。应用程序可能还需要一些gif格式的图片。
为了减少图片的数量,可以将一些相似的图片合在一起,组成一张图片。例如按钮背景,通常需要四种状态:正常、鼠标移上去、鼠标按下、禁用。这四张图片就可以合为一张图片。
我们还需要一个xml的索引文件,用来记录图片是由多少张图片合在一起的、绘制图时怎样去九宫格拉伸图片。
索引文件的格式如下:
<Images>
<Image Name="Button.png" Frame="4" Patch=”7,7,7,7”/>
<Image Name="IconButton.png" Frame="3" Patch=”7,7,7,7”/>
<Image Name="ComboArrow.png" Frame="4" Patch=”7,7,7,7”/>
<Image Name="CheckBox.png" Frame="12" Patch=”7,7,7,7”/>
<Image Name="Close.png" Frame="3" Patch=”7,7,7,7”/>
</Images>
我们可以写一个字体管理的单例类,通过ID获得字体。具体代码如下:
#pragma once
class CImageManager
{
private:
CImageManager();
~CImageManager();
public:
static CImageManager* GetInstance();
static void ReleaseInstance();
public:
Image* GetImage(const tstring& strId);
LONG GetFrameCount(const tstring& strId);
const CSize& GetSize(const tstring& strId);
const CPatch& GetPatch(const tstring& strId);
protected:
void Load();
private:
map<tstring, LONG> m_mapImageFrame;
map<tstring, pair<CSize, CPatch>> m_mapImageInfo;
map<tstring, Image*> m_mapImage;
static CImageManager* s_inst;
};
CImageManager* CImageManager::s_inst = NULL;
CImageManager::CImageManager()
{
}
CImageManager::~CImageManager()
{
}
CImageManager* CImageManager::GetInstance()
{
if(!s_inst)
{
s_inst = new CImageManager();
if(s_inst)
{
s_inst->Load();
}
}
return s_inst;
}
void CImageManager::ReleaseInstance()
{
if(s_inst)
{
delete s_inst;
s_inst = NULL;
}
}
void CImageManager::Load()
{
//从xml加载图片资源
}
LONG CImageManager::GetFrameCount(const tstring& strId)
{
map<tstring, LONG>::iterator iter = m_mapFrame.find(strId);
if(iter == m_mapFrame.end())
{
AddImage(strId);
}
return m_mapFrame[strId];
}
const CSize& CImageManager::GetSize(const tstring& strId)
{
map<tstring, pair<CSize, CPatch>>::iterator iter = m_mapResImage.find(strId);
if(iter == m_mapResImage.end())
{
AddImage(strId);
}
return m_mapResImage[strId].first;
}
const CPatch& CImageManager::GetPatch(const tstring& strId)
{
map<tstring, pair<CSize, CPatch>>::iterator iter = m_mapResImage.find(strId);
if(iter != m_mapResImage.end())
{
AddImage(strId);
}
return m_mapResImage[strId].second;
}
4 字符串管理
字符串资源可以保存在xml文件中,具体文件格式如下:
<StringTable>
<String Id="IDS_MEMU_TIPS">主菜单</String>
<String Id="IDS_SKIN_TIPS">更换皮肤</String>
<String Id="IDS_MIN_TIPS">最小化</String>
<String Id="IDS_MAX_TIPS">最大化</String>
<String Id="IDS_MENU_TIPS">主菜单</String>
<String Id="IDS_CLOSE_TIPS">关闭</String>
<String Id="IDS_RESTORE_TIPS">还原</String>
<String Id="IDS_TOP_MOST_TIPS">此窗口总在最前</String>
<String Id="IDS_NO_TOP_MOST_TIPS">取消总在最前</String>
<String Id="IDS_MAKE_SKIN_TIPS1">滚动鼠标滚轮,缩放图片</String>
<String Id="IDS_MAKE_SKIN_TIPS2">试试拖动主面板</String>
<String Id="IDS_YES">是</String>
<String Id="IDS_NO">否</String>
<String Id="IDS_OK">确定</String>
<String Id="IDS_CANCEL">取消</String>
</StringTable>
我们可以写一个字符串管理的单例类,通过ID获得字符串。具体代码如下:
#pragma once
class CStringManager
{
private:
CStringManager(){}
public:
static CStringManager* GetInstance();
static void ReleaseInstance();
public:
tstring GetString(const tstring& strId);
protected:
void Load(const tstring& strXml);
private:
static CStringManager* s_inst;
private:
map<tstring, tstring> m_mapString;
};
CStringManager* CStringManager::s_inst = NULL;
CStringManager* CStringManager::GetInstance()
{
if(!s_inst)
{
s_inst = new CStringManager();
if(s_inst)
{
s_inst->Load(_T("value\\string.xml"));
s_inst->Load(_T("value\\system\\string.xml"));
}
}
return s_inst;
}
void CStringManager::ReleaseInstance()
{
if(s_inst)
{
delete s_inst;
s_inst = NULL;
}
}
void CStringManager::Load(const tstring& strXml)
{
//从xml文件加载字符串资源
}
tstring CStringManager::GetString(const tstring& strId)
{
map<tstring, tstring>::iterator iter = m_mapString.find(strId);
if(iter != m_mapString.end())
{
return iter->second;
}
return strId;
}
5 结束语
可以定义一个公共类,用来获取界面的各种资源,方便取用,代码如下:
class SkinUI
{
public:
static LONG GetFrameCount(const tstring& strImage);
static CSize GetImageSize(const tstring& strImage);
static CPatch GetImagePatch(const tstring& strImage);
static CImage* LoadImage(const tstring& strImage);
static Image* GetImage(const tstring& strImage);
static Font* GetFont(const tstring& strFont);
static Color GetColor(const tstring& strColor);
static tstring GetString(const tstring& strString);
};
inline tstring SkinUI::GetString(const tstring& strString)
{
return CStringManager::GetInstance()->GetString(strString);
}
inline Color SkinUI::GetColor(const tstring& strColor)
{
return CColorManager::GetInstance()->GetColor(strColor);
}
inline LONG SkinUI::GetFrameCount(const tstring& strImage)
{
return CImageManager::GetInstance()->GetFrameCount(strImage);
}
inline CSize SkinUI::GetImageSize(const tstring& strImage)
{
return CImageManager::GetInstance()->GetSize(strImage);
}
inline CPatch SkinUI::GetImagePatch(const tstring& strImage)
{
return CImageManager::GetInstance()->GetPatch(strImage);
}
inline Image* SkinUI::GetImage(const tstring& strImage)
{
return CResourceManager::GetInstance()->GetImage(strImage);
}
inline Font* SkinUI::GetFont(const tstring& strFont)
{
return CFontManager::GetInstance()->GetFont(strFont);
}
获取资源的示例代码如下:
获取字符串:
tstring str = SkinUI::GetString(_T(“IDS_OK”));
获取颜色
Color color = SkinUI::GetColor(_T(“ID_COLOR_RED”));
获取图片
Image* pImg = SkinUI::GetImage(_T(“button.png”));
获取字体
Font* pFont = SkinUI::GetFont(_T(“ID_FONT_BOLD”));