Delphi逆向工程筆記[5]

看雪資料發表於2004-11-11

  OK,LicenseProc的最後一部分――WM_PAINT。應該有卻還沒有的效果應該就在裡
面。

0000:00404EBD loc_404EBD:
0000:00404EBD                 lea     eax, [ebp+Paint]
0000:00404EC0                 push    eax             ; lpPaint
0000:00404EC1                 mov     eax, [ebp+hWnd]
0000:00404EC4                 push    eax             ; hWnd
0000:00404EC5                 call    BeginPaint
0000:00404ECA                 push    offset sRect
0000:00404ECF                 push    0
0000:00404ED1                 push    767676h
0000:00404ED6                 mov     ecx, offset dword_4052F0
0000:00404EDB                 mov     edx, ds:dword_4076E8
//結合下面可以看到,這是一個hIcon,但奇怪的是,IDA顯示沒有其它的
//ref。然而我翻了一下前面的程式碼,發現這就是主程式的h_Icon!
//看來IDA的確有問題。

0000:00404EE1                 call    near ptr sub_403FF8
//好吧,又來一個公共call。
//記得以前專門研究過TP/Delphi的傳值問題,但當時寫的東西不知道丟
//哪裡了。不過幸好D5的HLP已經很詳細了。
//從這裡看應該有5個引數,但是考慮到Register方式的特點,我懷疑還
//有第6個引數eax。從邏輯上看也應該是這樣。檢視sub_403FF8發現,
//需要在eax裡放一個hdc,而BeginPaint的返回值就是hdc。
//那麼dword_4052F0是什麼呢?檢視Hex可知,就是視窗標題。這樣,我
//以前的一個分析就被證明是錯誤的,不過不影響已經得到的程式碼。

0000:00404EE6                 lea     eax, [ebp+Paint]
0000:00404EE9                 push    eax             ; lpPaint
0000:00404EEA                 mov     eax, [ebp+hWnd]
0000:00404EED                 push    eax             ; hWnd
0000:00404EEE                 call    EndPaint
0000:00404EF3                 jmp     loc_404F8F

  公共call:

0000:00403FF8 sub_403FF8      proc far
0000:00403FF8
0000:00403FF8 rc              = RECT ptr -50h
0000:00403FF8 var_40          = LOGBRUSH ptr -40h
0000:00403FF8 Rect            = tagRECT ptr -34h
0000:00403FF8 var_24          = word ptr -24h
//這個是迴圈變數
0000:00403FF8 var_22          = word ptr -22h
0000:00403FF8 var_20          = word ptr -20h
0000:00403FF8 var_1E          = word ptr -1Eh
0000:00403FF8 var_1C          = word ptr -1Ch
0000:00403FF8 var_1A          = word ptr -1Ah
0000:00403FF8 var_18          = word ptr -18h
//從var_18到var_22都用了一次
0000:00403FF8 var_16          = word ptr -16h
0000:00403FF8 var_14          = word ptr -14h
0000:00403FF8 var_12          = word ptr -12h
//上面3個有點象rgb,範圍都是位元組,變數
0000:00403FF8 hbr             = dword ptr -10h
//必須說明變數
0000:00403FF8 var_C           = dword ptr -0Ch
//僅用一次
0000:00403FF8 hIcon           = dword ptr -8
//內部沒有改變
0000:00403FF8 hDC             = dword ptr -4
//內部沒有改變
0000:00403FF8 arg_4           = dword ptr  10h
0000:00403FF8
0000:00403FF8                 push    ebp
0000:00403FF9                 mov     ebp, esp
0000:00403FFB                 add     esp, 0FFFFFFB0h
0000:00403FFE                 push    ebx
0000:00403FFF                 push    esi
0000:00404000                 push    edi
0000:00404001                 mov     esi, [ebp+arg_4]
//公共的Rect變數
0000:00404004                 lea     edi, [ebp+Rect]
//區域性Rect變數
0000:00404007                 push    ecx
0000:00404008                 mov     ecx, 4
0000:0040400D                 rep movsd
0000:0040400F                 pop     ecx
//把公共變數複製過來
0000:00404010                 mov     [ebp+var_C], ecx
0000:00404013                 mov     [ebp+hIcon], edx
0000:00404016                 mov     [ebp+hDC], eax
//三個透過reg傳遞的引數
0000:00404019                 xor     eax, eax
0000:0040401B                 call    nullsub_1
//空過程,為什麼?延時?還是Align?
0000:00404020                 and     eax, 0FFh
0000:00404025                 mov     [ebp+var_18], ax
//置0
0000:00404029                 xor     eax, eax
0000:0040402B                 call    sub_403C90
//右移8位
0000:00404030                 and     eax, 0FFh
0000:00404035                 mov     [ebp+var_1A], ax
0000:00404039                 xor     eax, eax
0000:0040403B                 call    sub_403C94
//右移16位,就是取高位
0000:00404040                 and     eax, 0FFh
0000:00404045                 mov     [ebp+var_1C], ax
//置0
//很多廢程式碼

