·汉化新世纪 ·汉化新世纪论坛 ·百家争鸣 ·论坛集萃 ·汉化问答 ·软件介绍
文章首页 >> 汉化教学 >> 特殊汉化 >> 再战非标准字体块-让 File Shredder 3.3 完美显示中文    Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎

再战非标准字体块-让 File Shredder 3.3 完美显示中文

作者: 树袋熊&飞鹰 来源:汉化教学 时间:2003-08-06 点击:9493

再战非标准字体块-让 File Shredder 3.3 完美显示中文

作者:树袋熊

最近在我(飞鹰)在汉化新世纪的论坛上看见有很多朋友讨论 File Shredder 3.3 的汉化问题,该软件汉化后主要会出现三个问题:

1、把软件主界面上的“Version”选项翻译为“版本”后,在 Win98 下显示不出任何字符,在 Win2000 下显示出几个框框,不知要如何修改才能让翻译后的中文字符完整显示出来?如图一所示。

2、在“Version”选项中的所有字体偏小,在16进制中查找“MS Sans Serif”任意改成任何一种字体名称后(只改这一处),在“Version”选项中的全部字体都会变的非常之大,不知何故?如图一所示。

(图一)

3、软件启动画面上的字体非常难看,不是我们希望的“宋体,9号”字,能解决这个问题吗?如图二所示。

(图二)

还有朋友反映说:该公司的其它软件,汉化时也会出现上面的这些现象,好象是对双字节的处理不太好,不知道是否有办法解决?

就此问题, 特别问过我(飞鹰)是否能帮助解决,可惜我(飞鹰)也无能为力,跟踪分析了大半天也没有个完整的解决方案。没办法,我(飞鹰)就去询问了我们汉化新世纪的好朋友 树袋熊。果然没到一天的时间,树袋熊 朋友就寄给了我(飞鹰)一份完整的解决方案,并附带了他已修改好的软件,下面我(飞鹰)就把 树袋熊 朋友研究出来的解决方案公布一下,毕竟好东西应该大家一起分享。

飞鹰你好!以下是对你的问题的答复:

像这种类型的对话框一般是调用PropertySheet函数创建的通用控件,通过对这个函数的拦截你可以找到以下代码:

0030:00401E56 8B842404020000     MOV   EAX,[ESP+0204]
0030:00401E5D 8BB42400020000     MOV   ESI,[ESP+0200]
0030:00401E64 83F805         CMP   EAX,BYTE +05
0030:00401E67 1BC9          SBB   ECX,ECX
0030:00401E69 8D9424F8000000     LEA   EDX,[ESP+F8]
0030:00401E70 23C8          AND   ECX,EAX
0030:00401E72 A1401E4200       MOV   EAX,[00421E40]
0030:00401E77 8954241C        MOV   [ESP+1C],EDX
0030:00401E7B 894C2424        MOV   [ESP+24],ECX
0030:00401E7F 8D542430        LEA   EDX,[ESP+30]
0030:00401E83 B920000000       MOV   ECX,20          ; 定义对话框属性
0030:00401E88 C744242005000000    MOV   DWORD [ESP+20],05    ; 这是定义有几个对话框
0030:00401E90 89542428        MOV   [ESP+28],EDX       ; 定义第一个对话框
0030:00401E94 897C2430        MOV   [ESP+30],EDI
0030:00401E98 894C2434        MOV   [ESP+34],ECX
0030:00401E9C 89442438        MOV   [ESP+38],EAX
0030:00401EA0 C744243CD0070000    MOV   DWORD [ESP+3C],07D0   ; 定义对话框ID
0030:00401EA8 C7442448B0144000    MOV   DWORD [ESP+48],004014B0 ; 定义对话框过程
0030:00401EB0 8974244C        MOV   [ESP+4C],ESI       ; 定义第二个对话框
0030:00401EB4 897C2458        MOV   [ESP+58],EDI
0030:00401EB8 894C245C        MOV   [ESP+5C],ECX
0030:00401EBC 89442460        MOV   [ESP+60],EAX
0030:00401EC0 C744246460090000    MOV   DWORD [ESP+64],0960   ; 定义对话框ID
0030:00401EC8 C7442470B02E4000    MOV   DWORD [ESP+70],00402EB0 ; 定义对话框过程
0030:00401ED0 89742474        MOV   [ESP+74],ESI       ; 定义第三个对话框
0030:00401ED4 89BC2480000000     MOV   [ESP+80],EDI
0030:00401EDB 898C2484000000     MOV   [ESP+84],ECX
0030:00401EE2 89842488000000     MOV   [ESP+88],EAX
0030:00401EE9 C784248C000000FC080000 MOV   DWORD [ESP+8C],08FC   ; 定义对话框ID
0030:00401EF4 C7842498000000B0174000 MOV   DWORD [ESP+98],004017B0 ; 定义对话框过程
0030:00401EFF 89B4249C000000     MOV   [ESP+9C],ESI       ; 定义第四个对话框
0030:00401F06 89BC24A8000000     MOV   [ESP+A8],EDI
0030:00401F0D 898C24AC000000     MOV   [ESP+AC],ECX
0030:00401F14 898424B0000000     MOV   [ESP+B0],EAX
0030:00401F1B C78424B400000088130000 MOV   DWORD [ESP+B4],1388   ; 定义对话框ID
0030:00401F26 C78424C0000000C01F4000 MOV   DWORD [ESP+C0],00401FC0 ; 定义对话框过程
0030:00401F31 89B424C4000000     MOV   [ESP+C4],ESI       ; 创建第五个对话框
0030:00401F38 89BC24D0000000     MOV   [ESP+D0],EDI
0030:00401F3F C78424D400000021000000 MOV   DWORD [ESP+D4],21    ; 定义对话框属性
0030:00401F4A 898424D8000000     MOV   [ESP+D8],EAX
0030:00401F51 E82A2E0000       CALL   00404D80
0030:00401F56 898424DC000000     MOV   [ESP+DC],EAX
0030:00401F5D 8D442408        LEA   EAX,[ESP+08]
0030:00401F61 83C670         ADD   ESI,BYTE +70
0030:00401F64 50           PUSH   EAX
0030:00401F65 C78424EC00000080494000 MOV   DWORD [ESP+EC],00404980
0030:00401F70 89B424F0000000     MOV   [ESP+F0],ESI
0030:00401F77 FF1518404100      CALL   NEAR [00414018]  ; 这是调用PropertySheet函数

