查看完整版本: [-- [原创] GetStockObject 非标准字体手动修改方法简介 --]

汉化新世纪论坛 -> 技术精华 -> [原创] GetStockObject 非标准字体手动修改方法简介 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

炎之川 2003-04-24 13:53

[原创] GetStockObject 非标准字体手动修改方法简介

GetStockObject 非标准字体手动修改方法简介

在这篇文章中,我将向大家简单的介绍一下使用 GetStockObject 设置的非标准字体块的修改方法。
相对于使用 CreateFontA 及 CreateFontIndirectA 两个函数的字体块来说,GetStockObject 并没有具体的设置使用某个字体,而是按照参数来“选择”一种备用字体来显示,所以相对而言,GetStockObject 字体块的修改比其他两类还要更容易一些。
通过查阅 MSDN,可知 GetStockObject 函数的结构:
HGDIOBJ GetStockObject(
 int fnObject  // stock object type
);
这个函数只有一个作为“标识”的参数,具体参数如下:
#define BLACK_BRUSH 4
#define DKGRAY_BRUSH 3
#define GRAY_BRUSH 2
#define HOLLOW_BRUSH 5
#define LTGRAY_BRUSH 1
#define NULL_BRUSH 5
#define WHITE_BRUSH 0
#define BLACK_PEN 7
#define NULL_PEN 8
#define WHITE_PEN 6
#define ANSI_FIXED_FONT 11
#define ANSI_VAR_FONT 12
#define DEVICE_DEFAULT_FONT 14
#define DEFAULT_GUI_FONT 17
#define OEM_FIXED_FONT 10
#define SYSTEM_FONT 13
#define SYSTEM_FIXED_FONT 16
#define DEFAULT_PALETTE 15
用来选择画笔、画刷和调色版这些参数我们可以忽略不看,所以设置字体参数的就是 11~14、16~17,具体来说,压入堆栈的数值就是 0ah~0eh、10h。
字体参数对应的含义如下:
ANSI_FIXED_FONT     Windows fixed-pitch (monospace) system font.
ANSI_VAR_FONT      Windows variable-pitch (proportional space) system font.
DEVICE_DEFAULT_FONT   Windows NT/2000: Device-dependent font.
DEFAULT_GUI_FONT    Default font for user interface objects such as menus and dialog boxes. This is MS Sans Serif. Compare this with SYSTEM_FONT.
OEM_FIXED_FONT     Original equipment manufacturer (OEM) dependent fixed-pitch (monospace) font.
SYSTEM_FONT       System font. By default, the system uses the system font to draw menus, dialog box controls, and text.
Windows 95/98 and NT: The system font is MS Sans Serif.
Windows 2000: The system font is Tahoma
SYSTEM_FIXED_FONT    Fixed-pitch (monospace) system font. This stock object is provided only for compatibility with 16-bit Windows versions earlier than 3.0.
所以我们需要的字体就是“DEFAULT_GUI_FONT”,其对应代码是 17,即 0x11。
写到这里,使用 GetStockObject 设置的非标准字体块的修改方法就已经出来了,就是找到软件适用此函数的地方,前面的压栈语句 push xxx,如果“xxx”是 0A~0E,10,则将其改为 11 即可,即改为 push 11。

下面举几个具体的例子来说明一下:
例子一、点睛字体设置示例
我们需要的是梁利锋兄特别写的一个版本,其中包括使用 CreateFontA、CreateFontIndirectA、GetStockObject 三种函数设置字体的例子,这个文件可以在汉化新世纪论坛“梁利锋专版”找到。
使用 W32Dasm 反汇编,搜索“GetStockObject”,找到下面的代码段:
:004010D8 6A0B          push 0000000B  //ObjType = ANSI_FIXED_FONT
* Reference To: GDI32.GetStockObject, Ord:01A5h
                 |
:004010DA FF1514204000      Call dword ptr [00402014]
:004010E0 50           push eax
:004010E1 56           push esi
:004010E2 FFD5          call ebp
:004010E4 6880204000       push 00402080
:004010E9 FFD7          call edi
:004010EB 50           push eax
:004010EC 6880204000       push 00402080
:004010F1 6854010000       push 00000154
:004010F6 6A3C          push 0000003C
:004010F8 56           push esi
:004010F9 FFD3          call ebx
:004010FB 6A0C          push 0000000C  //ObjType = ANSI_VAR_FONT
* Reference To: GDI32.GetStockObject, Ord:01A5h
                 |
:004010FD FF1514204000      Call dword ptr [00402014]
:00401103 50           push eax
:00401104 56           push esi
:00401105 FFD5          call ebp
:00401107 6880204000       push 00402080
:0040110C FFD7          call edi
:0040110E 50           push eax
:0040110F 6880204000       push 00402080
:00401114 6868010000       push 00000168
:00401119 6A3C          push 0000003C
:0040111B 56           push esi
:0040111C FFD3          call ebx
:0040111E 6A0D          push 0000000D  //ObjType = SYSTEM_FONT
* Reference To: GDI32.GetStockObject, Ord:01A5h
                 |
:00401120 FF1514204000      Call dword ptr [00402014]
:00401126 50           push eax
:00401127 56           push esi
:00401128 FFD5          call ebp
:0040112A 6880204000       push 00402080
:0040112F FFD7          call edi
:00401131 50           push eax
:00401132 6880204000       push 00402080
:00401137 687C010000       push 0000017C
:0040113C 6A3C          push 0000003C
:0040113E 56           push esi
:0040113F FFD3          call ebx
:00401141 6A0E          push 0000000E  //ObjType = DEVICE_DEFAULT_FONT
* Reference To: GDI32.GetStockObject, Ord:01A5h
                 |
:00401143 FF1514204000      Call dword ptr [00402014]
:00401149 50           push eax
:0040114A 56           push esi
:0040114B FFD5          call ebp
:0040114D 6880204000       push 00402080
:00401152 FFD7          call edi
:00401154 50           push eax
:00401155 6880204000       push 00402080
:0040115A 6890010000       push 00000190
:0040115F 6A3C          push 0000003C
:00401161 56           push esi
:00401162 FFD3          call ebx
:00401164 6A10          push 00000010  //ObjType = SYSTEM_FIXED_FONT
* Reference To: GDI32.GetStockObject, Ord:01A5h
                 |
:00401166 FF1514204000      Call dword ptr [00402014]
:0040116C 50           push eax
:0040116D 56           push esi
:0040116E FFD5          call ebp
:00401170 6880204000       push 00402080
:00401175 FFD7          call edi
:00401177 50           push eax
:00401178 6880204000       push 00402080
:0040117D 68A4010000       push 000001A4
:00401182 6A3C          push 0000003C
:00401184 56           push esi
:00401185 FFD3          call ebx
:00401187 6A11          push 00000011  //ObjType = DEFAULT_GUI_FONT,这是我们需要的字体,即宋体
* Reference To: GDI32.GetStockObject, Ord:01A5h
                 |
:00401189 FF1514204000      Call dword ptr [00402014]
:0040118F 50           push eax
所以修改方法很简单,将我做注释的代码改为 push 00000011 即可,修改前后的效果如图一所示。
图像
例子二、1toX v2.63 Build 2002.05.03
1toX 是一个文件分割软件,官方主页是 http://www.logipole.com/
软件主程序使用 Armadillo 2.52 加壳,支持语言文件。脱壳并优化文件结构后,随便汉化一点,可以看到菜单字体显示极为难看(如图二),通过分析可知软件使用了 GetStockObject 函数设置字体,所以使用 W32Dasm 反汇编,并搜索“GetStockObject”,发现有两处是设置字体的:
图像
第一处
* Referenced by a CALL at Address:
|:004044E5
|
:00404180 83EC0C         sub esp, 0000000C
:00404183 53           push ebx
:00404184 8B5C2414        mov ebx, dword ptr [esp+14]
:00404188 55           push ebp
:00404189 56           push esi
:0040418A 8B6B14         mov ebp, dword ptr [ebx+14]
:0040418D 57           push edi
:0040418E 6A0C          push 0000000C  //使用 ANSI_VAR_FONT,我们改为 push 00000011
* Reference To: GDI32.GetStockObject, Ord:01A6h
                 |
:00404190 FF1560504300      Call dword ptr [00435060]
:00404196 8BF8          mov edi, eax
:00404198 6A00          push 00000000
:0040419A 897C2414        mov dword ptr [esp+14], edi
第二处
* Referenced by a CALL at Address:
|:004044C5
|
:00404210 83EC10         sub esp, 00000010
:00404213 53           push ebx
:00404214 55           push ebp
:00404215 56           push esi
:00404216 8B742420        mov esi, dword ptr [esp+20]
:0040421A 57           push edi
:0040421B 6A0C          push 0000000C  //使用 ANSI_VAR_FONT,我们改为 push 00000011
:0040421D 8B462C         mov eax, dword ptr [esi+2C]
:00404220 89442428        mov dword ptr [esp+28], eax
* Reference To: GDI32.GetStockObject, Ord:01A6h
                 |
:00404224 FF1560504300      Call dword ptr [00435060]
:0040422A 89442418        mov dword ptr [esp+18], eax
:0040422E 8A4610         mov al, byte ptr [esi+10]
:00404231 A801          test al, 01
:00404233 7442          je 00404277
修改完成后保存,看看效果,呵呵,搞定了 (如图三)
图像

例子三、RenderSoft CamStudio v2.00
CamStudio 是一个屏幕摄像工具。它可以捕获屏幕上你所进行的操作,保存为标准的 AVI 视频文件。其官方主页为:http://www.atomixbuttons.com/
分析后发现软件共有三处使用了 GetStockObject 设置字体,分别如下:
图像
第一处
* Reference To: GDI32.CreateCompatibleDC, Ord:002Ah
                 |
:0041C707 FF15F0904200      Call dword ptr [004290F0]
:0041C70D 6A0C          push 0000000C  //使用 ANSI_VAR_FONT,我们改为 push 00000011
:0041C70F 8BE8          mov ebp, eax
* Reference To: GDI32.GetStockObject, Ord:015Fh
                 |
:0041C711 FF15B8904200      Call dword ptr [004290B8]
:0041C717 50           push eax
第二处
* Referenced by a (U)nconditional or ©onditional Jump at Address:
|:0041E4C3(U)
|
:0041E4D2 6A0C          push 0000000C  //使用 ANSI_VAR_FONT,我们改为 push 00000011
* Reference To: GDI32.GetStockObject, Ord:015Fh
                 |
:0041E4D4 FF15B8904200      Call dword ptr [004290B8]
:0041E4DA 50           push eax

第三处
:0041E998 FFD3          call ebx
:0041E99A 6A0C          push 0000000C  //使用 ANSI_VAR_FONT,我们改为 push 00000011
:0041E99C 8944244C        mov dword ptr [esp+4C], eax
* Reference To: GDI32.GetStockObject, Ord:015Fh
                 |
:0041E9A0 FF15B8904200      Call dword ptr [004290B8]
:0041E9A6 50           push eax
:0041E9A7 55           push ebp
:0041E9A8 FFD3          call ebx
图像
修改之后,软件界面就很清爽了

OK,这篇文章就写到这里了,希望在碰到 GetStockObject 设置的非标准字体修改问题时,本文能够对大家有所启发和帮助。

