cxm23 发表于 2015-3-13 16:23:17

请问怎么解决多个图片按钮时的闪烁问题

本帖最后由 cxm23 于 2015-3-15 21:22 编辑

在seniors做的office风格TABhttp://www.autoitx.com/forum.php?mod=viewthread&tid=33574&extra=&page=1的界面上放多个图片按钮,结果图片闪烁很严重,而且切换tab时会出现虚线框,不知有什么解决办法?

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <FontConstants.au3>
#include <WinAPIEx.au3>
#include <TabConstants.au3>
#include <GuiTab.au3>
#include <Constants.au3>
#include <GDIPlus.au3>


Global Const $SC_MOVE = 0xF010

Global $hGUI, $GUIMsg

Global $TabHover = False, $TABActiveID = 0, $TabHoverID = -1, $Count = 0
Global $WinWidth = 225, $WinHeight = 505, $TabWidth = 100, $TabHeight = 30, $Tabcount = 5

Global $hTABCallback = DllCallbackRegister("My_TABProc", "int", "hWnd;uint;wparam;lparam")
Global $tTABCallback = DllCallbackGetPtr($hTABCallback)

$hGUI = GUICreate("GUI1", $WinWidth, $WinHeight, -1, -1, BitOR($WS_SYSMENU, $WS_POPUP))

$Label2 = GUICtrlCreateLabel('×', 203, -4, 20, 30, $SS_CENTER)
GUICtrlSetBkColor(-1, 0xBFDBFF)
;~ GUICtrlSetColor(-1, 0xEFEFEF)
GUICtrlSetFont(-1, 20, 400, 0, 'Verdana')
$tab = GUICtrlCreateTab(0, 0, $WinWidth, $WinHeight, BitOR($TCS_FIXEDWIDTH, $TCS_OWNERDRAWFIXED))
$tabHwnd = GUICtrlGetHandle(-1)
_GUICtrlTab_SetItemSize($tab, $TabWidth, $TabHeight)

$tab_1 = GUICtrlCreateTabItem("项目一")

Global $pic_1
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 42, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 42, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 80, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 80, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 117, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 117, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 155, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 155, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 193, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 193, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 230, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 230, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 268, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 268, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 305, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 305, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 343, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 343, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 381, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 381, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 418, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 418, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 456, 116, 33)
$pic_1 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 456, 116, 33)


$tab_2 = GUICtrlCreateTabItem("项目二")

Global $pic_2
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 48, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 48, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 106, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 106, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 165, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 165, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 223, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 223, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 281, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 281, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 339, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 339, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 398, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 398, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic1.bmp", 58, 456, 116, 33)
$pic_2 = GUICtrlCreatePic(@ScriptDir & "\pic2.bmp", 58, 456, 116, 33)

GUICtrlCreateTabItem("")


For $i=0 To 11
        GUICtrlSetState($pic_1[$i], $GUI_HIDE)
Next

For $i=0 To 7
        GUICtrlSetState($pic_2[$i], $GUI_HIDE)
Next

$hdisplayDC = _WinAPI_CreateDC()
;初始化选项卡图像DC
$MyhImage = _WinAPI_LoadImage(0, @ScriptDir & "\OFFICE.bmp", $IMAGE_BITMAP, 0, 0, $LR_LOADFROMFILE)
$hBmpDC = _WinAPI_CreateCompatibleDC($hdisplayDC)
$hBmpSv = _WinAPI_SelectObject($hBmpDC, $MyhImage)
_WinAPI_DeleteObject($MyhImage)
;初始化临时DC,也就是二次缓冲,防止闪烁
$hTempDC = _WinAPI_CreateCompatibleDC($hdisplayDC)
$hTempImage = _WinAPI_CreateCompatibleBitmap($hdisplayDC, $TabWidth * $Tabcount, $TabHeight)
$hTempSv = _WinAPI_SelectObject($hTempDC, $hTempImage)
_WinAPI_DeleteObject($hTempImage)
_WinAPI_DeleteDC($hdisplayDC)

Global $TABCallProc = _WinAPI_SetWindowLong(GUICtrlGetHandle($tab), -4, $tTABCallback)
GUISetState()
WinSetOnTop($hGUI, "", 1)

