我可以从语言偏好中获取代码页吗?

时间:2013-08-19 17:43:25

标签: c++ windows winapi localization locale

Windows似乎跟踪“当前区域设置”的至少四个维度: http://www.siao2.com/2005/02/01/364707.aspx

  • DEFAULT USER LOCALE
  • DEFAULT SYSTEM LOCALE
  • 默认用户界面语言
  • DEFAULT INPUT LOCALE

我的大脑只是试图跟踪四个单独的语言环境对...有用...

但是,我没有理解代码页和语言环境(或LCID或语言ID)之间的关系,所有这些关系看起来都不同(例如日语(日语)是LANGID = 0x411位置代码1 ,但日本的代码页是932)。

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

也就是说,我们曾经是MBCS应用程序。然后我们切换到Unicode。事情在英语中运作良好,但在亚洲语言中失败,显然是因为Windows转换函数WideCharToMultiByteMultiByteToWideChar采用显式代码页(不是语言环境ID或语言ID),可以将其设置为{{ 1}}(默认为ANSI代码页),但似乎没有“默认为用户的默认界面语言代码页”的值。

我的意思是,这是一些非常复杂的琐事。 “当前语言”的四个独立维度,三种不同的标识符类型,以及C库和C ++标准库的(不同的)字符串标识符。

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

我们希望使用当前用户的语言代码页写出文件(缩小时)。在读入时,当前用户的语言代码页应该转换回UNICODE。

帮助!!!

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

4 个答案:

答案 0 :(得分:2)

我同意Jon Trauntvein的评论,GetACP功能确实反映了控制面板中用户的语言设置。此外,根据您提供的“全部排序”博客的链接,DEFAULT USER INTERFACE LANGUAGE是Windows用户界面将使用的语言,与程序使用的语言不同。 / p>

但是,如果您真的想使用DEFAULT USER INTERFACE LANGUAGE,那么您可以通过调用GetUserDefaultUILanguage来获取它,然后您可以使用下表将语言ID映射到代码页。 Language Identifiers and Locales

你也可以使用GetLocaleInfo函数进行映射,但首先你必须将你从GetUserDefaultUILanguage获得的语言ID转换为语言环境ID,我想你会得到代码页的名称而不是数字值,但您可以尝试并查看。

答案 1 :(得分:1)

如果你想要做的就是配置一个语言环境对象来使用当前选择的语言环境设置,你应该能够做到这样的事情:

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

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

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();
    }
}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

  1. #define _CONVERSION_DONT_USE_THREAD_LOCALE // force CP_ACP *not* CP_THREAD_ACP for MFC CString auto-conveters!!!
  2. 在应用程序启动时,构建所需的区域设置:m_locale(FStringA(".%u", GetACP()).GetString(), LC_CTYPE)
  3. 强制它同意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
  4. 这让我在CString中相对理想地使用MFC内置的窄 - 宽转换,以便在转换为当前区域设置的MBCS字符串时自动使用用户的默认语言。

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