程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi字體修改一例

Delphi字體修改一例

編輯:Delphi

Delphi 字體修改一例

聲明

個人可以自由轉載本文,不過應保持原文的完整性,並通知我;商業轉載先請和我聯系。

本文沒有任何明確或不明確地提示說本文完全正確,閱讀和使用本文的內容是您自己的選擇,本人不負任何責任。

如果您發現本文有錯漏的地方,請您給我指出;如果有什麼不理解的,請您給我提出。

意見、建議和提出的問題最好寫在我的主頁 http://llf.126.com 的留言版上。

前言

漢化人大宇在漢化 CTris2000 這個 Delphi 程序的時候,修改了所有 RCData 中的字體設置,但仍然有一個窗體的字體很難看,我幫他做了修改,在這裡就以它為例說一下 Delphi 程序字體字號的修改。

本來,我以為要詳細的說才能說清,不過現在看來,也未必,所以在這裡還是簡單的說一下算了。

Delphi 程序的字體

關於 Delphi 程序的字體,以我想大概有三種情況:

一、RCData 格式。這種格式的字體字號的問題有很多工具,諸如 eXeScope 、ResHacker 等工具都可以非常方便的修改,而且這也是 Delphi 程序中的字體設置使用最多的方法,而且大多數 Delphi 程序都只使用這一種方式,而其修改方法相對成熟的多,所以我不討論這種方式。

二、SDK 格式。有些 Delphi 程序為了追求最小的獨立可執行文件尺寸,不使用 Delphi 缺省的 VCL 運行庫,而是自行使用 SDK 的編程方式,不過這種程序不多,如果有,個頭也很小,一般是幾K、十幾K的居多,如果在這些程序裡出現字體不協調的問題,可以使用和修改 C 字體字號相同的方法修改。

三、VCL 內部格式。VCL 是 Delphi 使用的函數庫,其內部很可能使用了不是我們所希望的“宋體,9”的窗體,不過我想來想去,也只有類似 VB 函數的 InputBox 有這種可能,也就是 CTris2000 中要求輸入姓名的那個窗體,故我們要談的就是這種方式的程序的字體的修改,而且,幾乎可以確定的固定在 InputBox 上,當然,即使是這一種情況,也比較類似 C 字體的修改,而不是 VB 。(我不知道 Delphi 中相同功能的函數的函數名,所以暫稱其為 InputBox)。

修改過程

我修改的過程比較繁瑣,所以在這裡剔除復雜的部分,簡單的說。

首先,使用 W32dasm 反匯編漢化後的 CTris2000.exe ,存盤,打開 CTris2000.alf 文件,查找 CreateFont ,發現只有 CreateFontIndirectA ,而沒有 CreateFontA ,這真是一個煩人的開始。繼續查找,發現 CreateFontIndirectA 被三個地方調用,地址分別是 4124EC 、420460 和 42A7F3 。

運行 Trw2000 ,調入 CTris2000.exe ,然後鍵入“bpx 4124EC”、“bpx 420460” 和 “bpx 42A7F3”設置斷點,按“F5”運行,中斷時鍵入“dd *esp”查看堆棧的棧頂指針所指的地址的內容,發現大多數情況此地址的開頭都是“FFFFFFF4”,也就是“-12”,是正常的,不過有一次,它是“FFFFFFF5”,也就是“-11”,在它下面一點,我們見到了這種字體的名稱“MS Sans Serif”。

用 ResHacker 檢查 CTris2000.exe ,發現並不是所有的“MS Sans Serif,8”都被改成了“宋體,9”,所以首先把這些沒有改成“宋體,9”的項都改成“宋體,9”,存盤。

用 UEdit 打開 CTris2000.exe ,查找“MS Sans Serif”,只有一個,在 0x5b0b8 處,為了驗證,把這個“MS Sans Serif”改成“System”,運行程序,發現那個輸入窗體的字體確實如我們所想的變成“宋體,12”了。

0x5b0b8 在數據段,所以,數據基偏移 = 基地址 + 數據RVA - 數據Offset = 400000h + 5c000h - 5ae00 = 401200h ,所以,0x5b0b8 的在代碼中為 401200h + 5b0b8 = 45C2B8h 。在 CTris2000.alf 查找“0045C2B8”,沒找到,那麼,查找“0045C2B”吧,找到幾處,如“0045C2B7”、“0045C2B6”和“0045C2B0”,很是奇怪。