While 1

      $GUIMsg = GUIGetMsg()
      Switch $GUIMsg
                                Case $GUI_EVENT_PRIMARYDOWN
                                                _SendMessage($hGUI, $WM_SYSCOMMAND, $SC_MOVE + $HTCAPTION, 0)
                Case $GUI_EVENT_CLOSE
                        _myexitfunc()
                                Case $Label2
                        Exit
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)
                                Case $pic_1
                                                _dButton($pic_1, $pic_1)

                                Case $pic_2
                                                _dButton($pic_2, $pic_2)
                                Case $pic_2
                                                _dButton($pic_2, $pic_2)
                                Case $pic_2
                                                _dButton($pic_2, $pic_2)
                                Case $pic_2
                                                _dButton($pic_2, $pic_2)
                                Case $pic_2
                                                _dButton($pic_2, $pic_2)
                                Case $pic_2
                                                _dButton($pic_2, $pic_2)
                                Case $pic_2
                                                _dButton($pic_2, $pic_2)
                                Case $pic_2
                                                _dButton($pic_2, $pic_2)

      EndSwitch
WEnd
;退出函数,退出前要改回TAB原来的处理函数,不然退出要报错
Func _myexitfunc()
      _WinAPI_SetWindowLong(GUICtrlGetHandle($tab), -4, $TABCallProc)
      DllCallbackFree($hTABCallback)
      ;删除DC
      _WinAPI_SelectObject($hBmpDC, $hBmpSv)
      _WinAPI_DeleteDC($hBmpDC)
      _WinAPI_SelectObject($hTempDC, $hTempSv)
      _WinAPI_DeleteDC($hTempDC)
      Exit
EndFunc   ;==>_myexitfunc

Func My_TABProc($hWnd, $Msg, $wParam, $lParam)
      Switch $Msg
                Case $WM_MOUSEMOVE
                        If Not $TabHover Then;
                              $TabHover = True
                              _WinAPI_TrackMouseEvent($hWnd, 0x00000002)
                        EndIf
                        $mx = _WinAPI_LoWord($lParam)
                        $my = _WinAPI_HiWord($lParam)
                        onMouseMove($hWnd, $mx, $my)
                        Return 0
                Case 0x2A3;WM_MOUSELEAVE
                        $TabHover = False
                        $TabHoverID = -1
                        RedrawAllTAB()
                        Return 0
                Case $WM_ERASEBKGND
                        _JiuGongDraw($wParam, 0, 0, $WinWidth, $WinHeight, $hBmpDC, 19, 25, 1, 2, 0, 0, 0, 0)
                        _JiuGongDraw($wParam, 0, 0, $WinWidth, $TabHeight, $hBmpDC, 0, 0, 1, 27, 0, 0, 0, 1)
                        Return 0
                Case $WM_LBUTTONDOWN
                        $mx = _WinAPI_LoWord($lParam)
                        $my = _WinAPI_HiWord($lParam)
                        onMouseDown($hWnd, $mx, $my)                               
                        Return _WinAPI_CallWindowProc($TABCallProc, $hWnd, $Msg, $wParam, $lParam)
                Case $WM_PAINT
                        If $Count = 0 Then
                              Local $tPAINTSTRUCT, $hDC
                              $Count += 1
                              $hDC = _WinAPI_BeginPaint($hWnd, $tPAINTSTRUCT)
                              RedrawAllTAB()
                              _WinAPI_EndPaint($hWnd, $tPAINTSTRUCT)
                              $Count -= 1
                              Return 0
                        EndIf
      EndSwitch
      Return _WinAPI_CallWindowProc($TABCallProc, $hWnd, $Msg, $wParam, $lParam)
EndFunc   ;==>My_TABProc

Func onMouseMove($hWnd, $mx, $my)
      If $my <= $TabHeight Then
                $Idx = Int($mx / $TabWidth)
                If $Idx >= 0 And $Idx <= $Tabcount - 1 Then
                        If $Idx <> $TabHoverID Then
                              $TabHoverID = $Idx
                              RedrawAllTAB()
                        EndIf
                Else
                        If $TabHoverID <> -1 Then
                              $TabHoverID = -1
                              RedrawAllTAB()
                        EndIf
                EndIf
      Else
                If $TabHoverID >= 0 Then
                        $TabHoverID = -1
                        RedrawAllTAB()
                EndIf
      EndIf
EndFunc   ;==>onMouseMove

