gto250 发表于 2014-10-10 23:32:34

编辑框背景透明的代码不起作用的问题

本帖最后由 gto250 于 2014-10-10 23:48 编辑

在网上下载了一个vb的编辑框背景透明的源码,它的原理就获取编辑框所在的窗体中的图片,拷贝编辑框所在位置的图片到编辑框上。
试着将vb的代码改成au3的代码,但是运行的结果是不起作用。
vb的代码是拷贝窗体的图片,我改成了直接拷贝窗体
希望坛里的兄弟帮忙看看问题出在哪里。
au3版本 3.3.13.19


Global Const $GWL_WNDPROC = 0xFFFFFFFC
Global Const $WM_COMMAND = 0x0111
Global Const $WM_CTLCOLOREDIT = 0x0133
Global Const $WM_DESTROY = 0x0002
Global Const $WM_ERASEBKGND = 0x0014
Global Const $WM_HSCROLL = 0x0114
Global Const $WM_VSCROLL = 0x0115
Global Const $SRCCOPY = 0x00CC0020

Global Const $tagRECT = "struct; long Left;long Top;long Right;long Bottom; endstruct"



$Form1 = GUICreate("Form1", 615, 438, 192, 124)
$Input1 = GUICtrlCreateInput("Input1", 152, 104, 193, 21)
$Button1 = GUICtrlCreateButton("Button1", 200, 168, 75, 25)
MakeTransparentTextbox($Input1)
GUISetState(@SW_SHOW)


While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case -3
                        Exit
                Case $Button1

                       
        EndSwitch
WEnd


#cs
Public Function MakeTransparentTextbox(aTxt As TextBox)

CreateBGBrush aTxt


If GetProp(GetParent(aTxt.hwnd), "OrigProcAddr") = 0 Then
    SetProp GetParent(aTxt.hwnd), "OrigProcAddr", SetWindowLong(GetParent(aTxt.hwnd), GWL_WNDPROC, AddressOf NewWindowProc)
End If

If GetProp(aTxt.hwnd, "OrigProcAddr") = 0 Then
    SetProp aTxt.hwnd, "OrigProcAddr", SetWindowLong(aTxt.hwnd, GWL_WNDPROC, AddressOf NewTxtBoxProc)
End If

End Function
#ce
Func MakeTransparentTextbox($Input_id)
$Input_hwnd=GUICtrlGetHandle($Input_id)       

$NewWindowProcNew = DllCallbackRegister("NewWindowProc", "ptr", "hwnd;uint;long;ptr")
$NewTxtBoxProcNew = DllCallbackRegister("NewTxtBoxProc", "ptr", "hwnd;uint;long;ptr")

CreateBGBrush($Input_id)

If GetProp(GetParent($Input_hwnd), "OrigProcAddr") = 0 Then
    SetProp(GetParent($Input_hwnd), "OrigProcAddr", SetWindowLong(GetParent($Input_hwnd), $GWL_WNDPROC, DllCallbackGetPtr($NewWindowProcNew)))
EndIf

If GetProp($Input_hwnd, "OrigProcAddr") = 0 Then
    SetProp($Input_hwnd, "OrigProcAddr", SetWindowLong($Input_hwnd, $GWL_WNDPROC, DllCallbackGetPtr($NewTxtBoxProcNew)))
EndIf
EndFunc

#cs
Private Sub CreateBGBrush(aTxtBox As TextBox)

Dim screenDC As Long
Dim imgLeft As Long
Dim imgTop As Long
Dim picDC As Long
Dim picBmp As Long
Dim aTempBmp As Long
Dim aTempDC As Long
Dim txtWid As Long
Dim txtHgt As Long
Dim SolidBrush As Long
Dim aRect As RECT

If aTxtBox.Parent.Picture Is Nothing Then Exit Sub