運行 Trw2000 ,調入 CTris2000.exe ,像上面一樣設斷點,運行到有問題的 CreateFontA 的時候,鍵入“dd 0045C2B0”,看看是什麼?原來是“FFFFFFF5”!好吧,把“0045C2B0”當作突破口。

打開 CTris2000.alf ,查找“0045C2B0”,發現兩個地方,代碼如下:

* Referenced by a CALL at Address:
|:0041979B   
|
:00419604 53                      push ebx
:00419605 56                      push esi
:00419606 57                      push edi
:00419607 6A48                    push 00000048
:00419609 A1D0E54500              mov eax, dword ptr [0045E5D0]
:0041960E 50                      push eax
:0041960F 6A08                    push 00000008

* Reference To: kernel32.MulDiv, Ord:0000h
                                  |
:00419611 E836BEFEFF              Call 0040544C
:00419616 F7D8                    neg eax
:00419618 A3B0C24500              mov dword ptr [0045C2B0], eax
:0041961D A13CD64500              mov eax, dword ptr [0045D63C]
:00419622 80780800                cmp byte ptr [eax+08], 00
:00419626 743A                    je 00419662
:00419628 E893FFFFFF              call 004195C0
:0041962D 8BD8                    mov ebx, eax
:0041962F 8BC3                    mov eax, ebx
:00419631 2C80                    sub al, 80
:00419633 752D                    jne 00419662
:00419635 BE68964100              mov esi, 00419668
:0041963A BFB7C24500              mov edi, 0045C2B7
:0041963F B904000000              mov ecx, 00000004
:00419644 F3                      repz
:00419645 A5                      movsd
:00419646 6A48                    push 00000048
:00419648 A1D0E54500              mov eax, dword ptr [0045E5D0]
:0041964D 50                      push eax
:0041964E 6A09                    push 00000009

* Reference To: kernel32.MulDiv, Ord:0000h
                                  |
:00419650 E8F7BDFEFF              Call 0040544C
:00419655 F7D8                    neg eax
:00419657 A3B0C24500              mov dword ptr [0045C2B0], eax
:0041965C 881DB6C24500            mov byte ptr [0045C2B6], bl

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00419626(C), :00419633(C)
|
:00419662 5F                      pop edi
:00419663 5E                      pop esi
:00419664 5B                      pop ebx
:00419665 C3                      ret

不知道大家是否能大概看懂上面的代碼,不過它和我在《C 程序字號的修改》裡摘抄的 MSDN 裡建議的設置字號的方式是基本一樣的:

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

我們可以看到,“0041960F”處的“6A08”壓入的就是磅值,我們需要的是 9 磅的字體,所以把“6A08”改成“6A09”就可以了。代碼基偏移 = 基地址 + 代碼RVA - 代碼Offset = 400000h + 1000h - 400h = 400c00h ,41960fh - 400c00h = 18a0fh ,也就是說“6a08”在 0x18a0f 處。

所以,最後的修改是這樣的:把 0x5b0b8 處的 "MS Sans Serif" 改成 "宋體";把 0x18a0f 處的 6a08 改成 6a09 。

雖然我已經簡化了過程,不過好像還是很麻煩,那麼有沒有什麼簡單的方法呢?有的。

一、如果實在不會這樣的修改方法,也不要留著,把“MS Sans Serif”改成“System”是一種簡單有效的方法,遺憾的是字體顯得比較大。

二、先把“MS Sans Serif”改成“宋體”,然後用 W32dasm 反編譯漢化後的程序並存盤後,用 EmEditor 打開 *.alf 文件,按“Ctrl+F”,出現查找對話框,選擇“使用表達式”,在要查找的文本中輸入“push 00000008 * Reference To: kernel32.MulDiv,”,找到的不會很多,把“08”修改成“09”試一試,直到得到正確的結果。

需要注意,第二種方法只適用於 Delphi 程序的 InputBox 的字體修改,而第一種方法適用於所有程序。另外,我因為沒有見到其它類似的 Delphi 程序,也不能肯定第二種方法就是對的,如果各位有見到,不妨一試。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved