Что нового

Progress Bar без анимации, разноцветный для Windows Vista/7

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,714
Когда я перешел на Windows 7, то столкнулся с такой проблемой: изменение состояния Progress Bar'а происходит не скачками, как в Windows XP, а плавно, на что, естественно, требуется какое-то время. Выглядит все это конечно красиво, но в некоторых ситуациях очень не кстати. Например при отображении копирования файлов (пример 4). Как я не старался отключить анимацию, у меня так ничего и не получилось. Поэтому пришлось-таки нарисовать собственный Progress Bar, который полностью соответствует выбранной теме. Дополнительно можно задать один из четырех цветов: зеленый (по умолчанию), красный, желтый или голубой. Данный пример корректно будет работать только в Windows Vista/7, и только с включенной темой (не классический вид).

post_img_053.png

Код:
#Include <WinAPI.au3>

GUICreate('MyGUI', 476, 176)
For $i = 0 To 3
	GUICtrlCreatePic('', 20, 20 + 40 * $i, 280, 16)
	_SetProgress(-1, Random(0, 100, 1), $i)
Next
For $i = 0 To 3
	GUICtrlCreatePic('', 320 + 40 * $i, 20, 16, 136)
	_SetProgress(-1, Random(0, 100, 1), $i, 1)
Next
GUISetState()

Do
Until GUIGetMsg() = -3

Func _SetProgress($hWnd, $iPercent, $iState = 0, $fVertical = False)

	Local $hDC, $hMemDC, $hSv, $hObj, $hBitmap, $hTheme, $tRect, $tClip, $W, $H, $Ret, $Rusult = 1

	If Not IsHWnd($hWnd) Then
		$hWnd = GUICtrlGetHandle($hWnd)
		If Not $hWnd Then
			Return 0
		EndIf
	EndIf
	$hTheme = DllCall('uxtheme.dll', 'ptr', 'OpenThemeData', 'hwnd', $hWnd, 'wstr', 'Progress')
	If (@error) Or (Not $hTheme[0]) Then
		Return 0
	EndIf
	$tRect = _WinAPI_GetClientRect($hWnd)
	$W = DllStructGetData($tRect, 3) - DllStructGetData($tRect, 1)
	$H = DllStructGetData($tRect, 4) - DllStructGetData($tRect, 2)
	$hDC = _WinAPI_GetDC($hWnd)
	$hMemDC = _WinAPI_CreateCompatibleDC($hDC)
	$hBitmap = _WinAPI_CreateSolidBitmap(0, _WinAPI_GetSysColor(15), $W, $H, 0)
	$hSv = _WinAPI_SelectObject($hMemDC, $hBitmap)
	DllStructSetData($tRect, 1, 0)
	DllStructSetData($tRect, 2, 0)
	DllStructSetData($tRect, 3, $W)
	DllStructSetData($tRect, 4, $H)
	$Ret = DllCall('uxtheme.dll', 'uint', 'DrawThemeBackground', 'ptr', $hTheme[0], 'hwnd', $hMemDC, 'int', 2 - (Not $fVertical), 'int', 0, 'ptr', DllStructGetPtr($tRect), 'ptr', 0)
	If (@error) Or ($Ret[0]) Then
		$Rusult = 0
	EndIf
	If $fVertical Then
		DllStructSetData($tRect, 2, $H * (1 - $iPercent / 100))
	Else
		DllStructSetData($tRect, 3, $W * $iPercent / 100)
	EndIf
	$tClip = DllStructCreate($tagRECT)
	DllStructSetData($tClip, 1, 1)
	DllStructSetData($tClip, 2, 1)
	DllStructSetData($tClip, 3, $W - 1)
	DllStructSetData($tClip, 4, $H - 1)
	DllCall('uxtheme.dll', 'uint', 'DrawThemeBackground', 'ptr', $hTheme[0], 'hwnd', $hMemDC, 'int', 6 - (Not $fVertical), 'int', 1 + $iState, 'ptr', DllStructGetPtr($tRect), 'ptr', DllStructGetPtr($tClip))
	If (@error) Or ($Ret[0]) Then
		$Rusult = 0
	EndIf
	_WinAPI_ReleaseDC($hWnd, $hDC)
	_WinAPI_SelectObject($hMemDC, $hSv)
	_WinAPI_DeleteDC($hMemDC)
	DllCall('uxtheme.dll', 'uint', 'CloseThemeData', 'ptr', $hTheme[0])
	If $Rusult Then
		_WinAPI_DeleteObject(_SendMessage($hWnd, 0x0172, 0, $hBitmap))
		$hObj = _SendMessage($hWnd, 0x0173)
		If $hObj <> $hBitmap Then
			_WinAPI_DeleteObject($hBitmap)
		EndIf
	EndIf
	Return $Rusult
