方法一:动态加载英文资源的DLL
首先我们的把工程属性下的“MFC的使用”设置成为“在共享DLL中使用MFC”,如下图所示:
这样我们待会就可以把英文资源的DLL给动态加载进来了,不然后面DLL是不能动态加载进来的。
第二步我们就需要制作英文资源的DLL了,打开工程的资源视图,资源里的所有元素都插入一个英文版的副本,如下图所示:
在弹出来的对话框中语言选择为英文(美国),如下图所示:
把所有的资源都插入一个英文语言的副本。
第三步我们就需要建一个英文DLL的工程了,如下图所示:
直接点确定,然后参数默认点击完成即可。
然后把第一个工程里的所有资源副本剪切到这个工程中来,接下来就自己借助工具翻译资源里的中文了,包括Dialog、Menu、String Table里面的所有的中文字符串。
这些翻译完了之后,如果你工程里的消息字符串没有在String Table有对应资源的话,中文字符串也要翻译的,这个很容易忘记,实现如下:
if (g_bEnglish)
AfxMessageBox(_T("Communication failure!"));
else
AfxMessageBox(_T("通信失败!"));
这样我们就做好翻译这一步了,这里的消息字符串当然是中文那个工程里的。
第四部把英文资源DLL在Release下生成相应的Test_MultiLang.dll与Test_MultiLang.lib文件,拷贝到中文工程的App(可执行文件所在的目录,一般命名为App)下。
接下来我们就要实现英文资源的加载及软件中英文的切换了
在菜单栏帮助下“中文版”与“英文版”在XXXApp类中增加相应的响应函数,实现如下:
BOOL g_bEnglish = FALSE;
BOOL g_bRestart = FALSE;
void SetLang(BOOL bEnglish);
BOOL GetLang(void);
HINSTANCE m_hLangDLL;
void CHAM200App::SetLang(BOOL bEnglish)
{
CString strTemp;
strTemp.Format(_T("%d"), bEnglish);
WritePrivateProfileString(_T("English"), _T("bEnglish"), strTemp, g_strCurrPath + _T("set.lang"));
}
BOOL CHAM200App::GetLang(void)
{
BOOL bEnglish = GetPrivateProfileInt(_T("English"), _T("bEnglish"), 0, g_strCurrPath + _T("set.lang"));
return bEnglish;
}
void CHAM200App::OnEnglish()
{
// TODO: 在此添加命令处理程序代码
int iRet;
if (!g_bEnglish)
{
iRet = MessageBox(AfxGetApp()->GetMainWnd()->GetSafeHwnd(),_T("确定切换到英文版本?"),_T("提示"),MB_OKCANCEL | MB_ICONINFORMATION);
}
else
{
return ;
}
if (iRet == IDCANCEL)
{
return;
}
SetLang(TRUE);
g_bRestart = TRUE;
PostMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_CLOSE,0,0);
}
void CHAM200App::OnChinese()
{
// TODO: 在此添加命令处理程序代码
int iRet;
if (g_bEnglish)
{
//iRet = MessageBox(AfxGetApp()->GetMainWnd()->GetSafeHwnd(),_T("Really change to Chinese version?"),_T("Information"),MB_OKCANCEL | MB_ICONINFORMATION);
// 英文版的OK 与 Cancel
iRet = MessageBoxEx(AfxGetApp()->GetMainWnd()->GetSafeHwnd(),_T("Really change to Chinese version?"),_T("Information"),MB_OKCANCEL | MB_ICONINFORMATION,MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
else
{
return ;
}
if (iRet == IDCANCEL)
{
return;
}
SetLang(FALSE);
g_bRestart = TRUE;
PostMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_CLOSE,0,0);
}
在App类的InitInstance()函数中增加根据标志位载入资源的函数,如下:
g_bEnglish = GetLang();
if(g_bEnglish)
{
m_hLangDLL =::LoadLibrary(_T("HAM-200_En.dll"));
if( !m_hLangDLL )
{
AfxMessageBox(_T("Unable to load resource DLL!"));
return FALSE;
}
AfxSetResourceHandle(m_hLangDLL);
}
然后在退出实例的函数中增加,释放DLL句柄及重启程序的代码,实现如下:
int CHAM200App::ExitInstance()
{
//TODO: 处理可能已添加的附加资源
AfxOleTerm(FALSE);
if(m_hLangDLL)
{
FreeLibrary(m_hLangDLL);
}
if (g_bRestart)
{
STARTUPINFO StartupInfo={0};
PROCESS_INFORMATION ProcessInfo;
StartupInfo.cb=sizeof(STARTUPINFO);
char Path[256];
GetModuleFileName(NULL,(LPWSTR)(LPCTSTR)Path,250);
CreateProcess(NULL,(LPWSTR)(LPCTSTR)Path,NULL,NULL,FALSE,0,NULL,NULL,&StartupInfo,&ProcessInfo);
}
g_bRestart = FALSE;
return CWinAppEx::ExitInstance();
}
最后一步,通常工具栏与菜单栏切换中英文之后需要重置一下才能切换成相应的界面,这里我们在代码上实现,如下:
BOOL CMainFrame::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)
{
// 基类将执行真正的工作
if (!CFrameWndEx::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext))
{
return FALSE;
}
// 为所有用户工具栏启用自定义按钮
BOOL bNameValid;
CString strCustomize;
bNameValid = strCustomize.LoadString(IDS_TOOLBAR_CUSTOMIZE);
ASSERT(bNameValid);
for (int i = 0; i < iMaxUserToolbars; i ++)
{
CMFCToolBar* pUserToolbar = GetUserToolBarByIndex(i);
if (pUserToolbar != NULL)
{
pUserToolbar->EnableCustomizeButton(TRUE, ID_VIEW_CUSTOMIZE, strCustomize);
}
}
// 每次中英文切换,菜单栏与工具栏重置
m_wndMenuBar.ResetAll();
return TRUE;
}
至此为止,我们就用动态加载英文资源的DLL实现了软件的多语言的设计。效果如下:
---------------------
作者:jakee_chen
来源:CSDN
原文:https://blog.csdn.net/u012102000/article/details/57079328
版权声明:本文为博主原创文章,转载请附上博文链接!