热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

XP下MFC程序本地化的坑

MFC的本地化方案在MFC程序中,本地化是通过资源文件来完成的。菜单栏、对话框、字符串,图片等等资源都支持多个语言的副本。在框架内部,是通过CreateDialog、DialogB

MFC 的本地化方案

在 MFC 程序中,本地化是通过资源文件来完成的。菜单栏、对话框、字符串,图片等等资源都支持多个语言的副本。



在框架内部,是通过 CreateDialog、DialogBox、LoadMenu、LoadString、FindResource 来查找资源的。比如查找字符串:

inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage(
_In_ HINSTANCE hInstance,
_In_ UINT id) throw()
{
HRSRC hResource;
/*
The and operation (& static_cast(~0)) protects the expression from being greater
than WORD - this would cause a runtime error when the application is compiled with /RTCc flag.
*/
hResource = ::FindResourceW(hInstance, MAKEINTRESOURCEW( (((id>>4)+1) & static_cast(~0)) ), (LPWSTR) RT_STRING);
if( hResource == NULL )
{
return( NULL );
}
return _AtlGetStringResourceImage( hInstance, hResource, id );
}

这些函数有个特点:跟根据当前线程语言环境来定位资源

当一个线程创建时,它使用用户语言环境。该值由 GetUserDefaultLCID 返回。

也就是说,在默认情况下资源加载是根据用户的区域设置来的决定。


改变线程语言环境

使用 SetThreadLocale 可以改变当前线程的区域设置。从而可以改变 MFC 加载资源的语言。

::SetThreadLocale(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); // 将语言环境改为 英语(美国)
CString title;
title.LoadString(AFX_IDS_APP_TITLE); // 会尝试加载 英语(美国) 字符资源

但是缺点很明显,这会影响所有涉及到字符串操作的地方,比如在中文系统上,线程语言改为英文,为用户提供一个通用对话框:

::SetThreadLocale(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
CFileDialog dlg...
...

如果此时用户选了一个带有中文字符的路径,对话框将会得到一些乱码路径,问题还不仅仅只是这里而已。

所以不要使用 SetThreadLocale 来修改语言环境,除非你清楚自己在做什么。

正确做法应该是自行通过 FindResourceExA 来查找资源,这个函数不受线程语言影响,可以指定语言,但是缺点很明显,无法再使用 MFC 自带的一些加载资源的方法了。


线程UI语言

从 Vista 开始,提出了一个线程UI语言的概念,这解决了上面提到的SetThreadLocale影响全局的问题。通过 SetThreadUILanguage 或 SetThreadPreferredUILanguages 来改变当前线程的UI语言,而它仅仅只影响资源加载时的语言版本,不会影响线程的语言设置

LCID loc = ::GetThreadLocale(); // 2052
::SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
loc = ::GetThreadLocale(); // 还是 2052

但是坑的是这个函数在XP下等同于SetThreadLocale

LCID loc = ::GetThreadLocale(); // 2052
::SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
loc = ::GetThreadLocale(); // 1033

XP下的多语言解决方案

因为 XP 系统没有将线程语言和UI语言分离,所以不可以使用SetThreadLocaleSetThreadUILanguage去解决UI多语言问题。

有其他两个方案选择:



  1. 为每种语言单独制作一个资源型DLL,在APP初始化前用 AfxSetResourceHandle 设置特定语言DLL的句柄,这样之后任何资源加载都会从这里获取。

  2. 非常规手段,Hook FindResource,然后转发给 FindResourceEx,因为 FindResourceEx 可以指定语言。

第一种方法属于正规手段,但是很繁琐,工程会比较多。

第二种方法理论上可行,但没有实践,不再展开讨论。


参考

用户界面语言管理

SetThreadLocale function

SetThreadUILanguage function

创建纯资源 DLL

MFC 组件的本地化

MFC基于对话框使用dll进行多语言切换



推荐阅读
  • PHP中实现美观的对话框界面与10个相关教程推荐
    本文探讨了如何在PHP应用中创建美观且功能强大的对话框界面,并推荐了10篇关于对话框设计与实现的专业教程。 ... [详细]
  • 本文详细介绍了如何在MFC(Microsoft Foundation Classes)应用程序中使用树形控件(Tree Control)。通过创建基于对话框的应用程序,并逐步添加和配置树形控件,最终实现带有图标的树形结构。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 本文介绍如何通过注册表编辑器自定义和优化Windows文件右键菜单,包括删除不需要的菜单项、添加绿色版或非安装版软件以及将特定应用程序(如Sublime Text)添加到右键菜单中。 ... [详细]
  • 如何高效创建和使用字体图标
    在Web和移动开发中,为什么选择字体图标?主要原因是其卓越的性能,可以显著减少HTTP请求并优化页面加载速度。本文详细介绍了从设计到应用的字体图标制作流程,并提供了专业建议。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 帝国CMS多图上传插件详解及使用指南
    本文介绍了一款用于帝国CMS的多图上传插件,该插件通过Flash技术实现批量图片上传功能,显著提升了多图上传效率。文章详细说明了插件的安装、配置和使用方法。 ... [详细]
  • 本文介绍如何使用Python进行文本处理,包括分词和生成词云图。通过整合多个文本文件、去除停用词并生成词云图,展示文本数据的可视化分析方法。 ... [详细]
  • 本文探讨了如何在 PHP 的 Eloquent ORM 中实现数据表之间的关联查询,并通过具体示例详细解释了如何将关联数据嵌入到查询结果中。这不仅提高了数据查询的效率,还简化了代码逻辑。 ... [详细]
  • 在MFC开发中,TreeCtrl控件因其强大的层次结构展示能力而被广泛应用,例如在资源管理器视图中。本文将详细介绍如何高效地利用TreeCtrl控件,包括设置属性、添加项目以及使用图像列表等技巧。 ... [详细]
  • 本篇教程将继续深入探讨GDI+绘图技术,解决在使用过程中可能出现的文件覆盖保存问题,并提供详细的代码示例和解决方案。通过本教程,读者将能够更好地理解GDI+绘图机制,避免常见的错误。 ... [详细]
  • 请看|差别_Android 6.0 运行时权限处理解析
    请看|差别_Android 6.0 运行时权限处理解析 ... [详细]
author-avatar
345877103_b54cd7
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有