巴中模板建站价格多少,网页设计基础实训期末试卷和答案,wordpress折腾,wordpress文件路径VC开发多语言界面支持的简单方法 作者#xff1a;成晓旭 ( 需要完整源代码请留言 ) 最近在做一个小程序#xff0c;要求实现对多语言界面显示支持功能#xff0c;并且#xff0c;界面显示内容用户能够自己设置。 初步设计用 INI 文件来配置显示内容#xff0c;换一种语言的… VC开发多语言界面支持的简单方法 作者成晓旭 ( 需要完整源代码请留言 ) 最近在做一个小程序要求实现对多语言界面显示支持功能并且界面显示内容用户能够自己设置。 初步设计用 INI 文件来配置显示内容换一种语言的配置文件就能够更换整个系统的显示语言。考虑到系统规模很小周期又短不想用太复杂的方案来解决这个问题当参考了很多网上类似的设计和代码发现都不是很满意。 主要问题在于绝大多数基于 INI 文件配置这种简单应有实现的代码都是针对组件 ID 固定加载写死了组件的 ID 号比如 strCaption fileManager.GetString(section,IDC_Stc_ListStudent,); SetDlgItemText(IDC_Stc_ListStudent,strCaption); strCaption fileManager.GetString(section,IDC_Stc_AllContent,); SetDlgItemText(IDC_Stc_AllContent,strCaption); 这样界面组件越多加载代码越长每新增一个显示窗口又必须复制、粘贴类似的代码根据组件 ID 常量值来修改相关的加载项。很是不爽 初步设想是设计统一、通用的窗口组件 Caption 设置方法对给定的 Frame 或 Dialog 等 Window 容器组件内的所以组件进行遍历当增、减显示组件不对语言包加载代码产生影响达到自适应界面组件语言包加载效果。 这样就产生一个新问题语言包配置文件中的 Caption 值如何跟相关的组件正确地一一对应 好友文国庆建议用 XML 文件来定义这种对应关系。这个想法触动了我反正就是一个 [Key,Value] 的数据就用已经实现的 INI 配置文件也可以啊。于是所有问题解决 具体设计是语言包配置文件就直接设置成组件 ID 与组件显示信息的 Hash 表 Key Value 的形式比如 BtnOK 组件的 ControlID 为“ 1003 ” , 中文显示 Caption 为“登录”语言包配置内容就是“ 1003 登录”。 语言包的加载过程为 2 步实现 首先从语言包配置文件中读取所有配置的 ID 、 Caption 条目到 Vector 或者 Array 中。 其次在遍历指定窗口中所有组件时每发现一个组件就用其 ID 在已经加载的语言包数组中查找找到就用配置的值修改组件 Caption 属性找不到就认为是不需要动态配置不做处理。 配置文件实例 配置项解释 Section [Login Dialog] 界面 窗口等号左边窗口中需要设置其 Caption 属性的组件 ID 等号左边窗口中需要设置其 Caption 属性的组件 Caption 值 [Login Dialog] 1001 用户帐号 1002 用户密码 1017 登 录 1018 退 出 语言包配置信息加载代码 BOOL CLanguageManager::loadFromFile() ... { BOOL bReadFALSE; int i; ItemContext temp; CStringArray itemBuf,valueBuf; bRead fileManager.GetSectionValues(Main Window,itemBuf,valueBuf); if(bRead) ...{ for(i0;iitemBuf.GetSize();i) ...{ temp.uCtrlID atoi(itemBuf.GetAt(i)); temp.strContext valueBuf.GetAt(i); m_vtContexts.push_back(temp); } } itemBuf.RemoveAll(); valueBuf.RemoveAll(); bRead fileManager.GetSectionValues(Login Dialog,itemBuf,valueBuf); if(bRead) ...{ for(i0;iitemBuf.GetSize();i) ...{ temp.uCtrlID atoi(itemBuf.GetAt(i)); temp.strContext valueBuf.GetAt(i); m_vtContexts.push_back(temp); } } return bRead;} 读取语言包配置信息 BOOL CIniFile::GetSectionValues(CString Section, CStringArray strItemBuf, CStringArray strValueBuf) ... { BOOL bRead FALSE; ReadIniFile();//打开文件 if(bFileExist FALSE || FileContainer.GetSize() 0) return bRead;//文件打开出错或文件为空返回默认值 int i 0; int iFileLines FileContainer.GetSize(); CString strline,str; while(iiFileLines) ...{ strline FileContainer.GetAt(i); strline.TrimLeft(); if(strline.GetLength()0) continue; //跳过空行 if(strline.Left(2)//) continue; //跳过注释行 if(strline.GetAt(0)[)//查找Section第一个必须为[ ...{ strstrline.Left(strline.Find(]));//去掉]右边 strstr.Right(str.GetLength()-str.Find([)-1);//去掉[左边 str.TrimLeft(); str.TrimRight(); if(Section str)//找到Section ...{ while(iiFileLines) ...{ strline FileContainer.GetAt(i); strline.TrimLeft(); if(strline.GetLength()0) continue; //跳过空行 if(strline.GetAt(0)[) return bRead;//如果到达下一个[]即找不到,返回默认值 if(strline.Left(2)//) continue; //跳过注释行 str strline.Left(strline.Find());//去掉右边 str.TrimLeft(); str.TrimRight(); //保存等号左边项 strItemBuf.Add(str); strstrline.Right(strline.GetLength()-strline.Find()-1);//去掉左边 str.TrimLeft(); str.TrimRight(); //保存等号右边项 strValueBuf.Add(str); bRead TRUE; } //当前Section遍历结束 } //没有找到Section } //当前行遍历结束 } return bRead;} 修改指定组件 Caption 属性代码 BOOL CLanguageManager::setControlCaption(CWnd * pCtrl, UINT ctrlID) ... { BOOL isOKFALSE; for(int i0;im_vtContexts.size();i) ...{ isOK (m_vtContexts[i].uCtrlIDctrlID); if(isOK) ...{ pCtrl-SetWindowText(m_vtContexts[i].strContext); break; } } return isOK;} 遍历设置指定窗口所有组件 Caption 属性代码 void CLanguageManager::setCaptionForWindow(CWnd * pWnd) ... { //枚举对话框中所有组件 CWnd *pCtrl pWnd-GetWindow(GW_CHILD); while(pCtrl!NULL) ...{ UINT ctrlID pCtrl-GetDlgCtrlID(); setControlCaption(pCtrl,ctrlID); pCtrl pCtrl-GetNextWindow(); }}