mfc~实现mfc程序支持设置多语言

近10天,一直在忙活着让一个mfc中文版程序,支持设置其他语言。我用的stringtable来实现的,这个方法比较简单高效,就是实现起来枯燥了一些。昨天晚上刚忙完,今天总结一下实现过程中关键的几个点。

1、stringtable。

stringtable在此处主要是用来做翻译的,比如,对话框的caption,控件的windowtext,MessageBox的一些提示,我们都可以在各个语言对应的stringtable中,添加其翻译过来的内容。

(1)先添加stringtable。

若当前项目没有stringtable,就选择项目后,右键,选择“添加”----“资源”----“stringtable”----“新建”。

若当前项目有stringtable,就切换到资源视图,选择一个stringtable,右键,选择“插入副本”,然后选择想要添加哪种语言的stringtable即可。插入的新副本的stringtable。就是之前stringtable的复制版,然后翻译里面的内容。

(2)在stringtable中添加或者修改内容。

在中文stringtable中添加如下内容:

在英文stringtable中添加如下内容

若stringtable是从别的语言的stringtable复制过来的,就直接翻译,修改内容即可。

2、在代码中设置控件语言。

在控件所属对话框的类成员函数OnInitDialog()中,设置所属该对话框的控件的内容,比如“确认”“取消”按钮,以及我在对话框中间添加的静态文本框,,它们的控件ID分别为IDOK,IDCANCEL,ID_STATIC,则代码如下:

CString strLoad;
stLoad.LoadString(BTN_OK);
GetDlgItem(IDOK)->SetWindowText(strLoad);//设置“确认”按钮显示的内容

stLoad.LoadString(BTN_CANCLE);
GetDlgItem(IDCANCEL)->SetWindowText(strLoad);//设置“取消”按钮显示的内容

strLoad.LoadString(STATIC_CONTENT);
GetDlgItem(ID_STATIC)->SetWindowText(strLoad);//设置静态文本框显示的内容

 

3、设置线程和UI的语言。

在theApp类对象所属的类成员函数initInstance()中,设置线程和UI语言。函数如下:

LANGID idLang = SetThreadUILanguage(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));//设置线程UI语言为英语
SetThreadLocale(idLang);//设置线程语言和UI语言一致

 

LANGID idLang = SetThreadUILanguage(MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT));//设置线程UI语言为中文
SetThreadUILocale(idLang);//设置线程语言和UI语言一致

设置了线程和UI语言后,在第二步的CString.LoadString(ID)时,程序就会根据设置的语言,读取对应语言的stringtable中对应字符串ID的内容。

 

至此,设置语言的基本功能已经实现了。效果如下:

 

设置语言为英文时:

 

设置语言为中文时:

 

 

至此,实现mfc程序多语言设置的工作基本完成,但在具体实现中,还遇到下面几个问题。

 

1、设置MessageBox按钮的语言。

刚开始做多语言设置时,网上查了很多资料,都说MessageBox中的确认取消按钮的语言,是根据系统语言来变化的,自己设置不了。后来我师父说MessageBoxEx可以实现。比如,我在关闭对话框时,弹出“是否确认关闭对话框”的消息提示,实现如下:

(1)在中英两个stringtable中添加提醒内容:

中文stringtable:

英文stringtable

(2)在对话框的OnClose()消息中添加消息处理:

CString strLoad;
strLoad.LoadString(MSG_BOX_CLOSE);
int iRet = MessageBoxEx(NULL, strLoad, L"Warn", MB_OKCANCEL | MB_ICONWARNING, GetThreadLocale());
if(iRet == IDCANCEL)
{
    return;
}

设置为中文时:

 

设置为英文时:

 

可以看到,只要我们设置了MessageBoxEx函数的最后一个参数,就可以切换MessageBox中的确认取消按钮的语言,但MessageBox的提示内容和标题,还得自己在stringtable中添加,然后在代码中设置。

 

2、菜单。

