ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Codejock Xtreme ToolkitPro v13.2.1 中文汉化包实战指南

Codejock Xtreme ToolkitPro v13.2.1 中文汉化包实战指南

简介:这份汉化包面向使用 Codejock Xtreme ToolkitPro v13.2.1 的 MFC 开发者,专门解决原版界面库菜单、对话框、工具栏及 VC2005 应用向导均为英文、不利于中文团队高效开发的问题。压缩包体积仅 573KB,却收纳了 410 个文件:除 h 头文件、cpp 源文件与 rc 资源脚本外,还包含大量 bmp/gif/ico 图形资源、htm 帮助页面、rtf 说明文档以及 bat 辅助脚本,覆盖从资源模板到界面元素的多个层次,方便开发者按需替换和重新编译。通过覆盖 ToolkitPro.rc 并放置 vc80 向导相关文件后再编译,界面库的菜单、提示和属性页会显示为中文,VC2005 的 AppWizard 也会以中文提示引导创建项目,从而降低本地化集成的上手成本。需要注意的是该汉化仅支持 VC2005 环境下的向导,其他编译环境需另行适配。资源当前已有 494 人学习,适合刚接触这套界面库、希望快速完成中文本地化的 Visual C++ 开发者。

1. Codejock Xtreme ToolkitPro v13.2.1 中文汉化包到底改了什么

接手一套用 Codejock Xtreme ToolkitPro v13.2.1 做界面的老 MFC 工程,交付时客户一句话顶回来:“菜单怎么是英文的?”界面库自带的 Ribbon 菜单、停靠窗标题、右键菜单、对话框按钮全是英文资源,业务代码里写再多 SetWindowText 也填不满几百条界面库内置字符串。中文汉化包干的事,就是把 ToolkitPro 的英文资源整体替换成简体中文资源,让界面库里所有内置文本跟着业务进程一起变中文。它适合两类人:还在用 v13.2.1 维护存量工程的开发者,以及要拿老库快速交付中文界面的团队。先搞清楚它改的是资源、不是程序逻辑,后面所有安装和排查就都有方向了。

2. 汉化包的两种形态:资源DLL替换与源码级汉化

很多人以为汉化包是个安装程序,双击就能把界面库变成中文。实际对 ToolkitPro v13.2.1 这种老界面库,市面上流通的汉化包基本就两种形态:资源DLL和源码补丁。形态选错,后边工程量能差出半天到两天。本章先把原理和选型讲透,下一章再落到具体安装,这样你拿到任何一份汉化包,都能自己判断该走哪条路。

2.1 资源DLL是怎么把英文界面换掉的

MFC 和 Win32 程序显示文本,本质是调用 LoadString、FindResource 这类 API 按资源 ID 去字符串表里查询。界面库内部也一样,菜单、工具栏、对话框标题都挂在模块的资源段里。汉化包把英文资源单独编译成一份中文资源DLL,程序启动时让资源查找先落到中文DLL上。XTPResourceManager 做的就是这个事:UI 组件创建时从语言 DLL 里取字符串,取不到再回退到主模块的英文资源。

这个机制决定了三件事。第一,汉化只动界面库内置文本,碰不到你业务程序里自己写的字符串。第二,加载顺序有讲究,语言 DLL 必须在主窗体和工具栏创建之前挂上,挂晚了菜单已经用英文建好了。第三,资源 ID 是唯一的匹配钥匙,ID 对不上就完全失效,这也是后面排查时最先要检查的点。下面这条命令可以在不运行程序的情况下,直接查看界面库 DLL 的资源语言:

dumpbin /resources ToolkitPro1321u.dll | findstr /i "language"

逻辑说明:dumpbin 是 Visual Studio 自带的二进制查看工具,/resources 参数把 DLL 里的资源段展开成可读清单,language 字段表示每块资源使用的语言 ID。这条命令的本质是确认你手里的 DLL 到底是英文原版还是已经被汉化过,比直接拷进工程里试错要快得多。

