#pragma once #include #include static std::wstring StringToWString (const std::string &str, UINT codePage = CP_ACP) { if (str.empty ()) return std::wstring (); int len = MultiByteToWideChar (codePage, 0, str.c_str (), -1, nullptr, 0); if (len == 0) return std::wstring (); std::wstring wstr (len - 1, L'\0'); MultiByteToWideChar (codePage, 0, str.c_str (), -1, &wstr [0], len); return wstr; } #undef GetLocaleInfo /// /// 获取指定 LCID 的区域设置信息(ANSI 版本)。 /// /// 区域标识符(LCID)。 /// 要获取的信息类型(LCTYPE)。 /// 以 ANSI 字符串形式返回的区域设置信息。 std::string GetLocaleInfoA (LCID code, LCTYPE type) { char buf [LOCALE_NAME_MAX_LENGTH] = {0}; GetLocaleInfoA (code, type, buf, LOCALE_NAME_MAX_LENGTH); return buf; } /// /// 获取指定 LCID 的区域设置信息(Unicode 版本)。 /// /// 区域标识符(LCID)。 /// 要获取的信息类型(LCTYPE)。 /// 以宽字符串形式返回的区域设置信息。 std::wstring GetLocaleInfoW (LCID code, LCTYPE type) { WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; GetLocaleInfoW (code, type, buf, LOCALE_NAME_MAX_LENGTH); return buf; } /// /// 获取指定 LCID 的区域设置信息(宽字符串输出)。 /// /// 区域标识符(LCID)。 /// 要获取的信息类型(LCTYPE)。 /// 接收信息的宽字符串引用。 void GetLocaleInfo (LCID code, LCTYPE type, std::wstring &output) { output = GetLocaleInfoW (code, type); } /// /// 获取指定 LCID 的区域设置信息(ANSI 字符串输出)。 /// /// 区域标识符(LCID)。 /// 要获取的信息类型(LCTYPE)。 /// 接收信息的 ANSI 字符串引用。 void GetLocaleInfo (LCID code, LCTYPE type, std::string &output) { output = GetLocaleInfoA (code, type); } /// /// 获取指定区域名称的区域设置信息(扩展版本,支持 Windows Vista+)。 /// /// 区域名称(如 "en-US")。 /// 要获取的信息类型(LCTYPE)。 /// 接收信息的宽字符串引用。 /// 成功返回非零值,失败返回 0;如果 lpLocaleName 无效,则函数会返回 0。 int GetLocaleInfoEx (std::wstring lpLocaleName, LCTYPE type, std::wstring &output) { WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; int res = GetLocaleInfoEx (lpLocaleName.c_str (), type, buf, LOCALE_NAME_MAX_LENGTH); if (&output) output = std::wstring (buf); return res; } #undef SetLocaleInfo /// /// 设置指定 LCID 的区域设置信息(ANSI 版本)。 /// /// 区域标识符(LCID)。 /// 要设置的信息类型(LCTYPE)。 /// 要设置的数据(ANSI 字符串)。 /// 成功返回非零值,失败返回 0。 BOOL SetLocaleInfoA (LCID code, LCTYPE type, const std::string &lcData) { return SetLocaleInfoA (code, type, lcData.c_str ()); } /// /// 设置指定 LCID 的区域设置信息(Unicode 版本)。 /// /// 区域标识符(LCID)。 /// 要设置的信息类型(LCTYPE)。 /// 要设置的数据(宽字符串)。 /// 成功返回非零值,失败返回 0。 BOOL SetLocaleInfoW (LCID code, LCTYPE type, const std::wstring &lcData) { return SetLocaleInfoW (code, type, lcData.c_str ()); } /// /// 设置指定 LCID 的区域设置信息(宽字符串重载)。 /// /// 区域标识符(LCID)。 /// 要设置的信息类型(LCTYPE)。 /// 要设置的数据(宽字符串)。 /// 成功返回非零值,失败返回 0。 BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::wstring &lcData) { return SetLocaleInfoW (code, type, lcData); } /// /// 设置指定 LCID 的区域设置信息(ANSI 字符串重载)。 /// /// 区域标识符(LCID)。 /// 要设置的信息类型(LCTYPE)。 /// 要设置的数据(ANSI 字符串)。 /// 成功返回非零值,失败返回 0。 BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::string &lcData) { return SetLocaleInfoA (code, type, lcData); } /// /// 从 LCID 获取受限区域代码(如 "en"),ANSI 版本。 /// /// 区域标识符。 /// 受限区域代码的 ANSI 字符串。 std::string GetLocaleRestrictedCodeFromLcidA (LCID lcid) { return GetLocaleInfoA (lcid, 89); } /// /// 从 LCID 获取受限区域代码(如 "en"),Unicode 版本。 /// /// 区域标识符。 /// 受限区域代码的宽字符串。 std::wstring GetLocaleRestrictedCodeFromLcidW (LCID lcid) { return GetLocaleInfoW (lcid, 89); } /// /// 从 LCID 获取受限区域代码(ANSI 输出)。 /// /// 区域标识符。 /// 输出 ANSI 字符串。 void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::string &ret) { ret = GetLocaleRestrictedCodeFromLcidA (lcid); } /// /// 从 LCID 获取受限区域代码(宽字符串输出)。 /// /// 区域标识符。 /// 输出宽字符串。 void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::wstring &ret) { ret = GetLocaleRestrictedCodeFromLcidW (lcid); } /// /// 从 LCID 获取详细区域代码(如 "US"),ANSI 版本。 /// /// 区域标识符。 /// 详细区域代码的 ANSI 字符串。 std::string GetLocaleElaboratedCodeFromLcidA (LCID lcid) { return GetLocaleInfoA (lcid, 90); } /// /// 从 LCID 获取详细区域代码(如 "US"),Unicode 版本。 /// /// 区域标识符。 /// 详细区域代码的宽字符串。 std::wstring GetLocaleElaboratedCodeFromLcidW (LCID lcid) { return GetLocaleInfoW (lcid, 90); } /// /// 从 LCID 获取详细区域代码(宽字符串输出)。 /// /// 区域标识符。 /// 输出宽字符串。 void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::wstring &ret) { ret = GetLocaleElaboratedCodeFromLcidW (lcid); } /// /// 从 LCID 获取详细区域代码(ANSI 输出)。 /// /// 区域标识符。 /// 输出 ANSI 字符串。 void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::string &ret) { ret = GetLocaleElaboratedCodeFromLcidA (lcid); } /// /// 将宽字符串形式的区域名称转换为 LCID。 /// /// 区域名称(如 L"en-US")。 /// 对应的 LCID;若失败返回 0。 LCID LocaleCodeToLcidW (const std::wstring &localeCode) { #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) try { BYTE buf [LOCALE_NAME_MAX_LENGTH * sizeof (WCHAR)] = {0}; int res = GetLocaleInfoEx (localeCode.c_str (), LOCALE_RETURN_NUMBER | LOCALE_ILANGUAGE, (LPWSTR)buf, LOCALE_NAME_MAX_LENGTH); LCID lcid = *((LCID *)buf); return lcid; } catch (const std::exception &e) {} return LocaleNameToLCID (localeCode.c_str (), 0); #else return LocaleNameToLCID (localeCode.c_str (), 0); #endif } /// /// 将 ANSI 字符串形式的区域名称转换为 LCID。 /// /// 区域名称(如 "en-US")。 /// 对应的 LCID;若失败返回 0。 LCID LocaleCodeToLcidA (const std::string &localeCode) { std::wstring lcWide = StringToWString (std::string (localeCode)); return LocaleCodeToLcidW (lcWide.c_str ()); } /// /// 将宽字符串区域名称转换为 LCID(重载)。 /// /// 区域名称(宽字符串)。 /// 对应的 LCID。 LCID LocaleCodeToLcid (const std::wstring &loccode) { return LocaleCodeToLcidW (loccode.c_str ()); } /// /// 将 ANSI 字符串区域名称转换为 LCID(重载)。 /// /// 区域名称(ANSI 字符串)。 /// 对应的 LCID。 LCID LocaleCodeToLcid (const std::string &loccode) { return LocaleCodeToLcidA (loccode.c_str ()); } /// /// 根据区域名称获取受限区域代码(ANSI 版本,接受 C 字符串)。 /// /// 区域名称(如 "en-US")。 /// 受限区域代码的 ANSI 字符串。 std::string GetLocaleRestrictedCodeA (LPCSTR lc) { return GetLocaleInfoA (LocaleCodeToLcidA (lc), 89); } /// /// 根据区域名称获取受限区域代码(ANSI 版本,接受 std::string)。 /// /// 区域名称(std::string)。 /// 受限区域代码的 ANSI 字符串。 std::string GetLocaleRestrictedCodeA (const std::string &lc) { return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 89); } /// /// 根据区域名称获取受限区域代码(Unicode 版本,接受 C 宽字符串)。 /// /// 区域名称(如 L"en-US")。 /// 受限区域代码的宽字符串。 std::wstring GetLocaleRestrictedCodeW (LPCWSTR lc) { return GetLocaleInfoW (LocaleCodeToLcidW (lc), 89); } /// /// 根据区域名称获取受限区域代码(Unicode 版本,接受 std::wstring)。 /// /// 区域名称(std::wstring)。 /// 受限区域代码的宽字符串。 std::wstring GetLocaleRestrictedCodeW (const std::wstring &lc) { return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 89); } /// /// 根据区域名称获取受限区域代码(宽字符串重载)。 /// /// 区域名称(std::wstring)。 /// 受限区域代码的宽字符串。 std::wstring GetLocaleRestrictedCode (const std::wstring &lc) { return GetLocaleRestrictedCodeW (lc); } /// /// 根据区域名称获取受限区域代码(ANSI 字符串重载)。 /// /// 区域名称(std::string)。 /// 受限区域代码的 ANSI 字符串。 std::string GetLocaleRestrictedCode (const std::string &lc) { return GetLocaleRestrictedCodeA (lc); } /// /// 根据区域名称获取详细区域代码(ANSI 版本,接受 C 字符串)。 /// /// 区域名称(如 "en-US")。 /// 详细区域代码的 ANSI 字符串。 std::string GetLocaleElaboratedCodeA (LPCSTR lc) { return GetLocaleInfoA (LocaleCodeToLcidA (lc), 90); } /// /// 根据区域名称获取详细区域代码(ANSI 版本,接受 std::string)。 /// /// 区域名称(std::string)。 /// 详细区域代码的 ANSI 字符串。 std::string GetLocaleElaboratedCodeA (const std::string &lc) { return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 90); } /// /// 根据区域名称获取详细区域代码(Unicode 版本,接受 C 宽字符串)。 /// /// 区域名称(如 L"en-US")。 /// 详细区域代码的宽字符串。 std::wstring GetLocaleElaboratedCodeW (LPCWSTR lc) { return GetLocaleInfoW (LocaleCodeToLcidW (lc), 90); } /// /// 根据区域名称获取详细区域代码(Unicode 版本,接受 std::wstring)。 /// /// 区域名称(std::wstring)。 /// 详细区域代码的宽字符串。 std::wstring GetLocaleElaboratedCodeW (const std::wstring &lc) { return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 90); } /// /// 根据区域名称获取详细区域代码(宽字符串重载)。 /// /// 区域名称(std::wstring)。 /// 详细区域代码的宽字符串。 std::wstring GetLocaleElaboratedCode (const std::wstring &lc) { return GetLocaleElaboratedCodeW (lc); } /// /// 根据区域名称获取详细区域代码(ANSI 字符串重载)。 /// /// 区域名称(std::string)。 /// 详细区域代码的 ANSI 字符串。 std::string GetLocaleElaboratedCode (const std::string &lc) { return GetLocaleElaboratedCodeA (lc); } /// /// 将 LCID 转换为区域名称(ANSI 格式,如 "en-US")。 /// /// 区域标识符。 /// 分隔符,默认为 '-'。 /// 区域名称的 ANSI 字符串。 std::string LcidToLocaleCodeA (LCID lcid, char divide = '-') { return GetLocaleRestrictedCodeFromLcidA (lcid) + divide + GetLocaleElaboratedCodeFromLcidA (lcid); } /// /// 将 LCID 转换为区域名称(Unicode 格式,如 L"en-US")。 /// /// 区域标识符。 /// 分隔符,默认为 L'-'。 /// 区域名称的宽字符串。 std::wstring LcidToLocaleCodeW (LCID lcid, WCHAR divide = L'-') { #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) try { WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; LCIDToLocaleName (lcid, buf, LOCALE_NAME_MAX_LENGTH, 0); return buf; } catch (const std::exception &e) {} return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid); #else return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid); #endif } /// /// 将 LCID 转换为区域名称(宽字符串重载)。 /// /// 区域标识符。 /// 分隔符,默认为 L'-'。 /// 区域名称的宽字符串。 std::wstring LcidToLocaleCode (LCID lcid, WCHAR divide = L'-') { return LcidToLocaleCodeW (lcid, divide); } /// /// 将 LCID 转换为区域名称(ANSI 字符串重载)。 /// /// 区域标识符。 /// 分隔符,默认为 '-'。 /// 区域名称的 ANSI 字符串。 std::string LcidToLocaleCode (LCID lcid, char divide = '-') { return LcidToLocaleCodeA (lcid, divide); } /// /// 获取当前用户的默认区域名称(Unicode)。 /// /// 用户默认区域名称的宽字符串。 std::wstring GetUserDefaultLocaleName () { #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) try { WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH); return buf; } catch (const std::exception &e) {} return LcidToLocaleCodeW (GetUserDefaultLCID ()); #else return LcidToLocaleCodeW (GetUserDefaultLCID ()); #endif } /// /// 获取系统默认的区域名称(Unicode)。 /// /// 系统默认区域名称的宽字符串。 std::wstring GetSystemDefaultLocaleName () { #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) try { WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH); return buf; } catch (const std::exception &e) {} return LcidToLocaleCodeW (GetSystemDefaultLCID ()); #else return LcidToLocaleCodeW (GetSystemDefaultLCID ()); #endif } /// /// 获取当前计算机的区域设置名称(优先使用线程区域,然后用户默认,最后系统默认)。 /// /// 计算机区域名称的宽字符串。 std::wstring GetComputerLocaleCodeW () { #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) { try { { LCID lcid = GetThreadLocale (); std::wstring tmp = LcidToLocaleCodeW (lcid); if (lcid && tmp.length () > 1) return tmp; } { WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH); if (lstrlenW (buf)) return buf; } { WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH); return buf; } } catch (const std::exception &e) {} LCID lcid = GetThreadLocale (); if (!lcid) lcid = GetUserDefaultLCID (); if (!lcid) lcid = GetSystemDefaultLCID (); return LcidToLocaleCodeW (lcid); } #else { LCID lcid = GetThreadLocale (); if (!lcid) lcid = GetUserDefaultLCID (); if (!lcid) lcid = GetSystemDefaultLCID (); return LcidToLocaleCodeW (lcid); } #endif } /// /// 比较两个区域名称是否相等(支持字符串直接比较或通过 LCID 比较)。 /// /// 左区域名称。 /// 右区域名称。 /// 如果区域名称相同(字符串相等或 LCID 相等)则返回 true,否则 false。 /// 注意:此处使用的 std::wnstring::equals 非标准,可能为自定义函数,实际应替换为 wstring 比较。 bool LocaleNameCompare (const std::wstring &left, const std::wstring &right) { return std::wnstring::equals (left, right) || LocaleCodeToLcidW (left) == LocaleCodeToLcidW (right); }