Make your own free website on Tripod.com

再戰非標準字型框-讓 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   ; 定義對話框??
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   ; 定義對話框??
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   ; 定義對話框??
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   ; 定義對話框??
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等資源編輯工具在程式中自己建立第五個對話框 (您可以把??為2300的對話框複製一個來修改,它與Version對話框很相似,我假設您建立的對話框??為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   ; 定義對話框?? (這是修改的)
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」,如果不將資源中的??設定正確,那麼程式執行時點擊這個按鈕不會有任何反映。要確定這個??您可以這樣 (如果您會調試的話,在未修改的程式中攔截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   ; 這就是按鈕的??
: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

您會在程式中找到兩個類似於以上代碼的位置,只有這個才是的,另一個的??處為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 公司的其它軟體,讓其支援並完美的顯示中文。

這篇文章由 樹袋熊 朋友撰寫,漢化新世紀成員-飛鷹 補充、完善。



回教學