Delphi 字号修改之二

Delphi 字号修改之二


声明

个人可以自由转载本文,不过应保持原文的完整性,并通知我;商业转载先请和我联系。

本文没有任何明确或不明确地提示说本文完全正确,阅读和使用本文的内容是您自己的选择,本人不负任何责任。

如果您发现本文有错漏的地方,请您给我指出;如果有什么不理解的,请您给我提出。

意见、建议和提出的问题最好写在我的主页 http://llf.126.com 的留言版上。

Hint

在上次的 Delphi 消息框字体问题之后,又有汉化人提出 Hint 字体修正的问题,在说这一个问题之前,我们要再熟悉一下微软推荐的字体设置方法:

	nHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);

大家也看到了,最后一个参数是 72 ,也就是十六进制的 0x48 ,而且它是一个常数,所以这样的语句编译到可执行文件中的时候就会出现一个明显的 push 00000048 的语句,而且,因为 72 是最后一个参数,所以这个 push 语句是这一行程序的第一个 push 语句,这样,上次我们介绍的修改消息框的方法就可以用 push 00000048 作为辅助判断方法,据大宇说,用这种方法判断,迄今为止是百发百中的。 :)

而这一次的 Hint 的问题,因为在反编译出来的文件中找不到“push 00000008/n/n* Reference To: kernel32.MulDiv,”或上面几行没有“push 00000048”,所以无法找到需要修改的地方,我通过查找代码发现,对于 Hint 的字体设置,其中并不是直接压入 8 ,也就是说没有明显的 push 00000008 ,但是仍然是可以修改的。

以前 ChinEase 曾问过 iProtect SoHo 的字体问题,当时我并不熟悉,以为主界面是使用了枚举的方式设置的字体,觉得不能解决,不过现在才发现其实其主界面字体是可以自己设置的,所以所剩的字体问题仍然是 Hint 的问题,在这里就以 iProtect SoHo 为例说一下。

用 W32dasm 反编译 iprotect.exe ,生成 iprotect.alf ,打开它,查找 push 00000048 ,发现四个,其中后两个一个因为在 call MulDiv 之上的语句是 push 00000009 ,所以已经是 9 磅的字体,另一个后面根本没有 call MulDiv ,所以更不是我们所要找的语句了,剩下的两个如下:

	* Referenced by a CALL at Addresses:
	|:00412279   , :00416EAA   , :0041D93C   , :00425408   , :004BAFCA   
	|:004BB710   
	|
	:0041DB38 53                      push ebx
	:0041DB39 8BD8                    mov ebx, eax
	:0041DB3B 8B4314                  mov eax, dword ptr [ebx+14]
	:0041DB3E 50                      push eax
	:0041DB3F 6A48                    push 00000048
	:0041DB41 8BC3                    mov eax, ebx
	:0041DB43 E864FFFFFF              call 0041DAAC
	:0041DB48 50                      push eax

	* Reference To: kernel32.MulDiv, Ord:0000h
	                                  |
	:0041DB49 E8A67BFEFF              Call 004056F4
	:0041DB4E F7D8                    neg eax
	:0041DB50 5B                      pop ebx
	:0041DB51 C3                      ret


	:0041DB52 8BC0                    mov eax, eax

	* Referenced by a CALL at Addresses:
	|:00412298   , :00416EB9   , :0041AE0F   , :0041D945   , :00425417   
	|:0043CC63   , :0043D62A   , :00471F31   , :004914F4   , :0049CB09   
	|:004B6212   , :004BA4DA   , :004BA51E   , :004BB720   , :004D4955   
	|
	:0041DB54 53                      push ebx
	:0041DB55 56                      push esi
	:0041DB56 8BF2                    mov esi, edx
	:0041DB58 8BD8                    mov ebx, eax
	:0041DB5A 6A48                    push 00000048
	:0041DB5C 8B4314                  mov eax, dword ptr [ebx+14]
	:0041DB5F 50                      push eax
	:0041DB60 56                      push esi

	* Reference To: kernel32.MulDiv, Ord:0000h
	                                  |
	:0041DB61 E88E7BFEFF              Call 004056F4
	:0041DB66 8BD0                    mov edx, eax
	:0041DB68 F7DA                    neg edx
	:0041DB6A 8BC3                    mov eax, ebx
	:0041DB6C E843FFFFFF              call 0041DAB4
	:0041DB71 5E                      pop esi
	:0041DB72 5B                      pop ebx
	:0041DB73 C3                      ret

可以看到,在 call MulDiv 之上并不是压入的常数,而是寄存器值,而这两段代码其实是函数,所以它是通过别人调用来设置的,这需要跟踪才能知道究竟是谁在调用,我最近发现其实 W32dasm 也可以进行动态跟踪,因为不会中止其它进程,所以我现在比较喜欢用 W32dasm 来跟踪 —— 可以同时听 mp3 。 :) 不过 W32dasm 的跟踪界面有些零乱,我就不介绍了。在这里,跟踪到调用者:

	:0041ADFA BA38AE4100              mov edx, 0041AE38
	:0041ADFF 8B460C                  mov eax, dword ptr [esi+0C]
	:0041AE02 E8ED2C0000              call 0041DAF4
	:0041AE07 BA08000000              mov edx, 00000008
	:0041AE0C 8B460C                  mov eax, dword ptr [esi+0C]
	:0041AE0F E8402D0000              call 0041DB54