参考资料:
1、微软 MSDN
2、“一个小小的挑战……”(http://bbs.hanzify.org/bbs/cgi-bin/topic.cgi?forum=27&topic=9&show=0)

附录:MSDN 中的相关内容
GetStockObject
The GetStockObject function retrieves a handle to one of the stock pens, brushes, fonts, or palettes.
HGDIOBJ GetStockObject(
 int fnObject  // stock object type
);
Parameters
fnObject
[in] Specifies the type of stock object. This parameter can be one of the following values. Value Meaning
BLACK_BRUSH Black brush.
DKGRAY_BRUSH Dark gray brush.
DC_BRUSH Windows 98, Windows 2000: Solid color brush. The default color is white. The color can be changed by using the SetDCBrushColor function. For more information, see the Remarks section.
GRAY_BRUSH Gray brush.
HOLLOW_BRUSH Hollow brush (equivalent to NULL_BRUSH).
LTGRAY_BRUSH Light gray brush.
NULL_BRUSH Null brush (equivalent to HOLLOW_BRUSH).
WHITE_BRUSH White brush.
BLACK_PEN Black pen.
DC_PEN Windows 98, Windows 2000: Solid pen color. The default color is white. The color can be changed by using the SetDCPenColor function. For more information, see the Remarks section.
WHITE_PEN White pen.
ANSI_FIXED_FONT Windows fixed-pitch (monospace) system font.
ANSI_VAR_FONT Windows variable-pitch (proportional space) system font.
DEVICE_DEFAULT_FONT Windows NT/2000: Device-dependent font.
DEFAULT_GUI_FONT Default font for user interface objects such as menus and dialog boxes. This is MS Sans Serif. Compare this with SYSTEM_FONT.
OEM_FIXED_FONT Original equipment manufacturer (OEM) dependent fixed-pitch (monospace) font.
SYSTEM_FONT System font. By default, the system uses the system font to draw menus, dialog box controls, and text.
Windows 95/98 and NT: The system font is MS Sans Serif.
Windows 2000: The system font is Tahoma
SYSTEM_FIXED_FONT Fixed-pitch (monospace) system font. This stock object is provided only for compatibility with 16-bit Windows versions earlier than 3.0.
DEFAULT_PALETTE Default palette. This palette consists of the static colors in the system palette.

Return Values
If the function succeeds, the return value is a handle to the requested logical object.
If the function fails, the return value is NULL.
Windows NT/2000: To get extended error information, call GetLastError.
Remarks
Use the DKGRAY_BRUSH, GRAY_BRUSH, and LTGRAY_BRUSH stock objects only in windows with the CS_HREDRAW and CS_VREDRAW styles. Using a gray stock brush in any other style of window can lead to misalignment of brush patterns after a window is moved or sized. The origins of stock brushes cannot be adjusted.
The HOLLOW_BRUSH and NULL_BRUSH stock objects are equivalent.
The font used by the DEFAULT_GUI_FONT stock object could change. Use this stock object when you want to use the font that menus, dialog boxes, and other user interface objects use.
It is not necessary (but it is not harmful) to delete stock objects by calling DeleteObject.
Windows 98, Windows 2000: Both DC_BRUSH and DC_PEN can be used interchangeably with other stock objects like BLACK_BRUSH and BLACK_PEN. For information on retrieving the current pen or brush color, see GetDCBrushColor and GetDCPenColor. See Setting the Pen or Brush Color for an example of setting colors. The GetStockObject function with an argument of DC_BRUSH or DC_PEN can be used interchangeably with the SetDCPenColor and SetDCBrushColor functions.
Requirements
 Windows NT/2000: Requires Windows NT 3.1 or later.
 Windows 95/98: Requires Windows 95 or later.
 Header: Declared in Wingdi.h; include Windows.h.
 Library: Use Gdi32.lib.

作者:汉化新世纪成员-炎之川 2003.4.23
主页:http://skipli.yeah.net/

炎之川 2003-04-24 13:56
做好的 html 文件在这里:
http://skipli.hanzify.org/doc/loc_07.htm

网上的鱼 2003-04-24 14:09
好文章。简明易懂——我菜还能看得懂。
建议:将 W32Dasm 等可用于汉化的用法做下教程,以提高大家的水平。

simon 2003-04-24 14:51
不错不错,最爱看炎炎的文章,深入浅出、实例丰富、条理清楚

mimizero 2003-04-24 15:57
很好啊~~Aston 里面就很多 GetStockObject ,现在方便了:)

匆匆 2003-04-24 16:33
通俗易懂的好文!
使用 W32Dasm 反汇编,查找“GetStockObject”,记下偏移,用UltraEdit将相应的6A0B、6A0C、6A0D、6A0E、6A10改为6A11后显示十分美观。
谢谢炎!


查看完整版本: [-- [原创] GetStockObject 非标准字体手动修改方法简介 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Time 0.014037 second(s),query:3 Gzip disabled