Func onMouseDown($hWnd, $mx, $my)
      If $my <= $TabHeight Then
                $Idx = Int($mx / $TabWidth)
                If $Idx >= 0 And $Idx <= $Tabcount - 1 Then
                        $TABActiveID = $Idx
                EndIf
      EndIf
EndFunc   ;==>onMouseDown

Func RedrawAllTAB()
      For $i = 0 To $Tabcount - 1
                If $i = $TabHoverID Then
                        $stata = 1
                Else
                        $stata = 0
                EndIf
                DrawTAB($hTempDC, $i, $stata, $i * $TabWidth, 0, $TabWidth, $TabHeight)
      Next
      $hDC = _WinAPI_GetDC($tabHwnd)
      _WinAPI_BitBlt($hDC, 0, 0, $TabWidth * $Tabcount, $TabHeight, $hTempDC, 0, 0, $SRCCOPY)
      _WinAPI_ReleaseDC($tabHwnd, $hDC)
EndFunc   ;==>RedrawAllTAB

Func DrawTAB($hDC, $nTabID, $TabState, $nLeft, $nTop, $nRight, $nBottom)
      ;这里的数字是由于图像文件决定的
      If $nTabID = $TABActiveID Then;相等就是当前选项卡
                _JiuGongDraw($hDC, $nLeft, $nTop, $nRight, $nBottom, $hBmpDC, 13 + $TabState * 13, 0, 13, 27, 6, 5, 6, 2);$TabState是Hover标志
      Else
                If $TabState = 0 Then
                        _JiuGongDraw($hDC, $nLeft, $nTop, $nRight, $nBottom, $hBmpDC, 0, 0, 1, 27, 0, 0, 0, 1)
                Else
                        _JiuGongDraw($hDC, $nLeft, $nTop, $nRight, $nBottom, $hBmpDC, 0, 0, 13, 27, 6, 5, 6, 2)
                EndIf
      EndIf
      ;绘制选项卡文字
      $tRECT = DllStructCreate($tagRect)
      DllStructSetData($tRECT, "Left", $nLeft)
      DllStructSetData($tRECT, "Top", $nTop)
      DllStructSetData($tRECT, "Right", $nRight + $nLeft)
      DllStructSetData($tRECT, "Bottom", $nBottom)
      _WinAPI_SetBkMode($hDC, $TRANSPARENT)
      $hFont = _WinAPI_CreateFont(14, 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _
                        $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Arial')
      $hOldFont = _WinAPI_SelectObject($hDC, $hFont)
      _WinAPI_DrawText($hDC, _GUICtrlTab_GetItemText($tab, $nTabID), $tRECT, BitOR($DT_CENTER, $DT_VCENTER, $DT_SINGLELINE))
      _WinAPI_SelectObject($hDC, $hOldFont)
      _WinAPI_DeleteObject($hFont)
      Return 1
EndFunc   ;==>DrawTAB

;九宫格绘图,参数依次为:目标DC,左,上,长,高,图像DC,左,上,长,高,左上角的长,左上角的高,右下角的长,右下角的高
Func _JiuGongDraw($hDC, $dstX, $dstY, $dstWidth, $dstHeight, $hSrcDC, $SrcX, $SrcY, $srcWidth, $srcHeight, $gX1 = 0, $gY1 = 0, $gX2 = 0, $gY2 = 0)
      If $dstWidth = 0 Or $dstHeight = 0 Or $srcWidth = 0 Or $srcHeight = 0 Then Return
      Local $hmenDC = _WinAPI_CreateCompatibleDC($hDC)
      Local $hSource = _WinAPI_CreateCompatibleBitmap($hDC, $dstWidth, $dstHeight)
      Local $hSv = _WinAPI_SelectObject($hmenDC, $hSource)
      If $gX1 <= 0 And $gX2 <= 0 And $gY1 <= 0 And $gY2 <= 0 Then
                _WinApi_StretchBlt($hmenDC, 0, 0, $dstWidth, $dstHeight, $hSrcDC, $SrcX + $gX1, $SrcY + $gY1, $srcWidth - $gX2, $srcHeight - $gY2, $SRCCOPY)
      Else
                If $gX1 > 0 And $gY1 > 0 Then ;左上角
                        _WinAPI_BitBlt($hmenDC, 0, 0, $gX1, $gY1, $hSrcDC, $SrcX, $SrcY, $SRCCOPY)
                EndIf
                If $gX2 > 0 And $gY1 > 0 Then ;右上角
                        _WinAPI_BitBlt($hmenDC, $dstWidth - $gX2, 0, $gX2, $gY1, $hSrcDC, $SrcX + $srcWidth - $gX2, $SrcY, $SRCCOPY)
                EndIf
                If $gX1 > 0 And $gY2 > 0 Then ;左下角
                        _WinAPI_BitBlt($hmenDC, 0, $dstHeight - $gY2, $gX1, $gY2, $hSrcDC, $SrcX, $SrcY + $srcHeight - $gY2, $SRCCOPY)
                EndIf
                If $gX2 > 0 And $gY2 > 0 Then ;右下角
                        _WinAPI_BitBlt($hmenDC, $dstWidth - $gX2, $dstHeight - $gY2, $gX2, $gY2, $hSrcDC, $SrcX + $srcWidth - $gX2, $SrcY + $srcHeight - $gY2, $SRCCOPY)
                EndIf
                If $gX1 > 0 Then ;左边框
                        _WinApi_StretchBlt($hmenDC, 0, $gY1, $gX1, $dstHeight - $gY1 - $gY2, $hSrcDC, $SrcX, $SrcY + $gY1, $gX1, $srcHeight - $gY1 - $gY2, $SRCCOPY)
                EndIf
                If $gX2 > 0 Then ;右边框
                        _WinApi_StretchBlt($hmenDC, $dstWidth - $gX2, $gY1, $gX2, $dstHeight - $gY1 - $gY2, $hSrcDC, $SrcX + $srcWidth - $gX2, $SrcY + $gY1, $gX2, $srcHeight - $gY1 - $gY2, $SRCCOPY)
                EndIf
                If $gY1 > 0 Then ;上边框
                        _WinApi_StretchBlt($hmenDC, $gX1, 0, $dstWidth - $gX1 - $gX2, $gY1, $hSrcDC, $SrcX + $gX1, $SrcY, $srcWidth - $gX1 - $gX2, $gY1, $SRCCOPY)
                EndIf
                If $gY2 > 0 Then ;下边框
                        _WinApi_StretchBlt($hmenDC, $gX1, $dstHeight - $gY2, $dstWidth - $gX1 - $gX2, $gY2, $hSrcDC, $SrcX + $gX1, $SrcY + $srcHeight - $gY2, $srcWidth - $gX1 - $gX2, $gY2, $SRCCOPY)
                EndIf
                ;中间的伸展部分
                _WinApi_StretchBlt($hmenDC, $gX1, $gY1, $dstWidth - $gX1 - $gX2, $dstHeight - $gY1 - $gY2, $hSrcDC, $SrcX + $gX1, $SrcY + $gY1, $srcWidth - $gX1 - $gX2, $srcHeight - $gY1 - $gY2, $SRCCOPY)
      EndIf
      _WinAPI_BitBlt($hDC, $dstX, $dstY, $dstWidth, $dstHeight, $hmenDC, 0, 0, $SRCCOPY)
      _WinAPI_SelectObject($hmenDC, $hSv)
      _WinAPI_DeleteObject($hSource)
      _WinAPI_DeleteDC($hmenDC)
EndFunc   ;==>_JiuGongDraw

Func _WinAPI_CreateDC()
      Local $aResult = DllCall("gdi32.dll", "handle", "CreateDC", "str", "DISPLAY", "str", "", "str", "", "ptr", 0)
      If @error Then Return SetError(@error, @extended, 0)
      Return $aResult
EndFunc   ;==>_WinAPI_CreateDC




Func _dButton($pic_array, $pic_id)
;~         GUISetState(@SW_LOCK, $hGUI)
        $count = UBound($pic_array, 1)
        For        $i = 0 To $count -1
                If $pic_array[$i] = $pic_id Then
                        GUICtrlSetState ($pic_array[$i],$GUI_SHOW)
                        GUICtrlSetState ($pic_array[$i],$GUI_HIDE)
                Else
                        GUICtrlSetState ($pic_array[$i],$GUI_SHOW)
                        GUICtrlSetState ($pic_array[$i],$GUI_HIDE)
                EndIf
        Next
;~         GUISetState(@SW_UNLOCK, $hGUI)
EndFunc   ;==>_dButton

bingshen2014 发表于 2015-3-16 09:55:49

感谢楼主分享,辛苦了。
页: [1]
查看完整版本: 请问怎么解决多个图片按钮时的闪烁问题