使用动态链接库设计多国语言的应用程序
在设计应用程序时,为了使应用程序适应多国语言,通常将程序中的资源放置在单独的动态链接库中,一个资源通常对应多个语言版本的资源。例如,使应用程序能够在汉语和英语间切换,需要为每个资源提供汉语版的资源和英语版的资源。下面通过一个示例介绍如何向动态链接库中添加不同语言的资源。
例如,向动态链接库中添加不同语言的资源
(1)创建一个MFC动态链接库,工程名称为“LanguageRes”。
(2)在工作区的资源视图窗口中插入一个对话框资源,如图1所示。
.jpg)
图1 对话框资源设计窗口
(3)在工作区的资源视图窗口中选中对话框的资源ID,按“Alt+Enter”组合键打开属性窗口,如图2所示。
.jpg)
图2 对话框资源属性窗口
(4)在ID编辑框中设置对话框资源的ID,本例为“IDD_CH_DIALOG”。在对话框资源属性窗口的“Language”组合框中选择资源的语言为“Chines(P.R.C.)”。
(5)在工作区的资源视图窗口中选中对话框的资源ID,复制该对话框资源。按“Alt+Enter”组合键打开属性窗口,设置新的对话框资源ID也为IDD_CH_DIALOG,在“Language”组合框中选择资源的语言为“English(U.S.)”。
(6)编译并运行应用程序,将生成dll文件。
在设计完动态链接库之后,下面设计一个客户端应用程序,程序将利用动态链接库中的对话框资源设计一个包含汉语和英语两个版本的简单加法计算器。其具体操作步骤如下:
(1)创建一个基于对话框的工程,工程名称为“MultiLanguage”。设计对话框资源如图3所示。
.jpg)
图3 对话框资源设计
(2)将动态链接库工程中“Resource.h”头文件中的资源ID复制到当前的工程“Resource.h”头文件中。
#define IDC_PLUSONE 3000
#define IDD_CH_DIALOG 3000
#define IDC_PLUSTWO 3001
#define IDC_RESULT 3002
#define IDC_CALCULATE 3003
(3)创建一个MFC类,名称为CCalculate,基类为CDialog,不要提供对话框的资源ID。
(4)向CCalculate类中提供3个成员变量,分别对应于动态链接库中的对话框资源中的3个编辑框资源。
CEdit m_PlusOne; //定义编辑框变量
CEdit m_PlusTwo; //定义编辑框变量
CEdit m_Result; //定义编辑框变量
(5)在CCalculate类的DoDataExchange方法中映射编辑框的名称到编辑框的资源上。
void CCalculate::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCalculate)
// NOTE: the ClassWizard will add DDX and DDV calls here
DDX_Control(pDX, IDC_PLUSONE, m_PlusOne); //映射编辑框资源到编辑框变量
DDX_Control(pDX, IDC_PLUSTWO, m_PlusTwo); //映射编辑框资源到编辑框变量
DDX_Control(pDX, IDC_RESULT, m_Result); //映射编辑框资源到编辑框变量
//}}AFX_DATA_MAP
}
(6)向CCalculate类中添加OnCalculte方法,实现加法运算。
void CCalculate::OnCalculte()
{
CString plusone,plustwo,ret; //定义3个字符串变量
m_PlusOne.GetWindowText(plusone); //获取编辑框文本
m_PlusTwo.GetWindowText(plustwo); //获取编辑框文本
if (plusone.IsEmpty() || plustwo.IsEmpty()) //判断文本是否为空
return;
int iplusone = atoi(plusone.GetBuffer(0)); //将编辑框文本转换为整数
int iplustwo = atoi(plustwo.GetBuffer(0)); //将编辑框文本转换为整数
int iret = iplusone + iplustwo; //进行整数相加
ret.Format("%d",iret); //格式化字符串
m_Result.SetWindowText(ret); //设置编辑框文本
}
(7)在CCalculate类的消息映射部分添加ON_BN_CLICKED映射宏,使OnCalculate方法与按钮的命令ID关联。
ON_BN_CLICKED(IDC_CALCULATE, OnCalculte) //按钮命令的消息映射宏
(8)自定义一个窗口函数,用于作为对话框的临时窗口函数。
BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_INITDIALOG) //如果是对话框初始化消息
{
//根据对话框句柄获取对话框指针
CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, CWnd::FromHandlePermanent(hwndDlg));
if (pDlg != NULL) //判断对话框指针是否为空
return pDlg->OnInitDialog(); //调用对话框的OnInitDialog方法
else
return 1;
}
return 0;
}
说明:DYNAMIC_DOWNCAST宏能够将某一个MFC类转换为指定的指针类型,如果转换失败,则返回值为NULL。
(9)向对话框中添加CreateDlgFromDll方法,搜索动态链接库中的对话框资源,并根据对话框资源创建对话框窗口。
HWND CCalculate::CreateDlgFromDll(LPCSTR csFileName,UINT Flag)
{
//以数据文件的形式加载动态链接库
HMODULE hMod = LoadLibraryEx(csFileName,NULL,LOAD_LIBRARY_AS_DATAFILE);
if (hMod != NULL) //判断加载是否成功
{
HRSRC hDialog = NULL; //定义一个资源变量
if (Flag == 0) //加载汉语版对话框资源
{
//查找动态链接库中的对话框资源
hDialog = FindResourceEx(hMod,RT_DIALOG,MAKEINTRESOURCE(IDD_CH_DIALOG)
,MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED));
HGLOBAL hData = LoadResource(hMod,hDialog); //加载对话框资源
if (hData != NULL) //判断加载是否成功
{
//锁定对话框资源
LPCDLGTEMPLATE lpDialogTemplate = (LPCDLGTEMPLATE)LockResource( hData);
//根据对话框资源创建对话框
CWnd::CreateDlgIndirect(lpDialogTemplate,NULL);
}
UnlockResource(hData); //解除对资源的锁定
}
else if (Flag == 1) //加载英语版对话框资源
{
/查找动态链接库中的对话框资源
hDialog = FindResourceEx(hMod,RT_DIALOG,MAKEINTRESOURCE(IDD_CH_DIALOG),
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));
HGLOBAL hData = LoadResource(hMod,hDialog); //加载对话框资源
if (hData != NULL) //判断加载是否成功
{
//锁定对话框资源
LPCDLGTEMPLATE lpDialogTemplate = (LPCDLGTEMPLATE)LockResource( hData);
CWnd::CreateDlgIndirect(lpDialogTemplate,NULL); //根据对话框资源创建对话框
}
UnlockResource(hData); //解除对资源的锁定
}
}
FreeLibrary(hMod); //卸载动态链接库
return NULL;
}
(10)添加CCalculate类的析构函数,如果该类关联一个窗口,则在释放对象时销毁窗口。
CCalculate::~CCalculate() //定义析构函数
{
if (IsWindow(m_hWnd)) //判断窗口句柄是否合法
DestroyWindow(); //销毁窗口
}
(11)在主对话框中定义两个CCalculate类对象。
CCalculate m_CHDialog; //定义CCalculate类对象
CCalculate m_ENDialog; //定义CCalculate类对象
(12)处理“汉语版”按钮的单击事件,从动态链接库中加载汉语版的对话框资源,并根据该资源创建窗口。
void CMultiLanguageDlg::OnChEdition()
{
::DestroyWindow(m_CHDialog.m_hWnd); //销毁窗口
m_CHDialog.CreateDlgFromDll("LanguageRes.dll",0); //创建对话框
::ShowWindow(m_CHDialog.m_hWnd,SW_SHOW); //显示对话框
}
(13)处理“英语版”按钮的单击事件,从动态链接库中加载英语版的对话框资源,并根据该资源创建窗口。
void CMultiLanguageDlg::OnEnEdition()
{
::DestroyWindow(m_ENDialog.m_hWnd); //销毁窗口
m_ENDialog.CreateDlgFromDll("LanguageRes.dll",1); //创建对话框
::ShowWindow(m_ENDialog.m_hWnd,SW_SHOW); //显示对话框
}
(14)运行程序,效果如图4、图5所示。
.jpg)
图4 汉语版对话框
.jpg)
图5 英语版对话框