0000:00404049                 mov     eax, 767676h
//這裡很奇特,不知道和那個廢引數有什麼關係。懷疑原來就是
//那個引數,因為除錯的需要臨時註釋掉了,或者相反。

0000:0040404E                 call    nullsub_1
0000:00404053                 and     eax, 0FFh
0000:00404058                 mov     [ebp+var_1E], ax
0000:0040405C                 mov     eax, 767676h
0000:00404061                 call    sub_403C90
0000:00404066                 and     eax, 0FFh
0000:0040406B                 mov     [ebp+var_20], ax
0000:0040406F                 mov     eax, 767676h
0000:00404074                 call    sub_403C94
0000:00404079                 and     eax, 0FFh
0000:0040407E                 mov     [ebp+var_22], ax
//位元組分離,太象RGB了!
0000:00404082                 mov     ebx, [ebp+Rect.right]
0000:00404085                 sub     ebx, [ebp+Rect.left]
0000:00404088                 sar     ebx, 1
0000:0040408A                 jns     short loc_40408F
0000:0040408C                 adc     ebx, 0
//取水平中點,或者說水平長度的一半
0000:0040408F
0000:0040408F loc_40408F:
0000:0040408F                 xor     eax, eax
0000:00404091                 mov     [ebp+rc.top], eax
//清0
0000:00404094                 mov     eax, [ebp+Rect.bottom]
0000:00404097                 sub     eax, [ebp+Rect.top]
0000:0040409A                 mov     [ebp+rc.bottom], eax
//這裡應該是求高
0000:0040409D                 xor     eax, eax
0000:0040409F                 mov     [ebp+var_40.lbStyle], eax
//清0
0000:004040A2                 xor     eax, eax
0000:004040A4                 mov     [ebp+var_40.lbHatch], eax
//同上
0000:004040A7                 test    bx, bx
0000:004040AA                 jl      loc_4041C8
0000:004040B0                 mov     eax, ebx
0000:004040B2                 inc     eax
0000:004040B3                 mov     [ebp+var_24], ax
//sar以後最高位是保留的
0000:004040B7                 xor     edi, edi
//從下面可以看到,edi是個計數器,而var_24是迴圈變數
//一般說迴圈變數會用reg以加快速度的,但是這裡例外
//看迴圈變數就看迴圈末尾的dec什麼的

0000:004040B9
0000:004040B9 loc_4040B9:
//一個Damn迴圈,很長,到004041C2
0000:004040B9                 movsx   esi, bx
//注意movsx,這說明ebx不會很大
//但是ebx>$7f=127可以說明什麼呢?

0000:004040BC                 push    esi             ; nDenominator
0000:004040BD                 push    esi             ; nNumerator
0000:004040BE                 movsx   eax, di
0000:004040C1                 push    eax             ; nNumber
0000:004040C2                 call    MulDiv
//這個地方雖然呼叫了MulDiv,但是由於不知道它是不是由Delphi自動呼叫的,
//所以必須寫段程式實驗一下。用兩個Longword相乘,再除以另外一個Longword。
//可以看到,Delphi用了浮點指令。所以結論是,MulDiv是源程式呼叫的。
//另外,注意到MulDiv的引數意義,可以看出這個呼叫實際是沒有實際作用的。
//這樣的例子下面還有。

