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

Can I get a code page from a language preference?

本文关键字:获取 取代码 语言 我可以      更新时间:2023-10-16

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

  • 默认用户区域设置
  • 默认系统区域设置
  • 默认用户界面语言
  • 默认输入区域设置

我的大脑很痛,只是想知道四个不同的地方对什么有用。。。

然而,我不了解代码页和区域设置(或LCID,或Language ID)之间的关系,所有这些似乎都是不同的(例如,日语(Japan)是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语言代码页,而不是操作系统默认代码页。GetACP()返回系统默认代码页,但我不知道有一个函数会返回用户选择的MUI语言(如果没有指定/安装MUI,它会自动恢复为系统默认语言)

我同意Jon Trauntvein的评论,GetACP函数确实反映了控制面板中用户的语言设置。此外,根据您提供的"整理一切"博客链接,DEFAULT USER INTERFACE LANGUAGE是Windows用户界面将使用的语言,与程序使用的语言不同。

但是,如果您真的想使用DEFAULT USER INTERFACE LANGUAGE,那么您可以通过调用GetUserDefaultUILanguage来获得它,然后您可以使用下表将语言id映射到代码页。语言标识符和区域

您也可以使用GetLocaleInfo函数来进行映射,但首先您必须将从GetUserDefaultUILanguage获得的语言id转换为区域设置id,我认为您将获得代码页的名称,而不是数值,但您可以尝试并查看。

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

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

您还可以使用Win32::GetACP()函数访问窗口中的当前代码页。以下是我在字符串类中实现的一个示例,用于将多字节字符附加到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();
    }
}

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

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

这使我能够相对理想地使用MFC的内置窄<->CString中的宽转换,以便在转换到当前语言环境的MBCS字符串或从当前语言环境转换MBCS字符串时自动使用用户的默认语言。

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