WM_INITDIALOG:
Begin
GetClientRect(hDlg,sRect);
sRect.Bottom:=sRect.Top+$14;
SetWindowText(hDlg,szLicenseCaption);
SetDlgItemText(hDlg,1005,szLicenseText);
DialogInit(hDlg);
//暂且叫这个名字吧。
Result:=1;
End;
好,来看看那个奇怪的call:
0000:00404358 ; int __fastcall sub_404358(HWND hWnd)
0000:00404358 sub_404358 proc near
0000:00404358
0000:00404358
0000:00404358 X = word ptr -14h
0000:00404358 Y = word ptr -12h
0000:00404358 Rect = tagRECT ptr -10h //这些局部变量也被改名了,目的是便于阅读分析。
0000:00404358
0000:00404358 push ebx
0000:00404359 push esi
0000:0040435A push edi
0000:0040435B push ebp
0000:0040435C add esp, 0FFFFFFECh //这里相当于sub esp,14h。真不知道Borland那帮人是怎么想的。
//实际上,如果后面没有push,这句就是多余的。这是编译器优化的结果。
//PS:记得TP里是用bp做Local指针的。
0000:0040435F mov edi, eax
0000:00404361 push 0 ; nCmdShow
0000:00404363 push edi ; hWnd
0000:00404364 call ShowWindow
0000:00404369 lea eax, [esp+14h+Rect] //esp+14h,明白了?
0000:0040436D push eax ; lpRect
0000:0040436E push edi ; hWnd
0000:0040436F call GetWindowRect
0000:00404374 mov eax, [esp+14h+Rect.right] //因为API是自己处理esp,所以这里依然是+14h
0000:00404378 mov edx, eax
0000:0040437A sub edx, [esp+14h+Rect.left]
0000:0040437E sar edx, 1
0000:00404380 jns short loc_404385
0000:00404382 adc edx, 0 //OK,这里其实就是取Rect的X轴方向中点。
//sar移过以后,最高位是保持原来的,所以要判断一下,如果<0就
//加回来。这个组合比较巧妙。
//Borland那帮人确实与众不同!
0000:00404385
0000:00404385 loc_404385:
0000:00404385 mov [esp+14h+X], dx
0000:00404389 mov edx, [esp+14h+Rect.bottom]
0000:0040438D sub edx, [esp+14h+Rect.top]
0000:00404391 sar edx, 1
0000:00404393 jns short loc_404398
0000:00404395 adc edx, 0
0000:00404398
0000:00404398 loc_404398:
0000:00404398 mov [esp+14h+Y], dx
0000:0040439D mov ebp, eax //这里eax等于Rect.right
0000:0040439F sar ebp, 1
0000:004043A1 jns short loc_4043A6
0000:004043A3 adc ebp, 0
0000:004043A6
0000:004043A6 loc_4043A6:
0000:004043A6 test bp, bp //应该是进一步保证bp>0,结合下面可以看到,bp是循环变量
0000:004043A9 jl short loc_4043F2
0000:004043AB inc ebp
0000:004043AC xor ebx, ebx //因为ebp在循环体内没有用到,所以可以和ebx合并处理
0000:004043AE
0000:004043AE loc_4043AE: //循环体就没有什么值得注意的地方了,顶多是注意寄存器的变化
0000:004043AE movsx ecx, [esp+14h+Y]
0000:004043B3 movsx eax, bx
0000:004043B6 add ecx, eax
0000:004043B8 push ecx ; int
0000:004043B9 movsx edx, [esp+18h+X] //因为上面push了一下。所以偏移要修改。当时分析时一时没看出来
0000:004043BE mov ecx, edx
0000:004043C0 add ecx, eax
0000:004043C2 push ecx ; int
0000:004043C3 movsx ecx, [esp+1Ch+Y] //这里也是
0000:004043C8 sub ecx, eax
0000:004043CA push ecx ; int
0000:004043CB sub edx, eax
0000:004043CD push edx ; int
0000:004043CE call CreateRectRgn
0000:004043D3 mov esi, eax
0000:004043D5 push 0FFFFFFFFh ; bRedraw
0000:004043D7 push esi ; hRgn
0000:004043D8 push edi ; hWnd
0000:004043D9 call SetWindowRgn
0000:004043DE push 5 ; nCmdShow
0000:004043E0 push edi ; hWnd
0000:004043E1 call ShowWindow
0000:004043E6 push esi ; HGDIOBJ
0000:004043E7 call DeleteObject
0000:004043EC inc ebx
0000:004043ED dec bp
0000:004043F0 jnz short loc_4043AE
0000:004043F2
0000:004043F2 loc_4043F2:
0000:004043F2 add esp, 14h
0000:004043F5 pop ebp
0000:004043F6 pop edi
0000:004043F7 pop esi
0000:004043F8 pop ebx
0000:004043F9 retn
0000:004043F9 sub_404358 endp
这样,我们就得到了那个奇怪的call。
Procedure DialogInit(hDlg:HWND);
Var
RECT:TRect;
X,Y:Word;
i:Word;
Rgn:HRGN;
Begin
ShowWindow(hDlg,SW_HIDE);
GetWindowRect(hDlg,RECT);
X:=(RECT.Right-RECT.Left) DIV 2;
Y:=(RECT.Bottom-RECT.Top) DIV 2;
For i:=1 to RECT.Right DIV 2 do
Begin
Rgn:=CreateRectRgn(X-i,Y-i,X+i,Y+i);
SetWindowRgn(hDlg,Rgn,True);
ShowWindow(hDlg,SW_SHOW);
DeleteObject(Rgn);
End;
End;