参数说明:language 字段里 0409 代表英语(美国),0804 代表简体中文。如果界面库文件本身已经显示 0804,说明你拿到的是汉化过的完整主 DLL,可以直接用覆盖方案;如果还是 0409,说明汉化包是单独的语言 DLL,需要按 3.2 的方式在运行时加载。注意 x86 和 x64 的界面库文件通常放在不同子目录,dumpbin 前先确认路径正确,这个细节能省掉很多无用功。

提示:dumpbin 需要在 Visual Studio 命令提示符里运行,普通 cmd 环境可能要先执行 vcvarsall.bat 才能识别命令。

资源 DLL 方案的另一个好处是能做到按进程分流。同一个界面库,英文软件加载 0409 资源,中文软件加载 0804 资源,只要在启动时按产品配置把语言 DLL 挂上即可。如果你的产品同时出英文版和中文版,这种做法最省事,不需要维护两份界面库二进制,也方便以后扩展繁体、日文等其他语言包。

2.2 源码级汉化与资源级汉化:一张表选型

源码级汉化是另一条路:拿到界面库源码包,直接改 .rc 文件里的字符串表、菜单和对话框模板,然后连同你的工程一起重新编译。这里的 .rc 也是资源,但改在源码工程里,和你运行的 DLL 是同一份产物,不存在两套文件对不上的问题。选哪种,取决于你是“尽快交付”还是“长期定制”。

对比项资源DLL汉化源码级汉化
改动范围不碰源码,替换/加载语言DLL直接改 .rc 后整体重编
升级影响换版本要重新找对应汉化包升级后要重新合并资源补丁
字符集DLL编译期固定,运行时按ID查找随工程字符集自动一致
维护成本低,适合交付场景高,适合长期深度定制
主要风险版本不匹配、ID错位改动量大、编译参数引入新问题

我的选型倾向很明确:绝大多数商业交付走资源 DLL,因为省事、回滚容易,大不了把原 DLL 恢复回去。源码级汉化只推荐给真要深度定制界面库文案的团队,比如把内置日期格式全部改成“yyyy年MM月dd日”,或者去掉某个不合规的英文提示,这种需求只能从源码里改干净。

关于 .rc 编码,源码级汉化动手前要先看文件头。正常的界面库 .rc 文件要么以 UTF-16 保存,要么开头有#pragma code_page(936)这样的代码页声明。936 是简体中文代码页,说明源码作者已经考虑了本地化,替换进去的中文字符串只要保持源文件编码不变就行;如果头部写的是 1252(西欧)或者什么都没有,最好先补上 code_page 声明,否则编译出来的资源在中文系统上可能显示成乱码。这个细节我几乎每次做源码级汉化都要检查一遍。

选型做完,动手前还有三步检查我建议你走一遍。第一,确认界面库 DLL 是 x86 还是 x64,汉化包必须同位数。第二,确认工程的 MFC 使用方式是共享 DLL 还是静态库,这决定汉化落点是 DLL 还是源码。第三,把原界面库 DLL 做一份完整备份,放到带日期后缀的目录里,回滚时直接复制回来,这一步能省掉后面所有后悔药。三步检查加起来不到十分钟,但能挡掉汉化不生效、崩溃这类大半的问题。

3. 把汉化包装进MFC工程:三条路径与验证方法

汉化包装进工程,本质是让界面库的资源加载链路指向中文资源。根据你手上的汉化包形态和工程结构,常见做法有三条:覆盖原 DLL、运行时加载语言 DLL、改源码后重编。三条路径各有适用边界,我按从快到慢的顺序讲,最后统一给一个验证是否生效的方法。

3.1 路径一:用汉化资源DLL覆盖原DLL

这条路径最快,适合拿到的是“完整汉化主 DLL”的情况,也就是 2.1 里 dumpbin 看到 0804 的那种文件。操作前先确认程序真正加载的路径:很多老工程把界面库 DLL 放在可执行文件目录,也有放在公共 DLL 目录的,只改输出目录里那一份经常会漏。确认后按下面步骤走,覆盖前强制备份:

cd /d "C:\YourApp\Bin" if exist ToolkitPro1321u.dll ( ren ToolkitPro1321u.dll ToolkitPro1321u.dll.bak ) copy /y "D:\Patch\Chinese_zh-CN.dll" ToolkitPro1321u.dll

逻辑说明:cd 先进入程序运行目录,if exist 判断原文件在不在,用 ren 改成 .bak 后缀做备份,再用 copy 把汉化 DLL 覆盖过去。这样万一汉化包有问题,一条 ren 就能回滚,不需要重装环境。

参数说明:这里以ToolkitPro1321u.dll为例,u 后缀代表 Unicode 版本。老界面库通常同时提供 Unicode 和 ANSI 两套 DLL,另一套可能叫ToolkitPro1321a.dll,汉化包和原库必须对应同一套,混用的话字符集不匹配,跑起来就是满屏乱码。覆盖完先不要急着启动程序,用 dumpbin /resources 再查一次目标文件,确认语言确实是 0804 再继续,这一步能避免你反复怀疑自己操作错了。

注意:如果拿到的汉化包是一份独立的语言 DLL,比如叫 zh-CN.dll,就不要走覆盖主 DLL 的方案。那样会把英文主 DLL 整个换掉,语言 DLL 反而没地方挂,正确做法是 3.2 的运行时加载。

3.2 路径二:运行时用XTPResourceManager加载语言包

独立语言 DLL 的加载方式,是在程序初始化阶段把语言资源挂到资源查找链上。以 MFC 工程的 App 类为例:

BOOL CYourApp::InitInstance() { CString strLangDll; strLangDll.Format(_T("%s\\Languages\\zh-CN.dll"), GetExeDir()); if (::PathFileExists(strLangDll)) { // 语言DLL放在exe同级的Languages目录,防止发布时漏文件 XTPResourceManager()->LoadResource(strLangDll); } // ... 原有初始化代码 return TRUE; }

逻辑说明:InitInstance 是 MFC 程序创建主窗口前的必经入口,在这里调用 LoadResource,能保证语言资源先于所有界面库窗口生效。PathFileExists 是防御性判断,语言 DLL 缺失时不至于直接崩溃,程序还能以英文界面继续跑,便于现场排查。

参数说明:GetExeDir() 是需要自己实现的辅助函数,返回可执行文件所在目录;字符串里的Languages\\zh-CN.dll是举例,实际文件名以汉化包为准。XTPResourceManager() 是界面库暴露出来的全局资源管理器,老版本里加载语言的入口有的叫 LoadResource,有的叫 LoadLanguageResource,具体名称以你手上头文件的定义为准。关键点是调用时机必须赶在主窗口创建之前,挂晚了已经生成的菜单和工具栏不会自动刷新成中文。

走这条路还有个好处:英文版安装包可以不打包 Languages 目录,中文版才附带,产品多语言手段更干净。缺点是加载链路比覆盖多一环,一旦 PathFileExists 判断失败或路径写错,就是 5.3 那种“装了但纹丝不动”的怪现象,所以调试时建议在 LoadResource 调用处加一句 TRACE,输出实际加载路径和返回值,方便回头查。

3.3 路径三:直接改源码字符串表

适用情况很明确:你手上有界面库源码,而且工程本来就是源码静态编译。这时候不需要折腾 DLL,直接用脚本批量替换 .rc 里的字符串表,再和界面库一起重编,汉化就永久进产物了。下面这个 Python 脚本适合处理大部分 STRINGTABLE:

import re, io def localize_rc(src_path, mapping, out_path): with io.open(src_path, 'r', encoding='utf-16') as f: text = f.read() for eng, chs in mapping.items(): # 只替换行首的字符串条目,避免误伤消息名和宏 text = re.sub(r'(?m)^\s*("%s")\s*,' % re.escape(eng), lambda m: m.group(1) + ', L"%s"' % chs, text) with io.open(out_path, 'w', encoding='utf-16') as f: f.write(text)

逻辑说明:脚本按行匹配 STRINGTABLE 里的英文条目,把英文替换成对应的中文宽字符。正则前面的^\\s*限制在行首,能避免把出现在注释、消息 ID、宏定义里的同名英文也替换掉。mapping 字典由你维护,可以从汉化包里提取,也可以自己整理一份常用词表。

参数说明:src_path 指向界面库的 .rc 资源文件,out_path 是输出文件,建议先输出到新文件,人工抽查几条再回写原文件。encoding 固定 utf-16,绝大多数界面库源码的 .rc 都是这个编码,如果你的包是 ANSI 编码,改成 gbk 再跑。需要特别注意格式化占位符,比如“%d items”里的%d必须原样保留,否则运行时格式化字符串会读越界,程序直接在弹窗时崩溃。这也是源码级汉化比 DLL 替换更容易翻车的地方,因为静态编译没有 DLL 版本隔离,代码路径上任何一点疏漏都会进最终产物。

改完字符串表后,.rc 里可能还有菜单项、对话框按钮这些资源,它们不一定走 STRINGTABLE。稳妥做法是在资源视图里再人工过一遍对话框模板,把按钮标题改掉。这一步没有自动化捷径,只能靠界面库自带的示例工程逐个对照,我一般只改实际会用到的窗口,用不到的模板保持英文反而降低风险。

3.4 验证汉化是否生效

不管走哪条路径,装完都要验证。最快的方法不是用眼睛看截图,而是枚举窗口文本,把每个控件的标题打出来对比:

void DumpWindowText(HWND hWndRoot) { HWND hChild = ::GetWindow(hWndRoot, GW_CHILD); while (hChild) { CString strText; ::GetWindowText(hChild, strText.GetBuffer(128), 128); strText.ReleaseBuffer(); if (!strText.IsEmpty()) TRACE(_T("[%08X] %s\n"), hChild, (LPCTSTR)strText); hChild = ::GetWindow(hChild, GW_HWNDNEXT); } }

逻辑说明:从主窗口句柄出发,枚举全部子窗口,把每个控件能读到的标题文本打印到调试输出。主窗口、Ribbon 页签、停靠栏各跑一次,看到中文就说明资源加载链路已经通了,剩下的细节问题再去查。

参数说明:GetWindowText 的第三个参数 128 表示缓冲区大小,够读一条普通菜单标题;TRACE 只在 Debug 版输出,Release 版想验证的话换成 OutputDebugString,再用 DebugView 收。这段代码只是验证手段,不建议留在正式版里。如果这里输出已经是中文,但界面上某个角落还是英文,问题基本不在加载链路,而要去查资源覆盖度,也就是 5.4 的场景。

4. v13.2.1 的版本适配与必调参数:字符集、字体、DPI

汉化包装不上、装上乱码,八成不是包的问题,而是版本和工程参数没对齐。v13.2.1 是老版本线,很多工程到今天还在用它维护,碰到的坑也特别集中。下面四个参数在动手前先核对清楚,能省掉后面一长串排查。

4.1 编译器版本与链接方式决定你选哪个汉化包

v13.2.1 那个年代,主流用法是 VS2008 和 VS2010 的 MFC 工程,也有一部分老项目还在用 VC6。不同编译器出来的界面库 DLL,导入导出和运行时不兼容,汉化包必须和你的编译器匹配。另外还要区分链接方式:动态链接到共享 DLL,还是把界面库静态编进 exe。动态链接触碰的是独立 DLL,汉化包可以只替换资源;静态链接则必须走源码级汉化,因为根本没有独立 DLL 可换。

工程形态汉化包类型关键注意点
动态链接,Unicode替换 u 后缀主 DLL版本号必须精确等于 13.2.1
动态链接,ANSI替换 a 后缀主 DLL罕见但存在,别拿 Unicode 包硬上
静态链接无现成 DLL必须改源码 .rc 后重编
VC6 老工程多为 ANSI 包优先确认字符串表代码页

怎么看自己是哪种:Visual Studio 工程属性里找“Use of MFC”,选项是 Use MFC in a Shared DLL 还是 Use MFC in a Static Library,一眼就能区分。拿到汉化包后,先对自己的工程形态,再动手,这一步错了后面全是白费。

4.2 字符集和代码页:Unicode工程最容易翻车

同样的中文词,在 UTF-16 和 GBK 里生成的字节完全不同。界面库 Unicode 版用 UTF-16 存字符串,ANSI 版用系统当前代码页。汉化包如果按 GBK 做,放到 Unicode 版上就是乱码;反过来 Unicode 包放到 ANSI 工程里,轻则字符串截断,重则运行时报资源格式错误。判断方法很简单,打开 .rc 文件看头部:

Get-Content ToolkitPro.rc -TotalCount 3 | Format-Hex

逻辑说明:把 .rc 文件的前三行以十六进制方式输出。如果开头是FF FE,说明文件是 UTF-16 LE 编码,属于 Unicode 资源;如果开头没有 BOM,再看前几行有没有#pragma code_page(936),有就是 ANSI 中文代码页。这个判断决定你该选哪种汉化包。

参数说明:Format-Hex 是 PowerShell 自带的格式化命令,不修改文件本身;TotalCount 3 只取前三行,足够看到 BOM 和 code_page 声明。另一条更直接的验证路径是 2.1 的 dumpbin /resources,看语言 ID。判断完之后,Unicode 工程一定要找 Unicode 版汉化包,ANSI 工程找 ANSI 版,两者混用基本没有好结果。

4.3 字体替换与DPI:中文小字是另一个坑

即使资源全部汉化成功,老界面库的对话框默认字体还是 MS Shell Dlg,这套字体在中文环境下渲染小字号特别容易发虚,尤其在高 DPI 屏上,文字边缘糊成一片。解决办法是启动时把界面库默认字体替换成中文字体,常见做法是这样:

LOGFONT lf = {0}; lf.lfHeight = -12; lf.lfCharSet = DEFAULT_CHARSET; _tcscpy_s(lf.lfFaceName, _T("Microsoft YaHei UI")); CFont* pFont = new CFont; pFont->CreateFontIndirect(&lf); XTPResourceManager()->SetFont(pFont);

逻辑说明:构造一个 LOGFONT 结构,指定字体名称和大小,通过 CreateFontIndirect 生成字体对象,再交给 XTPResourceManager 作为界面库全局默认字体。之后界面库新建的对话框和工具栏都会优先使用这份字体。

参数说明:lfHeight 用负值表示字符高度,-12 在 96 DPI 下大约是 9pt,这是中文界面比较舒服的尺寸。如果你要精确匹配物理字号,应该用lf.lfHeight = -MulDiv(9, GetDeviceCaps(dc, LOGPIXELSY), 72),这样在 125% 缩放的屏幕上字号不会变小。Microsoft YaHei UI 是微软雅黑的 UI 变体,老系统没有的话就写 Microsoft YaHei。SetFont 这个入口在不同版本里也可能叫 SetDefaultFont,以你手上的接口为准,核心思路是让界面库内部所有字体请求都落到中文字体上。

4.4 锁定版本:13.2.1 的汉化包不要跨版本用

这条看着像废话,但我见过太多人拿 13.2.0 或 13.3.0 的包硬顶上 13.2.1。界面库每个版本都会增删资源 ID,两个相邻版本的 ID 表可能有几十条差异。资源 ID 错位的后果,轻的是某几处界面仍然是英文,重的是字符串查找命中错误 ID,格式化参数对不上导致越界读,程序启动后随机崩溃。

所以拿到任何汉化包,第一件事就是右键 DLL 看属性里的文件版本,跟原界面库 DLL 逐位对比。版本一致后再查语言 ID 和位数,三个条件都满足才允许进工程。少一步检查,后面就要用第 5 章的排查流程来还债。

5. 汉化避坑排查:五个真实踩过的坑

下面五条是给老界面库做汉化时最容易翻车的地方,全部按“现象、原因、怎么解决”的结构写。遇到对应症状可以直接跳到对应小节,不必从头读。

5.1 汉化后中文显示成方块乱码

现象:界面已经变成中文了,但所有中文都显示成一排方框,英文和数字正常。

原因有两种。第一种是汉化包本身按 ANSI(GBK)编译,而主程序是 Unicode 字符集,界面库把 GBK 字节错当 Unicode 解释;第二种是对话框资源的字体是 MS Shell Dlg,老系统里没有中文字体回退,字形渲染不出来。

解决:先看工程属性里的字符集。如果主工程是 Unicode,就换 Unicode 版汉化包;实在只有 ANSI 包,就只能走 3.3 的源码级汉化,把 .rc 转成 UTF-16 后重新编译。字体问题用 4.3 的代码在启动时替换成微软雅黑,两个原因都排除后乱码基本消失。判断到底是哪个原因,可以在调试器里看字符串变量的内存:宽字符显示成0x4E2D这种就是对的,显示成两个单字节 0xB4 0xD6 就说明 ANSI 串被当成了宽串。

5.2 切换皮肤后菜单一夜回到英文

现象:程序启动时全中文,用户通过界面库的皮肤管理器切了一次皮肤,菜单和 Ribbon 又变回英文。

原因是换肤时界面库会重建整个工具栏和菜单,重建路径重新从英文主资源读取字符串,绕过了已经加载的语言 DLL。语言资源还在,但换肤流程没有走语言查找链。

解决:在换肤完成事件里重新调用一次语言资源加载,也就是把 3.2 的 LoadResource 调用再执行一遍。另外一个隐藏原因是皮肤文件本身也可能带英文标题,如果皮肤包里有字符串资源,单独替换皮肤文件里的资源也能解决。这个坑在交付验收时最容易被忽略,因为演示时一般不会当场切皮肤。

5.3 汉化包装了但界面纹丝不动

现象:DLL 已经覆盖到目标路径,路径确认无误,程序启动还是全英文。

原因多半是程序实际加载的不是你覆盖的那个 DLL。常见于多分支目录、多人协同开发,或者安装包把界面库放到了公共目录,而你把汉化 DLL 放进了自己熟悉的输出目录。

解决:先在任务管理器里看实际模块路径:按下 Ctrl+Shift+Esc,点“详细信息”,右键进程选择“打开文件位置”,直接能看到 exe 加载的 DLL 实际路径。更准确的做法是在程序里调用 GetModuleHandle 加 GetModuleFileName,打印出 ToolkitPro DLL 的真实路径。确认路径后还要检查是不是 Debug 版程序配了 Release 版汉化 DLL,老界面库的 Debug 和 Release 是两个不同的 DLL 文件,复制错了不但不生效,还会在启动时直接报找不到入口点。

5.4 主界面中文了,弹窗还是英文

现象:主窗口、Ribbon、菜单都已经是中文,但某些子对话框、气泡提示还是英文。

原因是这些字符串不在界面库资源里,而在你自己的模块或者另一个第三方库里。也可能是汉化包作者漏译了界面库的某几个对话框模板,这种情况在手工汉化的包里很常见。

解决:先用 Spy++ 或资源视图检查弹窗标题对应的资源 ID 属于哪个模块。如果是自己工程里的字符串,直接在业务资源里改;如果是界面库漏译,常见做法是维护一份补充语言 DLL,把缺失 ID 的资源补进去,资源 ID 和语言属性必须与原资源完全一致,否则 MFC 的回退查找找不到它。改完再跑一次 3.4 的窗口文本转储,确认弹窗标题变了才算补上。

5.5 换上汉化包后程序启动崩溃

现象:覆盖完 DLL,双击 exe,程序还没出主窗口就崩了,崩溃位置每次还不一样。

原因大概率是汉化包版本和主程序链接的原库版本不一致,资源 ID 错位导致空指针或数组越界。另一种可能是网上下载的汉化 DLL 是手工改过的,导出表不完整,程序加载时链接失败。

解决:先验证导出表。把汉化 DLL 和原版 DLL 并排,用 Visual Studio 命令提示符执行以下对比:

dumpbin /exports ToolkitPro1321u.dll.orig > exports_orig.txt dumpbin /exports ToolkitPro1321u.dll > exports_patch.txt fc exports_orig.txt exports_patch.txt

逻辑说明:分别导出两个 DLL 的函数列表,再用 fc 对比差异。差异很大说明汉化包不是基于同一版本二次开发的,直接放弃,换一份来源干净的包。差异很小甚至没有,再看版本号是否精确匹配。

参数说明:ToolkitPro1321u.dll.orig 是你第一步备份的原版文件;fc 是 Windows 自带的文件对比命令,输出里出现大量“FC: 找不到差异”就说明导出表一致。如果导出表没问题还是崩溃,把程序运行日志开起来,重点看崩溃发生在哪个窗口创建之后,再去查对应资源 ID。这条排查流程能覆盖绝大多数汉化包引发的启动崩溃。

6. 汉化完成后怎么验证覆盖度:一个顺手的小工具脚本

汉化不是“装上能跑”就结束,交付前还要确认覆盖度。我习惯用一个小脚本把所有窗口文本转储出来,对着界面库常见英文词条逐个核对,比肉眼截图靠谱得多。

6.1 快速检查语言属性和覆盖度

把验证逻辑做成独立函数,进程启动后手动触发一次,就可以拿到整棵窗口树的文本。结合资源语言检查一起用,能覆盖 90% 的汉化问题:

BOOL CALLBACK EnumResLangProc(HMODULE hMod, LPCTSTR lpszType, LPCTSTR lpszName, WORD wIDLanguage, LONG_PTR lParam) { CString strLog; strLog.Format(_T("Type=%s Name=%s Lang=0x%04X\n"), lpszType, lpszName, wIDLanguage); OutputDebugString(strLog); return TRUE; // 返回TRUE继续枚举 }

逻辑说明:这是标准的资源语言枚举回调,Windows 会对指定 DLL 里的每块资源调用一次。把 hMod 换成界面库 DLL 的模块句柄,就能在调试输出里看到哪些资源还是英文语言 ID(0409),哪些已经切成中文(0804)。

参数说明:hMod 可以传 GetModuleHandle(_T("ToolkitPro1321u.dll")) 的返回值;lpszType 代表资源类型,字符串、对话框、菜单各有各的类型名;wIDLanguage 就是前文反复提到的语言 ID。回调里做一次过滤,只把 STRING 类型且语言为 0409 的资源列出来,剩下的就是漏译清单。

6.2 我自己的交付前检查习惯

这套流程走到最后,我形成了固定三个动作:先跑一次 3.4 的窗口文本转储,确认运行时的界面文本已经是中文;再跑一次 6.1 的资源语言枚举,确认没有 0409 资源残留;最后截图留档,把主窗口、Ribbon、一个典型弹窗各截一张,日期命名归档。三步做完才敢把包发出去验收。

有一次就是因为没跑资源枚举,界面看起来全中文,但某个深层设置对话框的字符串忘了翻,客户点开就露馅,现场改包非常狼狈。从那以后我再也不敢跳过资源枚举这一步。如果你也在维护 v13.2.1 这种老界面库,建议把这套检查固化到发布脚本里,顺手执行,不用每次手动点。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进