txtWid = aTxtBox.Width / Screen.TwipsPerPixelX
txtHgt = aTxtBox.Height / Screen.TwipsPerPixelY
imgLeft = aTxtBox.Left / Screen.TwipsPerPixelX
imgTop = aTxtBox.Top / Screen.TwipsPerPixelY

screenDC = GetDC(0)
picDC = CreateCompatibleDC(screenDC)
picBmp = SelectObject(picDC, aTxtBox.Parent.Picture.Handle)

aTempDC = CreateCompatibleDC(screenDC)
aTempBmp = CreateCompatibleBitmap(screenDC, txtWid, txtHgt)
                                                                  
DeleteObject SelectObject(aTempDC, aTempBmp)
                                                


BitBlt aTempDC, 0, 0, txtWid, txtHgt, picDC, imgLeft, imgTop, vbSrcCopy


If GetProp(aTxtBox.hwnd, "CustomBGBrush") <> 0 Then
    DeleteObject GetProp(aTxtBox.hwnd, "CustomBGBrush")
End If
SetProp aTxtBox.hwnd, "CustomBGBrush", CreatePatternBrush(aTempBmp)


DeleteDC aTempDC
DeleteObject aTempBmp
SelectObject picDC, picBmp
DeleteDC picDC
DeleteObject picBmp
ReleaseDC 0, screenDC

End Sub
#ce
Func CreateBGBrush($Input_id)

$Input_hwnd=GUICtrlGetHandle($Input_id)
$NewRect=GetWindowRect ($Input_hwnd)

$txtWid = DllStructGetData($NewRect,"Right")-DllStructGetData($NewRect,"Left")
$txtHgt = DllStructGetData($NewRect,"Bottom")-DllStructGetData($NewRect,"Top")

ScreenToClient (GetParent ($Input_hwnd),$NewRect)

$imgLeft = DllStructGetData($NewRect,"Left")
$imgTop = DllStructGetData($NewRect,"Top")



$screenDC = GetDC(0)
$picDC = CreateCompatibleDC($screenDC)
$picBmp = SelectObject($picDC, GetParent ($Input_hwnd))

$aTempDC = CreateCompatibleDC($screenDC)
$aTempBmp = CreateCompatibleBitmap($screenDC, $txtWid, $txtHgt)
                                                                  
DeleteObject(SelectObject($aTempDC, $aTempBmp))
                                                


BitBlt($aTempDC, 0, 0, $txtWid, $txtHgt, $picDC, $imgLeft, $imgTop, $SRCCOPY)


If GetProp($Input_hwnd, "CustomBGBrush") <> 0 Then
    DeleteObject(GetProp($Input_hwnd, "CustomBGBrush"))
EndIf
SetProp($Input_hwnd, "CustomBGBrush", CreatePatternBrush($aTempBmp))


DeleteDC($aTempDC)
DeleteObject($aTempBmp)
SelectObject($picDC, $picBmp)
DeleteDC($picDC)
DeleteObject($picBmp)
ReleaseDC(0, $screenDC)       
       
EndFunc



#cs
Private Function NewWindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Dim origProc As Long
Dim isSubclassed As Long

origProc = GetProp(hwnd, "OrigProcAddr")

If origProc <> 0 Then

    If (uMsg = WM_CTLCOLOREDIT) Then
      isSubclassed = (GetProp(lParam, "OrigProcAddr") <> 0)
      If isSubclassed Then
      CallWindowProc origProc, hwnd, uMsg, wParam, lParam
      SetBkMode wParam, 1
      NewWindowProc = GetProp(lParam, "CustomBGBrush")
      Else
      NewWindowProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
      End If
      
    ElseIf uMsg = WM_COMMAND Then
      isSubclassed = (GetProp(lParam, "OrigProcAddr") <> 0)
      If isSubclassed Then
      LockWindowUpdate GetParent(lParam)
      InvalidateRect lParam, 0&, 1&
      UpdateWindow lParam
      End If
      NewWindowProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
      If isSubclassed Then LockWindowUpdate 0&
      
    ElseIf uMsg = WM_DESTROY Then
   
      SetWindowLong hwnd, GWL_WNDPROC, origProc
      NewWindowProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
      RemoveProp hwnd, "OrigProcAddr"
      
    Else
      NewWindowProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
    End If