0000:004040C7                 mov     [ebp+rc.left], eax
0000:004040CA                 push    esi             ; nDenominator
0000:004040CB                 push    esi             ; nNumerator
0000:004040CC                 movsx   eax, di
0000:004040CF                 inc     eax
0000:004040D0                 push    eax             ; nNumber
0000:004040D1                 call    MulDiv
0000:004040D6                 mov     [ebp+rc.right], eax
0000:004040D9                 push    esi             ; nDenominator
0000:004040DA                 movsx   eax, [ebp+var_1E]
0000:004040DE                 push    eax             ; nNumerator
0000:004040DF                 movsx   eax, di
0000:004040E2                 push    eax             ; nNumber
0000:004040E3                 call    MulDiv
0000:004040E8                 add     ax, [ebp+var_18]
0000:004040EC                 mov     [ebp+var_12], ax
0000:004040F0                 push    esi             ; nDenominator
0000:004040F1                 movsx   eax, [ebp+var_20]
0000:004040F5                 push    eax             ; nNumerator
0000:004040F6                 movsx   eax, di
0000:004040F9                 push    eax             ; nNumber
0000:004040FA                 call    MulDiv
0000:004040FF                 add     ax, [ebp+var_1A]
0000:00404103                 mov     [ebp+var_14], ax
0000:00404107                 push    esi             ; nDenominator
0000:00404108                 movsx   eax, [ebp+var_22]
0000:0040410C                 push    eax             ; nNumerator
0000:0040410D                 movsx   eax, di
0000:00404110                 push    eax             ; nNumber
0000:00404111                 call    MulDiv
0000:00404116                 add     ax, [ebp+var_1C]
0000:0040411A                 mov     [ebp+var_16], ax
0000:0040411E                 cmp     [ebp+var_12], 0FFh
0000:00404124                 jle     short loc_40412C
0000:00404126                 mov     [ebp+var_12], 0FFh
//最大變化到255
0000:0040412C
0000:0040412C loc_40412C:
0000:0040412C                 cmp     [ebp+var_14], 0FFh
0000:00404132                 jle     short loc_40413A
0000:00404134                 mov     [ebp+var_14], 0FFh
0000:0040413A
0000:0040413A loc_40413A:
0000:0040413A                 cmp     [ebp+var_16], 0FFh
0000:00404140                 jle     short loc_404148
0000:00404142                 mov     [ebp+var_16], 0FFh
0000:00404148
0000:00404148 loc_404148:
0000:00404148                 mov     cl, byte ptr [ebp+var_16]
0000:0040414B                 mov     dl, byte ptr [ebp+var_14]
0000:0040414E                 mov     al, byte ptr [ebp+var_12]
0000:00404151                 call    unknown_libname_15 ; Borland Visual Component Library & Packages
//來,拼一下RGB分量
0000:00404156                 mov     [ebp+var_40.lbColor], eax
//返回的分量
0000:00404159                 lea     eax, [ebp+var_40]
0000:0040415C                 push    eax             ; LOGBRUSH *
0000:0040415D                 call    CreateBrushIndirect
0000:00404162                 mov     [ebp+hbr], eax
0000:00404165                 mov     eax, [ebp+hbr]
0000:00404168                 push    eax             ; hbr
0000:00404169                 lea     eax, [ebp+rc]
0000:0040416C                 push    eax             ; lprc
0000:0040416D                 mov     eax, [ebp+hDC]
0000:00404170                 push    eax             ; hDC
0000:00404171                 call    FillRect
0000:00404176                 push    esi             ; nDenominator
0000:00404177                 push    esi             ; nNumerator
0000:00404178                 movsx   eax, di
0000:0040417B                 push    eax             ; nNumber
0000:0040417C                 call    MulDiv
0000:00404181                 mov     edx, [ebp+Rect.right]
0000:00404184                 sub     edx, [ebp+Rect.left]
0000:00404187                 sub     edx, eax
0000:00404189                 mov     [ebp+rc.left], edx
0000:0040418C                 push    esi             ; nDenominator
0000:0040418D                 push    esi             ; nNumerator
0000:0040418E                 movsx   eax, di
0000:00404191                 inc     eax
0000:00404192                 push    eax             ; nNumber
0000:00404193                 call    MulDiv
0000:00404198                 mov     edx, [ebp+Rect.right]
0000:0040419B                 sub     edx, [ebp+Rect.left]
0000:0040419E                 sub     edx, eax
0000:004041A0                 mov     [ebp+rc.right], edx
0000:004041A3                 mov     eax, [ebp+hbr]
0000:004041A6                 push    eax             ; hbr
0000:004041A7                 lea     eax, [ebp+rc]
0000:004041AA                 push    eax             ; lprc
0000:004041AB                 mov     eax, [ebp+hDC]
0000:004041AE                 push    eax             ; hDC
0000:004041AF                 call    FillRect
0000:004041B4                 mov     eax, [ebp+hbr]
0000:004041B7                 push    eax             ; HGDIOBJ
0000:004041B8                 call    DeleteObject
0000:004041BD                 inc     edi
0000:004041BE                 dec     [ebp+var_24]
0000:004041C2                 jnz     loc_4040B9
//迴圈末尾
0000:004041C8
0000:004041C8 loc_4041C8:
0000:004041C8                 mov     [ebp+var_40.lbColor], 9E6A54h
0000:004041CF                 lea     eax, [ebp+var_40]
0000:004041D2                 push    eax             ; LOGBRUSH *
0000:004041D3                 call    CreateBrushIndirect
0000:004041D8                 mov     [ebp+hbr], eax
0000:004041DB                 mov     eax, [ebp+hbr]
0000:004041DE                 push    eax             ; hbr
0000:004041DF                 lea     eax, [ebp+Rect]
0000:004041E2                 push    eax             ; lprc
0000:004041E3                 mov     eax, [ebp+hDC]
0000:004041E6                 push    eax             ; hDC
0000:004041E7                 call    FrameRect
0000:004041EC                 mov     eax, [ebp+hbr]
0000:004041EF                 push    eax             ; HGDIOBJ
0000:004041F0                 call    DeleteObject
0000:004041F5                 push    0DCDCDCh        ; COLORREF
0000:004041FA                 mov     eax, [ebp+hDC]
0000:004041FD                 push    eax             ; HDC
0000:004041FE                 call    SetTextColor
0000:00404203                 push    1               ; int
0000:00404205                 mov     eax, [ebp+hDC]
0000:00404208                 push    eax             ; HDC
0000:00404209                 call    SetBkMode
0000:0040420E                 mov     [ebp+Rect.left], 2
0000:00404215                 mov     [ebp+Rect.top], 2
0000:0040421C                 sub     [ebp+Rect.bottom], 2
0000:00404220                 push    offset locret_4042A4 ; LPCSTR
0000:00404225                 push    0               ; DWORD
0000:00404227                 push    0               ; DWORD
0000:00404229                 push    0               ; DWORD
0000:0040422B                 push    0               ; DWORD
0000:0040422D                 push    1               ; DWORD
0000:0040422F                 push    0               ; DWORD
0000:00404231                 push    0               ; DWORD
0000:00404233                 push    0               ; DWORD
0000:00404235                 push    2BCh            ; int
0000:0040423A                 push    0               ; int
0000:0040423C                 push    0               ; int
0000:0040423E                 push    0               ; int
0000:00404240                 push    0FFFFFFF4h      ; int
0000:00404242                 call    CreateFontA
0000:00404247                 mov     ebx, eax
0000:00404249                 push    ebx             ; HGDIOBJ
0000:0040424A                 mov     eax, [ebp+hDC]
0000:0040424D                 push    eax             ; HDC
0000:0040424E                 call    SelectObject
0000:00404253                 cmp     [ebp+hIcon], 0
0000:00404257                 jz      short loc_40427B
0000:00404259                 push    3               ; diFlags
0000:0040425B                 push    0               ; hbrFlickerFreeDraw
0000:0040425D                 push    0               ; istepIfAniCur
0000:0040425F                 push    10h             ; cyWidth
0000:00404261                 push    10h             ; cxWidth
0000:00404263                 mov     eax, [ebp+hIcon]
0000:00404266                 push    eax             ; hIcon
0000:00404267                 push    2               ; yTop
0000:00404269                 push    2               ; xLeft
0000:0040426B                 mov     eax, [ebp+hDC]
0000:0040426E                 push    eax             ; hdc
0000:0040426F                 call    DrawIconEx
0000:00404274                 mov     [ebp+Rect.left], 14h
0000:0040427B
0000:0040427B loc_40427B:
0000:0040427B                 push    24h             ; uFormat
0000:0040427D                 lea     eax, [ebp+Rect]
0000:00404280                 push    eax             ; lpRect
0000:00404281                 push    0FFFFFFFFh      ; nCount
0000:00404283                 mov     eax, [ebp+var_C]
0000:00404286                 call    @System@@LStrToPChar$qqrv ; System::__linkproc__ LStrToPChar(void)
0000:0040428B                 push    eax             ; lpString
0000:0040428C                 mov     eax, [ebp+hDC]
0000:0040428F                 push    eax             ; hDC
0000:00404290                 call    DrawTextA
0000:00404295                 push    ebx             ; HGDIOBJ
0000:00404296                 call    DeleteObject
0000:0040429B                 pop     edi
0000:0040429C                 pop     esi
0000:0040429D                 pop     ebx
0000:0040429E                 mov     esp, ebp
0000:004042A0                 pop     ebp
0000:004042A1                 retn    0Ch
0000:004042A4
0000:004042A4 ; const CHAR locret_4042A4
0000:004042A4 locret_4042A4:
0000:004042A4                 retf
0000:004042A4 sub_403FF8      endp ; sp = -60h

0000:00403C8C nullsub_1       proc near
0000:00403C8C                 retn
0000:00403C8C nullsub_1       endp

0000:00403C90 sub_403C90      proc near
0000:00403C90                 shr     eax, 8
0000:00403C93                 retn
0000:00403C93 sub_403C90      endp

0000:00403C94 sub_403C94      proc near
0000:00403C94                 shr     eax, 10h
0000:00403C97                 retn
0000:00403C97 sub_403C94      endp

0000:00403C70 ; Borland Visual Component Library & Packages
0000:00403C70 ; Attributes: library function
0000:00403C70
0000:00403C70 unknown_libname_15 proc near
0000:00403C70                 and     eax, 0FFh
0000:00403C75                 and     edx, 0FFh
//取al和dl
0000:00403C7B                 shl     edx, 8
0000:00403C7E                 or      eax, edx
0000:00403C80                 xor     edx, edx
0000:00403C82                 mov     dl, cl
0000:00403C84                 shl     edx, 10h
0000:00403C87                 or      eax, edx
//非常象是RGB的拼裝,位元組順序是
//CL:DL:AL

0000:00403C89                 retn
0000:00403C89 unknown_libname_15 endp

  首先看看引數。這個公共的call從形式上有6個引數,前3個依次用eax,edx,ecx傳,