菜单实现多语言,跟stringtable类似,在资源里,选择该菜单,右键,“插入副本”,然后选择要添加的语言,添加后,直接在菜单上翻译就行。我们在代码里设置了线程和UI语言后,程序会根据设置的语言,自动选择相应语言的菜单。

如果想在代码里动态的修改菜单语言,代码如下:

CMenu*pMainMenu = CMenu::FromHandle(m_wndMenuBar.GetDefaultMenu());
if(pMainMenu != nullptr)
{
    CString strLoad;

    //修改一级菜单,比如文件,工具,视图,设置等
    strLoad.LoadString(MENU_FILE);
    pMainMenu->ModifyMenu(0, MF_BYPOSITION | MF_STRING, 0, strLoad);//修改一级菜单的第一项
    
    strLoad.LoadString(MENU_EDIT);
    pMainMenu->ModifyMenu(1, MF_BYPOSITION | MF_STRING, 0, strLoad);//修改一级菜单的第二项
    
    //以此类推,修改一级菜单的第几项,就将ModifyMenu的第一个参数设置为从0开始的索引值,只要不用响应消息,第三个参数就为0;需要响应消息的话,就必须传入菜单对应的控件ID
    //...

    //修改一级菜单第一项的子菜单(也就是二级菜单),比如文件菜单下的新建文件,打开文件,保存文件,等等
    CMenu*pSubMenu = pMainMenu->GetSubMenu(0);
    if(pSubMenu != nullptr)
    {
        //注意,此时的菜单是需要响应具体消息的,所以ModifyMenu的第三个参数,必须是实际的菜单按钮的ID值,因为消息映射里,消息影响函数是和控件ID绑定的
        strLoad.LoadString(MENU_OPEN_NEW);
        pSubMenu->ModifyMenu(0, MF_BYPOSITION | MF_STRING, IDC_MRU_FILE_NEW, strLoad);
        strLoad.LoadString(MENU_OPEN_FILE);
        pSubMenu->ModifyMenu(1, MF_BYPOSITION | MF_STRING, IDC_MRU_FILE_OPEN, strLoad);
    }
}
//下面这行代码很重要,只要修改了主菜单,必须在修改后加上这行,不然菜单更新不及时
m_wndMenuBar.CreateFromMenu(pMainMenu->GetSafeHmenu(), TRUE, TRUE);
pMainMenu.Detach();

需要注意的是,菜单里的横线也是占据一个索引项的,比如:

注意索引为3和5的横线。

3、多线程的问题。

前面我们也看到了,MFC设置语言,是以线程为单位来设置的,所以需要在每个线程里,都通过调用SetThreadUILanguage和SetThreadLocale设置语言。如果发现某些地方的语言设置没起作用,就先检查是否在该线程中设置了语言。

4、资源访问问题。

如果引用了dll模块,在dll中需要使用dll自带的stringtable资源,那么在LoadString时最好指定dll的资源句柄。

获取dll的资源句柄有两种情况:如果该dll有dllMain函数,该函数的第一个参数就是该dll的资源句柄,将该句柄传给LoadString的第一个参数即可。如果没有dllMain函数,就在该dll的app的initInstance函数中添加如下代码:

HINSTANCE g_instance;

BOOL testDllApp::InitInstance()
{
    CWinApp::InitInstance();
    
    AFX_MODULE_STATE* state = AfxGetModuleState();
    g_instance = state->m_hCurrentInstanceHandle;
    return TRUE;
}

然后将g_instance传给LoadString的第一个参数即可。

 