Else

    NewWindowProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
End If

End Function
#ce

Func NewWindowProc($hwnd, $uMsg, $wParam, $lParam)
$origProc = GetProp(hwnd, "OrigProcAddr")

If $origProc <> 0 Then

    If ($uMsg = $WM_CTLCOLOREDIT) Then
      $isSubclassed = (GetProp($lParam, "OrigProcAddr") <> 0)
      If $isSubclassed Then
      CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
      SetBkMode($wParam, 1)
      Return GetProp($lParam, "CustomBGBrush")
      Else
      Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
      EndIf
      
    ElseIf $uMsg = $WM_COMMAND Then
      $isSubclassed = (GetProp($lParam, "OrigProcAddr") <> 0)
      If $isSubclassed Then
      LockWindowUpdate( GetParent($lParam))
      InvalidateRect ($lParam, 0, 1)
      UpdateWindow ($lParam)
      EndIf
      Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
      If $isSubclassed Then LockWindowUpdate(0)
      
    ElseIf $uMsg = $WM_DESTROY Then
   
      SetWindowLong ($hwnd, $GWL_WNDPROC, $origProc)
       Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
      RemoveProp ($hwnd, "OrigProcAddr")
      
    Else
      Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
    EndIf
Else

    Return DefWindowProc($hwnd, $uMsg, $wParam, $lParam)
EndIf

EndFunc

#cs
Private Function NewTxtBoxProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Dim aRect As RECT
Dim origProc As Long
Dim aBrush As Long


origProc = GetProp(hwnd, "OrigProcAddr")

If origProc <> 0 Then
    If uMsg = WM_ERASEBKGND Then
      aBrush = GetProp(hwnd, "CustomBGBrush")
      If aBrush <> 0 Then
      GetClientRect hwnd, aRect
      FillRect wParam, aRect, aBrush
      NewTxtBoxProc = 1
      Else
      NewTxtBoxProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
      End If
      
    ElseIf uMsg = WM_HSCROLL Or uMsg = WM_VSCROLL Then

      LockWindowUpdate GetParent(hwnd)
      NewTxtBoxProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
      InvalidateRect hwnd, 0&, 1&
      UpdateWindow hwnd
      LockWindowUpdate 0&
      
    ElseIf uMsg = WM_DESTROY Then
   
      aBrush = GetProp(hwnd, "CustomBGBrush")
      DeleteObject aBrush
      RemoveProp hwnd, "OrigProcAddr"
      RemoveProp hwnd, "CustomBGBrush"
      SetWindowLong hwnd, GWL_WNDPROC, origProc
      NewTxtBoxProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
      
    Else
      NewTxtBoxProc = CallWindowProc(origProc, hwnd, uMsg, wParam, lParam)
    End If
Else
    NewTxtBoxProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
End If

End Function
#ce
Func NewTxtBoxProc($hwnd, $uMsg, $wParam, $lParam)

$origProc = GetProp($hwnd, "OrigProcAddr")

If $origProc <> 0 Then
    If $uMsg = $WM_ERASEBKGND Then
      $aBrush = GetProp($hwnd, "CustomBGBrush")
      If $aBrush <> 0 Then
       $aRect= GetClientRect($hwnd)
          
      FillRect($wParam, $aRect, $aBrush)
      Return 1
      Else
      Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
      EndIf
      
    ElseIf $uMsg = $WM_HSCROLL Or $uMsg = $WM_VSCROLL Then

      LockWindowUpdate (GetParent(hwnd))
      Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
      InvalidateRect ($hwnd, 0, 1)
      UpdateWindow (hwnd)
      LockWindowUpdate (0)
      
    ElseIf $uMsg = $WM_DESTROY Then
   
      $aBrush = GetProp($hwnd, "CustomBGBrush")
      DeleteObject ($aBrush)
      RemoveProp ($hwnd, "OrigProcAddr")
      RemoveProp ($hwnd, "CustomBGBrush")
      SetWindowLong ($hwnd, $GWL_WNDPROC, $origProc)
   Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
      
    Else
      Return CallWindowProc($origProc, $hwnd, $uMsg, $wParam, $lParam)
    EndIf
Else
    Return DefWindowProc($hwnd, $uMsg, $wParam, $lParam)
EndIf

EndFunc



Func GetWindowRect($hWnd)
        Local $tRECT = DllStructCreate($tagRECT)
        Local $aRet = DllCall("user32.dll", "bool", "GetWindowRect", "hwnd", $hWnd, "struct*", $tRECT)
        If @error Or Not $aRet Then Return SetError(@error + 10, @extended, 0)

        Return $tRECT
EndFunc   ;==>GetWindowRect

Func ScreenToClient($hWnd, ByRef $tPoint)
        Local $aResult = DllCall("user32.dll", "bool", "ScreenToClient", "hwnd", $hWnd, "struct*", $tPoint)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>ScreenToClient

Func SetWindowLong($hWnd, $iIndex, $iValue)
        SetLastError(0) ; as suggested in MSDN
        Local $sFuncName = "SetWindowLongW"
        If @AutoItX64 Then $sFuncName = "SetWindowLongPtrW"
        Local $aResult = DllCall("user32.dll", "long_ptr", $sFuncName, "hwnd", $hWnd, "int", $iIndex, "long_ptr", $iValue)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>SetWindowLong

Func CallWindowProc($pPrevWndFunc, $hWnd, $iMsg, $wParam, $lParam)
        Local $aResult = DllCall("user32.dll", "lresult", "CallWindowProc", "ptr", $pPrevWndFunc, "hwnd", $hWnd, "uint", $iMsg, _
                        "wparam", $wParam, "lparam", $lParam)
        If @error Then Return SetError(@error, @extended, -1)

        Return $aResult
EndFunc   ;==>CallWindowProc

Func DefWindowProc($hWnd, $iMsg, $wParam, $lParam)
        Local $aResult = DllCall("user32.dll", "lresult", "DefWindowProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, _
                        "lparam", $lParam)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>DefWindowProc

Func BitBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iROP)
        Local $aResult = DllCall("gdi32.dll", "bool", "BitBlt", "handle", $hDestDC, "int", $iXDest, "int", $iYDest, "int", $iWidth, _
                        "int", $iHeight, "handle", $hSrcDC, "int", $iXSrc, "int", $iYSrc, "dword", $iROP)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>BitBlt

Func CreateCompatibleBitmap($hDC, $iWidth, $iHeight)
        Local $aResult = DllCall("gdi32.dll", "handle", "CreateCompatibleBitmap", "handle", $hDC, "int", $iWidth, "int", $iHeight)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>CreateCompatibleBitmap

Func CreateCompatibleDC($hDC)
        Local $aResult = DllCall("gdi32.dll", "handle", "CreateCompatibleDC", "handle", $hDC)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>CreateCompatibleDC

Func CreatePatternBrush($hBitmap)
        Local $aResult = DllCall("gdi32.dll", "handle", "CreatePatternBrush", "handle", $hBitmap)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>CreatePatternBrush

Func CreateSolidBrush($iColor)
        Local $aResult = DllCall("gdi32.dll", "handle", "CreateSolidBrush", "INT", $iColor)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>CreateSolidBrush

Func DeleteDC($hDC)
        Local $aResult = DllCall("gdi32.dll", "bool", "DeleteDC", "handle", $hDC)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>DeleteDC

Func DeleteObject($hObject)
        Local $aResult = DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hObject)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>DeleteObject