EndFunc   ;==>_SetProgress
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
C помощью кнопки тоже не плохо ;D

Код:
#Include <WinAPI.au3>

GUICreate('MyGUI', 476, 176)
$hProgress = GUICtrlCreatePic('', 20, 20, 280, 16)
GUISetState()

For $i = 0 To 100 Step 1
    _SetProgress($hProgress, $i, 1, False)
	Sleep(100)
Next

Do
Until GUIGetMsg() = -3

Func _SetProgress($hWnd, $iPercent, $iState = 0, $fVertical = False)

    Local $hDC, $hMemDC, $hSv, $hObj, $hBitmap, $hTheme, $tRect, $tClip, $W, $H, $Ret, $Rusult = 1

    If Not IsHWnd($hWnd) Then
        $hWnd = GUICtrlGetHandle($hWnd)
        If Not $hWnd Then
            Return 0
        EndIf
    EndIf
    $hTheme = DllCall('uxtheme.dll', 'ptr', 'OpenThemeData', 'hwnd', $hWnd, 'wstr', 'Button')
    If (@error) Or (Not $hTheme[0]) Then
        Return 0
    EndIf
    $tRect = _WinAPI_GetClientRect($hWnd)
    $W = DllStructGetData($tRect, 3) - DllStructGetData($tRect, 1)
    $H = DllStructGetData($tRect, 4) - DllStructGetData($tRect, 2)
    $hDC = _WinAPI_GetDC($hWnd)
    $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
    $hBitmap = _WinAPI_CreateSolidBitmap($hWnd, _WinAPI_GetSysColor(14), $W, $H, 1)
    $hSv = _WinAPI_SelectObject($hMemDC, $hBitmap)

    DllStructSetData($tRect, 1, 0)
    DllStructSetData($tRect, 2, 0)
    DllStructSetData($tRect, 3, $W)
    DllStructSetData($tRect, 4, $H)
    $Ret = DllCall('uxtheme.dll', 'uint', 'DrawThemeBackground', 'ptr', $hTheme[0], 'hwnd', $hMemDC, 'int', 2 - (Not $fVertical), 'int', 0, 'ptr', DllStructGetPtr($tRect), 'ptr', 0)
    If (@error) Or ($Ret[0]) Then
        $Rusult = 0
    EndIf
    If $fVertical Then
        DllStructSetData($tRect, 2, $H * (1 - $iPercent / 100))
    Else
        DllStructSetData($tRect, 3, $W * $iPercent / 100)
    EndIf
    $tClip = DllStructCreate($tagRECT)
    DllStructSetData($tClip, 1, 1)
    DllStructSetData($tClip, 2, 1)
    DllStructSetData($tClip, 3, $W - 1)
    DllStructSetData($tClip, 4, $H - 1)
    DllCall('uxtheme.dll', 'uint', 'DrawThemeBackground', 'ptr', $hTheme[0], 'hwnd', $hMemDC, 'int', 2 - (Not $fVertical), 'int', 1 + $iState, 'ptr', DllStructGetPtr($tRect), 'ptr', DllStructGetPtr($tClip))
    If (@error) Or ($Ret[0]) Then
        $Rusult = 0
    EndIf
    _WinAPI_ReleaseDC($hWnd, $hDC)
    _WinAPI_SelectObject($hMemDC, $hSv)
    _WinAPI_DeleteDC($hMemDC)
    DllCall('uxtheme.dll', 'uint', 'CloseThemeData', 'ptr', $hTheme[0])
    If $Rusult Then
        _WinAPI_DeleteObject(_SendMessage($hWnd, 0x0172, 0, $hBitmap))
        $hObj = _SendMessage($hWnd, 0x0173)
        If $hObj <> $hBitmap Then
            _WinAPI_DeleteObject($hBitmap)
        EndIf
    EndIf
    Return $Rusult
EndFunc   ;==>_SetProgress
 
Верх