汉化分两块,一个和封包有关,另一个就是搞程序。这部分和一般的软件汉化差不多,我这方面经验实在是少,什么时候把汉化新世纪的教材拿出来看看。
今天研究一个程序,找了半天没有DialogBox,或者CreateDialog。最后调下来觉得在comctl32里面,里面就一个函数PropertySheetA。于是拿出api手册,原来如此,还有这么一个东西。
int PropertySheet(
LPCPROPSHEETHEADER lppsph
);
这玩意儿只有一个参数 LPCPROPSHEETHEADER lppsph,该结构如下:
typedef struct _PROPSHEETHEADER { // psh
DWORD dwSize;
DWORD dwFlags;
HWND hwndParent;
HINSTANCE hInstance;
union {
HICON hIcon;
LPCTSTR pszIcon;
};
LPCTSTR pszCaption;
UINT nPages
union {
UINT nStartPage
LPCTSTR pStartPage;
};
union {
LPCPROPSHEETPAGE ppsp;
HPROPSHEETPAGE FAR *phpage;
};
PFNPROPSHEETCALLBACK pfnCallback;
} PROPSHEETHEADER, FAR *LPPROPSHEETHEADER;
第二个字段Flag很重要,Remarks里面提到“If the dwFlags member of the PROPSHEETHEADER structure specifies the PSH_MODELESS flag, PropertySheet creates a modeless dialog and returns immediately after the dialog is created. In this case, the PropertySheet return value is the window handle of the modeless dialog. ”,其他flag做啥我没试过,反正这个flag能创建一个无模式的对话框。(其实调进去也能看到,还是用CreateDialogIndirectParam创建对话框的,但是一开始下he的话od不让。)
倒数第二个字段pStartPage是一个指针,指向PROPSHEETPAGE结构的数组,该结构定义如下:
typedef struct _PROPSHEETPAGE { // psp
DWORD dwSize;
DWORD dwFlags;
HINSTANCE hInstance;
union {
LPCTSTR pszTemplate;
LPCDLGTEMPLATE pResource;
};
union {
HICON hIcon;
LPCTSTR pszIcon;
};
LPCTSTR pszTitle;
DLGPROC pfnDlgProc;
LPARAM lParam;
LPFNPSPCALLBACK pfnCallback;
UINT FAR * pcRefParent;
} PROPSHEETPAGE, FAR *LPPROPSHEETPAGE;
这个结构中pfnDlgProc最为重要,里面是一个消息循环,进入一个通用的dialogproc之后,断在WM_INIT上,再进去,就是初始化Dialog的代码,一般来说往list/combo等控件添加项的代码都在这里。
下面用例子来说明一下,先断PropertySheetA
0044FE42 |. E8 6D7C1900 call <jmp.&COMCTL32.PropertySheetA> ; /PropertySheetA
看堆栈
0012FB9C 0012FBA8 /pPropSheetHeader = 0012FBA8
跟踪过去
PROPSHEETHEADER部分
0012FA38 28 00 00 00 88 00 00 00 30 07 07 00 00 00 00 00
- size - - flag -
0012FA48 00 00 00 00 70 76 5F 00 04 00 00 00 00 00 00 00
- caption - - nPages -
0012FA58 60 FA 12 00 00 00 00 00
- ppsp -
PROPSHEETPAGE List 部分
28 00 00 00 00 00 00 00
list[0] - size -
0012FA68 00 00 40 00 23 76 5F 00 00 00 00 00 00 00 00 00
- template -
0012FA78 BC ED 44 00 00 00 00 00 00 00 00 00 00 00 00 00
- pfnDlgProc -
0012FA88 28 00 00 00 00 00 00 00 00 00 40 00 34 76 5F 00
// list[1]
0012FA98 00 00 00 00 00 00 00 00 B8 F2 44 00 00 00 00 00
0012FAA8 00 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00
// list[2]
0012FAB8 00 00 40 00 46 76 5F 00 00 00 00 00 00 00 00 00
0012FAC8 74 F5 44 00 00 00 00 00 00 00 00 00 00 00 00 00
0012FAD8 28 00 00 00 00 00 00 00 00 00 40 00 5C 76 5F 00
// list[3]
0012FAE8 00 00 00 00 00 00 00 00 A0 F6 44 00 00 00 00 00
0012FAF8 00 00 00 00 00 00 00 00 00 00 40 00 30 07 07 00
对4个pfnDlgProc下断,断在第一个函数44EDBC。F7一路下去找到来到这里:
0045063B |> /8B55 0C mov edx, dword ptr [ebp+C] ; Case 110 (WM_INITDIALOG) of switch 004505F9
0045063E |. 52 push edx
0045063F |. 50 push eax
00450640 |. 8B08 mov ecx, dword ptr [eax]
00450642 |. FF51 04 call dword ptr [ecx+4] ; 0045083C
断在450642,然后F7进去就行了。