Func GetDC($hWnd)
        Local $aResult = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hWnd)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>GetDC

Func GetSysColor($iIndex)
        Local $aResult = DllCall("user32.dll", "INT", "GetSysColor", "int", $iIndex)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>GetSysColor

Func ReleaseDC($hWnd, $hDC)
        Local $aResult = DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "handle", $hDC)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>ReleaseDC

Func SelectObject($hDC, $hGDIObj)
        Local $aResult = DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hGDIObj)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>SelectObject

Func GetProp($hWnd, $sProperty)
      Local $iResult = DllCall("User32.dll", "long", "GetPropW", "hwnd", $hWnd, "wstr", $sProperty)
      Return $iResult
EndFunc

Func SetProp($hWnd, $sProperty, $vData)
      Local $iResult = DllCall("User32.dll", "bool", "SetPropW", "hwnd", $hWnd, "wstr", $sProperty, "long", $vData)
      Return $iResult
EndFunc

Func RemoveProp($hWnd, $sProperty)
      Local $iResult = DllCall("User32.dll", "bool", "RemovePropW", "hwnd", $hWnd, "wstr", $sProperty)
      Return $iResult
EndFunc

Func FillRect($hDC, $pRECT, $hBrush)
        Local $aResult
        If IsPtr($hBrush) Then
                $aResult = DllCall("user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $pRECT, "handle", $hBrush)
        Else
                $aResult = DllCall("user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $pRECT, "dword_ptr", $hBrush)
        EndIf
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>FillRect

Func GetClientRect($hWnd)
        Local $tRECT = DllStructCreate($tagRECT)
        Local $aRet = DllCall("user32.dll", "bool", "GetClientRect", "hwnd", $hWnd, "struct*", $tRECT)
        If @error Or Not $aRet Then Return SetError(@error + 10, @extended, 0)

        Return $tRECT
EndFunc   ;==>GetClientRect

Func GetParent($hWnd)
        Local $aResult = DllCall("user32.dll", "hwnd", "GetParent", "hwnd", $hWnd)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>GetParent

Func InvalidateRect($hWnd, $tRECT = 0, $bErase = True)
        Local $aResult = DllCall("user32.dll", "bool", "InvalidateRect", "hwnd", $hWnd, "struct*", $tRECT, "bool", $bErase)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>InvalidateRect

Func LockWindowUpdate($hWnd)
        Local $aRet = DllCall('user32.dll', 'bool', 'LockWindowUpdate', 'hwnd', $hWnd)
        If @error Then Return SetError(@error, @extended, False)
        ; If Not $aRet Then Return SetError(1000, 0, 0)

        Return $aRet
EndFunc   ;==>LockWindowUpdate

Func SetBkMode($hDC, $iBkMode)
        Local $aResult = DllCall("gdi32.dll", "int", "SetBkMode", "handle", $hDC, "int", $iBkMode)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aResult
EndFunc   ;==>SetBkMode

Func UpdateWindow($hWnd)
        Local $aResult = DllCall("user32.dll", "bool", "UpdateWindow", "hwnd", $hWnd)
        If @error Then Return SetError(@error, @extended, False)

        Return $aResult
EndFunc   ;==>UpdateWindow

Func WindowFromDC($hDC)
        Local $aRet = DllCall('user32.dll', 'hwnd', 'WindowFromDC', 'handle', $hDC)
        If @error Then Return SetError(@error, @extended, 0)

        Return $aRet
EndFunc   ;==>WindowFromDC

Func SetLastError($iErrorCode, Const $_iCurrentError = @error, Const $_iCurrentExtended = @extended)
        DllCall("kernel32.dll", "none", "SetLastError", "dword", $iErrorCode)
        Return SetError($_iCurrentError, $_iCurrentExtended, Null)
EndFunc   ;==>SetLastError
页: [1]
查看完整版本: 编辑框背景透明的代码不起作用的问题