就是最后一个 call 0041DB54 调用了上面的设置字体的代码,我们发现很明显的上面有一个 mov edx, 00000008 ,我们尝试把它修改成 mov edx, 0000000F ,运行程序,发现 Hint 的字体真的变得很大了,也就是说,改对地方了。

另外,第一句的 mov edx, 0041AE38 其实压入的是字体名,所以最后的修改是:把 0x1a239 处的“MS Sans Serif”改成“宋体”,把 0x1a208 处的 08 改成 09 。(0x1a238 处是字体名的长度计数器,最好也修改成 04)

简单方法

上面的介绍只是为了让大家知道为什么要这样修改,其实是有一种简单的方法找到要修改的地方的。我说过,Delphi 程序员一般不会自己创建字体,所以这里的仍然是 VCL 的问题,而 VCL 编译出来的代码不会因为不同的程序而不同,所以仍然有规律可循。

不知道大家注意到没有,上面修改的地方相差不大,一个 0x1a239 ,一个 0x1a208 ,只相差 0x31 ,对于 UEdit 来说,就是三行多一个字符,其实这就是它的规律,我们可以先找到究竟是哪一个字体名的问题,再向上三行,找到一个“BA 08”,把它改成“BA 09”就可以了,我修改的几个程序用这种方法的成功率目前也是百分之百的。:)

至于怎么找到是哪一个字体名的问题,我就不说了 —— 顶多一个一个的改成“System”进行测试,一定可以找到的。 :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
应用程序在运行当中经常要输出各种即时信息,Delphi提供了多种形式的消息对话框可以满足这些要求,尽管可以使用各种标志定制一个消息框,但仍不能将自己的图标放在消息框内,也不能修改其标准行为去创建自己的消息框,其实通过调用函数MessageBoxIndirect()就很容易绕过这些明确的限制,这是一个功能很强、易于使用的函数。 ---- 此函数在WINDOWS单元里面,文件位于Delphi安装路径Source\Rtl\Win里面,需要指出的是,Delphi的原代码中它的返回值类型是BOOL型,而实质上它的返回值应为Integer。修改方法:在WINDOWS单元中找到此函数后,把BOOL改为Integer,共有三处要修改,然后在Delphi安装路径Lib中找到WINDOWS.DCU文件,把它改名或者删除,并把修改后的WINDOWS.PAS源码复制到Lib路径中。 ---- 该函数只有一个参数,类型是TMsgBoxParams,它的结构及说明如下: tagMSGBOXPARAMSA = packed record cbSize: UINT; {数据结构的长度} hwndOwner: HWND; {所有者窗口句柄} hInstance: HINST; {应用程序实例句柄} lpszText: PAnsiChar; {在消息框客户区内显示的文本} lpszCaption: PAnsiChar; {标题栏文本} dwStyle: DWORD; {确定消息框内按钮和图符 的数量及种类的MB_标志} lpszIcon: PAnsiChar; {从资源文件中取出的一个 图符资源的名字} dwContextHelpId: DWORD; {指定帮助文本的ID号} lpfnMsgBoxCallback: TPRMsgBoxCallback; {当用户按下HELP按钮时调用的一个回 调函数} dwLanguageId: DWORD; {显示在按钮内文本的语言定义} end; ---- 由于直接使用此函数比较复杂,我们可以自定义一个函数来封装此函数,对它进行简化,在用法上尽量做到与Delphi的消息框相一致,自定义函数代码如下: function MessageEx (lText,lCaption:PChar; lStyle:DWord;lIcon:PChar):Integer; var Msg:TMsgBoxParams; begin Msg.cbSize:=Sizeof(Msg); Msg.hwndOwner:=Application.Handle; Msg.hInstance:=hinstance; Msg.lpszText:=lText; Msg.lpszCaption:=lCaption; Msg.dwStyle:=lStyle; Msg.lpszIcon:=lIcon; Msg.dwContextHelpId:=1; Msg.lpfnMsgBoxCallback:=nil; Msg.dwLanguageId:=LANG_NEUTRAL; Result:=MessageBoxIndirect(Msg); end; ---- 要想在消息框中显示自己的图标,先准备一个装有图标的资源文件,加在程序中,如{$R c:\mydir\myres.res},在lStyle参数里除了所需的MB_标志外还要加上MB_USERICON标志,并在最后一个参数里写上资源文件中图标的名字,如果不想使用自定义的图标,可将最后一个参数设为nil。函数的其它用法和返回值的处理与Delphi提供的消息框一样。 ---- 强烈建议把自定义函数放在一个单元文件里,并把此文件放在Delphi的搜索路径如Lib下,以后只需要把此单元加在uses语句里,就可以直接使用自定义函数,非常方便。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值