以上就是我实现mfc程序设置多语言功能的总结。上述代码都是一字一字在网页里编辑的,可能会有手误,望见谅。

 

  • 14
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: MFC(Microsoft Foundation Class)多语言切换可以通过以下几种方法实现。 1. 使用资源文件:MFC支持使用不同的资源文件来存储不同语言的文本、图像等资源。首先,创建一个基本语言的资源文件(例如英文),然后创建其他语言的资源文件,并将其命名为相应的语言代码(例如中文为zh-CN)。接下来,在代码中通过加载对应的资源文件来实现语言切换。 2. 使用多语言库:使用第三方多语言库可以更方便地实现语言切换。这些库可以根据当前系统的语言设置自动加载对应的语言资源,并在界面上显示正确的文本。常见的多语言库包括GetText、Qt Linguist等。 3. 使用资源文件字符串表:在资源文件中创建一个字符串表,其中包含所有需要多语言切换的文本。然后,在代码中根据用户设置语言代码来加载对应的字符串,并在界面上显示。 4. 动态加载语言资源:通过编写一段代码来动态加载语言资源,将对应语言的文本赋值给相应的控件,并刷新界面。这种方法需要提前准备好不同语言的文本资源,并通过代码控制切换。 无论使用哪种方法,都需要在代码中添加逻辑来切换语言,可以通过用户界面设置、系统语言设置或其他方式来确定使用哪种语言。在切换语言后,需要重新加载相应的语言资源,并刷新界面以显示新的语言。 ### 回答2: MFC语言切换的实现方法主要有以下几种: 1. 使用资源文件:在MFC应用程序中,可以将不同语言的文本信息存储在不同的资源文件中,然后通过加载不同的资源文件来实现语言切换。每个资源文件都对应一种语言,通过读取不同的资源文件,可以获取相应语言的文本信息,并将其显示在界面上。 2. 使用国际化库:可以使用一些开源的国际化库,如gettext等,来实现MFC应用程序的多语言切换。这些库提供了一些函数和接口,可以根据当前的语言设置,从对应的语言文件中获取文本信息,并将其显示在界面上。 3. 手动切换语言:可以在代码中手动实现语言切换的逻辑。通过在程序中定义一些全局变量来表示当前的语言设置,然后根据不同的语言设置,从相应的语言文件中获取对应的文本信息,并将其显示在界面上。当需要切换语言时,可以通过用户的操作或者设置来改变当前的语言设置。 无论使用何种方法,都需要在应用程序的各个界面和对话框中统一使用资源文件或者函数来获取文本信息,从而实现整个应用程序的多语言切换。同时,还需要注意对齐文本的布局和调整控件的大小,以适应不同语言的文本长度和字符宽度的差异。 ### 回答3: MFC(Microsoft Foundation Classes)多语言切换可以通过以下几个步骤实现: 1. 提前准备好多语言的资源文件:对于每一种语言,创建对应的字符串表和对话框资源文件,并为每个控件提供相应的文字和提示信息。 2. 在MFC应用程序的初始化过程中,根据用户所选语言加载对应的资源文件。可以通过读取系统的语言设置或者用户自定义选择来确定加载哪种语言的资源文件。 3. 在应用程序的实例化和初始化完成之后,在每一个窗口的初始化过程中,调用相应的函数来切换语言。例如,可以使用 AfxSetResourceHandle 函数来设置当前语言的资源句柄。 4. 在对话框或窗口类中重写虚函数 OnIniDialog 或 OnInitInstance,在函数中调用对应的语言切换函数,例如 SetWindowText 或 SetDlgItemText 来更新窗口中控件的文本。 5. 如果需要切换界面语言而不需要重启应用程序,可以在对话框的响应事件中或者菜单项的点击事件中调用相应的语言切换函数。例如,可以使用 SetWindowText 或 SetDlgItemText 来更新当前对话框中控件的文本。 6. 使用资源编辑器,为每个对话框和控件设置唯一的资源ID。然后,在代码中使用相应的ID来获取和设置对应的文本。可以通过调用 GetDlgItemText 或 SetDlgItemText 函数来实现。 通过以上步骤,我们可以在MFC应用程序实现语言切换,让用户能够根据自己的需求选择使用不同的语言界面。这样可以提高用户体验,使应用程序更具国际化和多元化特色。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值