後3個透過stack傳。從程式碼看,call前push了12個位元組,ret時也pop了12個,堆疊是平
衡的。如果有誰懷疑,不妨自己數數整個call的push和pop,可以鍛鍊一下。我自己沒
有數,但不反對別人數。
  這個call有很多區域性變數和3個堆疊引數,至少形式是這樣,但是IDA只分析出一個
堆疊引數。我一開始以為IDA發飈了,於是畫了一下堆疊,結果發現程式沒有用到第4和
第5個引數,調的時候直接傳了個數的。但是看上去第4個引數好象是個RGB數。對不對,
請laoqian指正。
  分析這個call不能象前面幾個call一樣可以直接寫出框架。只有逐步來。首先寫出
過程首部。

Procedure Paint(dc:HDC;Icon:hIcon;Caption:PChar;dummy:DWORD;dummyRGB:DWORD;Rect:TRect);

  然後直接把ASM改成Pas,但是暫存器名和形如var_18的名稱依然作為變數保留。下
面是精簡變數。簡單的說,就是隻賦值和使用一次的變數可以去掉,其他的作為區域性變
量保留。最後根據變數使用的情況,分別改用適當的名稱,這樣便於閱讀理解。
  下面就是得到的程式碼了:

Procedure Paint(dc:HDC;Icon:hIcon;Caption:PChar;dummy:DWORD;dummyRGB:DWORD;Rect:TRect);

  然後直接把ASM改成Pas,但是暫存器名和形如var_18的名稱依然作為變數保留。下
面是精簡變數。簡單的說,就是隻賦值和使用一次的變數可以去掉,其他的作為區域性變
量保留。最後根據變數使用的情況,分別改用適當的名稱,這樣便於閱讀理解。
  下面就是得到的程式碼了:

Procedure Paint(dc:HDC;Icon:hIcon;Caption:PChar;BeginRGB:DWORD;EndRGB:DWORD;Rect:TRect);
Var
  LogBrush:TLogBrush;
  LRect,rc:TRect;
  LhBR:HBRUSH;
  R,G,B,Ri,Gi,Bi,Rt,Gt,Bt:Word;
  LFont:HFONT;
  Width:Word;
  i:Word;
Begin
  LRect:=Rect;
  
  B:=EndRGB AND $FF;
  G:=(EndRGB SHR 8) AND $FF;
  R:=(EndRGB SHR 16) AND $FF;

  Bi:=BeginRGB AND $FF;
  Gi:=(BeginRGB SHR 8) AND $FF;
  Ri:=(BeginRGB SHR 16) AND $FF;

  Width:=(LRect.right-LRect.left) DIV 2;

  rc.top:=0;
  rc.bottom:=LRect.bottom-LRect.top;

  LogBrush.lbStyle:=0;
  LogBrush.lbHatch:=0;

  If Width>=0 Then
    Begin
      For i:=0 To (Width AND $FF) Do
        Begin
            rc.left:=i;
            rc.right:=i+1;

            Bt:=MulDiv(i,Bi,Width)+B;
            Gt:=MulDiv(i,Gi,Width)+G;
            Rt:=MulDiv(i,Ri,Width)+R;

            If Bt>$FF Then Bt:=$FF;
            If Gt>$FF Then Gt:=$FF;
            If Rt>$FF Then Rt:=$FF;

            LogBrush.lbColor:=(Rt SHL 16) OR (Gt SHL 8) OR (Bt);
            LhBR:=CreateBrushIndirect(LogBrush);
            FillRect(dc,rc,LhBR);

            rc.left:=Rect.right-Rect.left-i;
            rc.right:=Rect.right-Rect.left-i-1;

            FillRect(dc,rc,LhBR);
            DeleteObject(LhBR);
        End;
    End;

  LogBrush.lbColor:=$9E6A54;
  LhBR:=CreateBrushIndirect(LogBrush);
  FrameRect(dc,Rect,LhBR);
  DeleteObject(LhBR);
  SetTextColor(dc,$DCDCDC);
  SetBkMode(dc,1);

  Rect.left:=2;
  Rect.top:=2;
  Dec(Rect.bottom,2);

  LFont:=CreateFont(-$C,0,0,0,$2BC,0,0,0,1,0,0,0,0,'宋體');
  SelectObject(dc,LFont);

  If Icon<>0 Then
    Begin
      DrawIconEx(dc,2,2,Icon,$10,$10,0,0,3);
      Rect.left:=$14;
    End;

  DrawText(dc,Caption,-1,Rect,$24);
  DeleteObject(LFont);
End;

  Shit!效果是:按鈕上的字沒有,標題欄的顏色有問題。標題顏色估計是對signed
int處理不當,但按鈕的字就有點頭痛。只能說,應該是WM_DRAWITEM的問題,但是我傳
的引數肯定是對的,否則是沒有那個三維按鈕效果的!
  按鈕的問題,要麼是SetColor出了問題,要麼就是Get/Set文字出問題。
  好,除錯一下。發現問題!GetWindowText得到的Str是空的!看來還是String的
轉換存在問題。把Str定義為Array of Byte,成功!
  下面就是改正的ItemDraw:

Procedure ItemDraw(lpDIS:PDrawItemStruct);
Var
  Str:Array[1..11] of Byte;
Begin
  FillRect(lpDIS^.hDC,lpDIS^.rcItem,h_Brush);
  SetTextColor(lpDIS^.hDC,$A0A0A0);
  SetBkMode(lpDIS^.hDC,TRANSPARENT);
  DrawEdge(lpDIS^.hDC,lpDIS^.rcItem,BDR_RAISEDOUTER,BF_RECT);
  GetWindowText(lpDIS^.hwndItem,@Str,10);
  DrawText(lpDIS^.hDC,@Str,-1,lpDIS^.rcItem,DT_SINGLELINE OR DT_VCENTER OR DT_CENTER);
  
  If lpDIS^.itemState MOD 2=1 Then
    Begin
      SetTextColor(lpDIS^.hDC,$DDFF);
      DrawText(lpDIS^.hDC,@Str,-1,lpDIS^.rcItem,DT_SINGLELINE OR DT_VCENTER OR DT_CENTER);
      DrawEdge(lpDIS^.hDC,lpDIS^.rcItem,BDR_SUNKENOUTER,BF_RECT);
    End;
End;

  那麼餘下的問題就是顏色了。這個,負數的處理恰好是我頭痛的問題。下次再說
吧……另外,為什麼必須用Array of Byte(上面剛剛提到的嘛),這個也下次分析
了……

  當然,不要指望上面的程式碼和原始程式碼一樣(哪怕是99%的相似),因為我是做了
點最佳化的,去掉了從邏輯上無用的程式碼。

  OK,我很想知道這麼一大篇東西有沒有人會真的有耐心看完,特別是對dump出的代
碼的分析,而不僅僅是Delphi的程式碼。我在上面的分析裡提到以前的一個判斷被證明是
錯誤的。知道我在說什麼的人有興趣的話請在FCG論壇發簡訊告訴我,ID嘛,一樣的。

相關文章