c++ - Building application with different language specified in resource.rc
问题描述
I never done something like this, so this is my first attempt. From reading online different information and tutorials, I can confidently say that I got very confused so I went on my own with this.
What I am trying to achieve is have different build configurations with different languages for the GUI.
My application is Win32 built using Visual Studio 2019.
Steps I tried:
- Cloned my existing Release build
- Opened up my .rc file in Notepad++ and cloned the "default" language sections
- Changed the language macro in the cloned sections ( LANGUAGE LANG_VIETNAMESE, SUBLANG_DEFAULT)
- Translated everything from Menu, Dialogs, etc.
- Reloaded in visual studio, and I can see 2x set of all resources. ( menu, dialogs, everything in 2 sets - 1 english and 1 vietnamese )
- Opened up project propierties -> Resources and changed Culture to Vietnamese
- Built the project successfully
However the result is nothing. The menu and dialogs are still in English.
Is there something else I must do to specify which set of resources to use to obtain a different language build ?
Or am I over complicating this and going all wrong...
Any advice/examples are much appreciated.
解决方案
看来我会回答我自己的问题,因为我相信其他人也遇到了这个问题。
更改 Windows GUI 应用程序语言的正确官方方法是:
使用此功能,以及我在问题中所做的确切事情;该函数将在运行时应用该语言的资源。(菜单,对话框,一切)
我的情况很简单:
SetThreadUILanguage(MAKELANGID(LANG_VIETNAMESE, SUBLANG_VIETNAMESE_VIETNAM));
但是在我的情况下,我正在为每种语言创建构建,所以如果您想允许用户在运行时更改语言,请参阅注释和这篇文章。
这样做的非官方方式需要更多的工作,但非常稳定且不易出错。
- 您必须用该语言翻译和重建您的菜单
- 您必须翻译和重命名每种语言的每个对话 ID,并显示每种语言的对话 ID
对于社区和其他开发人员,我将分享重建菜单的代码:
// Find our Menu resource based on desired language
HRSRC hRes = FindResourceExW(hInstance, RT_MENU, MAKEINTRESOURCE(IDC_APPLICATION), MAKELANGID(LANG_VIETNAMESE, SUBLANG_VIETNAMESE_VIETNAM));
if (!hRes) {
wchar_t buf[MAX_PATH] = { 0 };
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
MessageBoxW(0, buf, _TEXT(L"FindResourceExW Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
// Load our Menu resource based on desired language
HGLOBAL hGlo = LoadResource(hInstance, hRes);
if (!hGlo) {
wchar_t buf[MAX_PATH] = { 0 };
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
MessageBoxW(0, buf, _TEXT(L"LoadResource Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
// Lock the resource
LPVOID pData = LockResource(hGlo);
if (pData == NULL) {
wchar_t buf[MAX_PATH] = { 0 };
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
MessageBoxW(0, buf, _TEXT(L"LockResource Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
// Load the new Menu into memory
HMENU hMenu = LoadMenuIndirectW((MENUTEMPLATE*)pData);
if (!hMenu) {
wchar_t buf[MAX_PATH] = { 0 };
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
MessageBoxW(0, buf, _TEXT(L"LoadMenuIndirectW Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
// Get our default Menu
HMENU hMenu_old = GetMenu(g_Hwnd);
// Set no Menu
SetMenu(g_Hwnd, NULL);
// Erase default Menu
DestroyMenu(hMenu_old);
// Set our new Menu
SetMenu(g_Hwnd, hMenu);
// Draw our new Menu
DrawMenuBar(g_Hwnd);
注意:如果您想使用FindResourceEx搜索字符串,由于RT_STRING会更复杂,因此请在浪费时间之前先查看此内容。
享受!
推荐阅读
- javascript - 如何在反应中更改导航栏标题的值?
- python - 检查文件是否已处理的最佳方法
- java - 在 iText7 中创建 PdfTextFormField 专门用于数字输入
- android - android 应用程序是否可以使用 manifest.xml 文件中未声明的权限?
- c++ - 使用 WM_TIMER 绘制分段连续函数
- reactjs - 远程调试时反应本机组件不会更新
- stripe-payments - 分条付款 - 单次收费的最高金额为 $999,999.99
- python-3.x - 在 python 中使用 cv2.drawcontours() 时出错
- javascript - ES6 功能不可用
- angular - 从 Cordova android 应用程序下载 .xlsx 文件的问题