关于c ++:我可以从语言首选项中获取代码页吗?

Can I get a code page from a language preference?

Windows似乎至少跟踪"当前语言环境"的四个方面:
http://www.siao2.com/2005/02/01/364707.aspx

  • 默认用户位置
  • 默认系统位置
  • 预设使用者介面语言
  • 默认输入位置

我的大脑只是试图跟踪四个单独的区域设置对您有用的东西而感到痛苦。

但是,我不理解代码页与语言环境(或LCID或语言ID)之间的关系,它们似乎都不同(例如,日语(日本)为LANGID = 0x411位置代码1,但代码页日本是932)。

在Unicode和窄字符串之间转换时,如何配置我们的应用程序以使用用户期望的语言作为默认MBCS目标?

也就是说,我们曾经是MBCS应用程序。然后我们切换到Unicode。事情在英语下运行良好,但在亚洲语言下却失败,这显然是因为Windows转换功能WideCharToMultiByteMultiByteToWideChar带有显式的代码页(不是区域设置ID或语言ID),可以将其设置为CP_ACP(默认为ANSI代码页),但似乎没有"默认为用户默认界面语言的代码页"的值。

我的意思是,这是一些令人费解的问题。"当前语言"的四个独立维度,三种不同的标识符类型以及C库和C ++标准库的(不同)字符串标识符。

在我们以前的MBCS构建中,磁盘I / O和用户I / O可以正常工作:所有内容保留在DEFAULT SYSTEM LOCALE(Windows XP术语:"非Unicode程序的语言")中。但是现在,在我们的UNICODE构建中,所有内容都尝试使用" C"作为语言环境,并且文件I / O无法将UNICODE正确地转码为用户的语言环境,反之亦然。

我们希望使用当前用户的语言代码页将文本文件写出来(窄时)。并且当读入时,当前用户的语言代码页应转换回UNICODE。

救命!!!

澄清:理想情况下,我想使用MUI语言代码页而不是OS默认代码页。 GetACP()返回系统默认代码页,但是我不知道该函数返回用户选择的MUI语言(如果未指定/未安装MUI,则该语言会自动恢复为系统默认语言)。


我同意Jon Trauntvein的评论,GetACP函数的确反映了控制面板中用户的语言设置。另外,基于您提供的"全力以赴"博客的链接,默认用户界面语言是Windows用户界面将使用的语言,与程序所使用的语言不同。

但是,如果您确实要使用DEFAULT USER INTERFACE LANGUAGE,则可以通过调用GetUserDefaultUILanguage来获得它,然后可以使用下表将语言ID映射到代码页。
语言标识符和语言环境

您还可以使用GetLocaleInfo函数进行映射,但是首先您必须将从GetUserDefaultUILanguage获得的语言ID转换为语言环境ID,我认为您将获得代码页的名称,而不是一个数值,但您可以尝试看看。


如果您只想配置一个语言环境对象以使用当前选择的语言环境设置,那么您应该能够执行以下操作:

1
std::locale loc = std::locale("");

您还可以使用Win32 :: GetACP()函数在Windows中访问当前代码页。这是我在字符串类中实现的将多字节字符附加到unicode字符串的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void StrUni::append_mb(char const *buff, size_t buff_len)
{
    UINT current_code_page = ::GetACP();
    int space_needed;

    if(buff_len == 0)
       return;
    space_needed = ::MultiByteToWideChar(
       current_code_page,
       MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
       buff,
       buff_len,
       0,
       0);
    if(space_needed > 0)
    {
       reserve(this->buff_len + space_needed + 1);
       MultiByteToWideChar(
          current_code_page,
          MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
          buff,
          buff_len,
          storage + this->buff_len,
          space_needed);
       this->buff_len += space_needed;
       terminate();
    }
}


FWIW,这就是我最终要做的事情:

  • #define _CONVERSION_DONT_USE_THREAD_LOCALE // force CP_ACP *not* CP_THREAD_ACP for MFC CString auto-conveters!!!
  • 在应用程序启动中,构造所需的语言环境:m_locale(FStringA(".%u", GetACP()).GetString(), LC_CTYPE)
  • 强制其与GetACP()达成一致:// force C++ and C libraries based on setlocale() to use system locale for narrow strings
    m_locale = ::std::locale::global(m_locale); // we store the previous global so we can restore before termination to avoid memory loss
  • 这使我相对理想地使用了CString中MFC内置的窄范围宽转换,以便在从当前语言环境转换为MBCS字符串或从其转换时自动使用用户的默认语言。

    注意:m_locale是类型::std::locale


    只需使用CW2A()或CA2W(),它们就会使用当前的系统区域设置(或用于非Unicode应用程序的语言)为您完成转换。