程序中第五个对话框(也就是那个Version对话框)不是以资源形式存在的,它是程序启动时创建的,没有可使用的字体函数来修改窗口的显示,只是使用系统默认的字体(切换到Win2000下,你就会发现软件的字体是正常的)。还有一点就是“Version”这个字符串在程序运行过程中已将它转换为双字节的形式存放在内存中,要修改为中文好像不太可能。如果要改为宋体字最好的办法就是用VC等资源编辑工具在程序中自己创建第五个对话框(你可以把ID为2300的对话框复制一个来修改,它与Version对话框很相似,我假设你创建的对话框ID为5100),再把从401F3F开始的指令改为(只需要修改二条即可):

0030:00401F31 89B424C4000000     MOV   [ESP+C4],ESI
0030:00401F38 89BC24D0000000     MOV   [ESP+D0],EDI
0030:00401F3F C78424D400000020000000 MOV   DWORD [ESP+D4],20    ; 定义对话框属性(这是修改的)
0030:00401F4A 898424D8000000     MOV   [ESP+D8],EAX       ; 定义应用程序实例
0030:00401F51 C78424DC000000EC130000 MOV   DWORD [ESP+DC],13EC   ; 定义对话框ID(这是修改的)
0030:00401F5C 90           NOP  
0030:00401F5D 8D442408        LEA   EAX,[ESP+08]
0030:00401F61 83C670         ADD   ESI,BYTE +70
0030:00401F64 50           PUSH   EAX
0030:00401F65 C78424EC00000080494000 MOV   DWORD [ESP+EC],00404980
0030:00401F70 89B424F0000000     MOV   [ESP+F0],ESI
0030:00401F77 FF1518404100      CALL   NEAR [00414018]  ; 这是调用PropertySheet函数

因为PropertySheet函数在这个程序中是唯一的,它不可能被多次调用,如果程序本身没有CRC校验,就不会引起问题。如果你不想这样修改的话,你也可以直接把401E88处的05改为04就不会显示这个Version对话框了。但我想一个好的汉化作品应该不至于做的这么差劲。
汉化后会存在一个问题:就是在这个对话框中有一个按钮“www.gregorybraun.com”,如果不将资源中的ID设置正确,那么程序运行时点击这个按钮不会有任何反映。要确定这个ID你可以这样(如果你会调试的话,在未修改的程序中拦截SetDlgItemTextA函数也可以找到),用十六进制编辑器打开Shredder.exe文件,查找“www.gregorybraun.com”,会在偏移17538的位置处找到,用ProcDump32编辑该文件可看到程序的基址是400000,那么400000+17538=417538,再用w32dasm反汇编程序后查找38754100,将在以下位置找到:

* Possible StringData Ref from Data Obj ->"www.gregorybraun.com"
                 |
:00405374 6838754100       push 00417538
:00405379 66C7060000       mov word ptr [esi], 0000
:0040537E 83C602         add esi, 00000002
:00405381 66C7060150       mov word ptr [esi], 5001
:00405386 83C602         add esi, 00000002
:00405389 66C7060000       mov word ptr [esi], 0000
:0040538E 83C602         add esi, 00000002
:00405391 66C7060000       mov word ptr [esi], 0000
:00405396 83C602         add esi, 00000002
:00405399 66C7069B00       mov word ptr [esi], 009B
:0040539E 83C602         add esi, 00000002
:004053A1 66C7068C00       mov word ptr [esi], 008C
:004053A6 83C602         add esi, 00000002
:004053A9 66C7067300       mov word ptr [esi], 0073
:004053AE 83C602         add esi, 00000002
:004053B1 66C7060E00       mov word ptr [esi], 000E
:004053B6 83C602         add esi, 00000002
:004053B9 66C7066B00       mov word ptr [esi], 006B   ; 这就是按钮的ID
:004053BE 83C602         add esi, 00000002
:004053C1 66C706FFFF       mov word ptr [esi], FFFF
:004053C6 83C602         add esi, 00000002
:004053C9 66C7068000       mov word ptr [esi], 0080
:004053CE 83C602         add esi, 00000002

你会在程序中找到两个类似于以上代码的位置,只有这个才是的,另一个的ID处为FFFF(其它搜索到的都是没有设置资源信息的语句就不用管它了)。 现在只剩下启动画面还不是宋体字了。它用的是GetStockObject函数检取字体,这样得到的不会是宋体9号字。我想你应该早就发现程序中在40ADF9处调用了一个CreateFontIndirecta函数创建字体,但它创建的是“Arial”字体,你可以用十六进制编辑器打开程序查找“Arial”将它改为“宋体”,并记下程序运行时保存这个字体句柄的位置,那么现在我们就有宋体字可用了。然后将程序在显示启动画面时调用GetStockObject函数检取字体的语句改为直接从这个位置取字体句柄。具体操作如下:

0030:0040ADDA 52           PUSH   EDX
0030:0040ADDB 252C010000       AND   EAX,012C
0030:0040ADE0 895C2418        MOV   [ESP+18],EBX
0030:0040ADE4 0590010000       ADD   EAX,0190
0030:0040ADE9 884C2428        MOV   [ESP+28],CL
0030:0040ADED 89442424        MOV   [ESP+24],EAX
0030:0040ADF1 885C2429        MOV   [ESP+29],BL
0030:0040ADF5 885C242A        MOV   [ESP+2A],BL
0030:0040ADF9 FF1548404100      CALL   NEAR [00414048]
0030:0040ADFF 8BF8          MOV   EDI,EAX
0030:0040AE01 3BFB          CMP   EDI,EBX
0030:0040AE03 7524          JNZ   0040AE29
0030:0040AE05 FF1598404100      CALL   NEAR [00414098]  ; CreateFontIndirecta函数

这个地方被调用两次,第一次是创建宋体9号字,第二次创建的字体较大。当为创建宋体9号字时从上面的指令处返回后到以下位置:

0030:00408395 E8A6290000       CALL   0040AD40
0030:0040839A 6A00          PUSH   BYTE +00
0030:0040839C 6A01          PUSH   BYTE +01
0030:0040839E 6A09          PUSH   BYTE +09
0030:004083A0 687C7C4100       PUSH   DWORD 00417C7C
0030:004083A5 6A00          PUSH   BYTE +00
0030:004083A7 A39C1E4200       MOV   [00421E9C],EAX   ; 保存字体句柄
0030:004083AC E88F290000       CALL   0040AD40

可以看到字体句柄被保存在内存421E9C处,经常调试程序你就会知道,这种地方一般是用来保存全局变量的,那么我们也可以在其它地方使用。现在开始拦截GetStockObject函数,并注意该函数的后面是否有SelectObject函数,如果有那就说明是需要修改的。找到以下位置:

0030:00404750 57           PUSH   EDI
0030:00404751 FF152C424100      CALL   NEAR [0041422C]  ; 这是BeginPaint函数
0030:00404757 6A0C          PUSH   BYTE +0C      ; 这是参数入栈
0030:00404759 8BF0          MOV   ESI,EAX
0030:0040475B FF156C404100      CALL   NEAR [0041406C]  ; 这是GetStockObject函数
0030:00404761 8B1D58404100      MOV   EBX,[00414058]
0030:00404767 50           PUSH   EAX
0030:00404768 56           PUSH   ESI
0030:00404769 FFD3          CALL   EBX        ; 这是SelectObject函数

改为以下指令:

0030:00404757 90           NOP             ; 这是删除入栈指令
0030:00404758 90           NOP
0030:00404759 8BF0          MOV   ESI,EAX
0030:0040475B 8B059C1E4200      MOV   EAX,[00421E9C]   ; 取字体句柄

另外在以下位置处也能拦截到,这一段可能是用来绘制的,但修不修改对程序好像没什么影响,你自己可以决定是否修改。

0030:00404895 6A0C          PUSH   BYTE +0C      ; 这是参数入栈
0030:00404897 1BDB          SBB   EBX,EBX
0030:00404899 8BF0          MOV   ESI,EAX
0030:0040489B C7442414A8000000    MOV   DWORD [ESP+14],A8
0030:004048A3 C74424186E000000    MOV   DWORD [ESP+18],6E
0030:004048AB C744241CCC010000    MOV   DWORD [ESP+1C],01CC
0030:004048B3 C74424207E000000    MOV   DWORD [ESP+20],7E
0030:004048BB F7DB          NEG   EBX
0030:004048BD FF156C404100      CALL   NEAR [0041406C]  ; 这是GetStockObject函数
0030:004048C3 50           PUSH   EAX
0030:004048C4 56           PUSH   ESI
0030:004048C5 FF1558404100      CALL   NEAR [00414058]  ; 这是SelectObject函数

启动画面中的其它文字都是些图片,如果有兴趣,你也可以用绘图软件改改。

以上就是 树袋熊 朋友解决此问题的完整方案,经过我(飞鹰)的测试后证明该方案完全正确可行。修改后的软件,如图三、如图四所示。

(图三)

(图四)

该软件有些需要汉化的字符,是存放在注册表的 HKEY_CURRENT_USER\Software\Software by Design\File Shredder for Windows 95/NT\DeskTop\Window\Labels 项目下,如图五中红色框所示。

(图五)

解决了上述的全部问题后, File Shredder 3.3 就能完美的显示出中文字符,软件汉化后也就不会再出现那种“半英半中”的现象了。至此,我(飞鹰)代表我们 汉化新世纪的全体成员 谢谢 树袋熊 朋友的热心帮助和指导,谢谢!

大家可以参照此篇文章,修正 Software Design 公司的其它软件,让其支持并完美的显示中文。

这篇文章由 树袋熊 朋友撰写,汉化新世纪成员-飞鹰 补充、完善。

汉化新世纪 责任编辑: 乾 .:|:. 标签(Tag): 字体 汇编

·上一篇: 汉化提高课─UPXPR 的脱壳方法 ·下一篇: Delphi 汉化中 PixelsPerInch 对界面效果的影响以及解决

· 版权申明: 本文引自《汉化教学》,如有版权疑问请及时联系本站,以便本站处理。

· 转载申明: 本文引自《汉化教学》[ 作者: 树袋熊&飞鹰],如需转载请直接联系原始作者,并请注明原始出处。

相关文章                                                                                发表评论 打印此文 关闭窗口

| 设为首页 | 加入收藏 | 联系我们 | 友情链接
Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎
本站内容,除转载或版权特别申明的内容外,皆遵守 创造共用协议中文版之“署名-非商业性使用-禁止演绎 2.5 中国大陆”条款
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.5 China License.
本网站内容源自汉化新世纪论坛的摘录和汉化新世纪成员的原创文章。
凡汉化新世纪论坛的文字皆默认为汉化新世纪与原作者共同拥有并授权发布。
如对本站发布文章有所异议请来信告知,我们将及时删除。
凡商业摘录本站文字请先与我们联系,本站将保留非授权商业发布的追究权利。
凡非商业摘录本站文字请明显注明出处和原作者,并不得改动,凡改动必先征求原作者同意。
苏ICP备05002283号