Jump to content

Progress Bar without animation in Vista/7


Yashied
 Share

Recommended Posts

When I started using Windows 7, I saw the following feature. The state change of the Progress Bar is not jumping, like Windows XP, but smoothly (animation), naturally it takes a while. It certainly looks nice, but in some situations is not necessary. For example, when displays a copying files. I could not disable this animation by using API, and I had to write your own Progress Bar which completely match the current theme. Optionaly, you can specify one of four colors: green (default), red, yellow, or blue (see screenshot). The following example will work properly only in Windows Vista/7, and only for a themeable windows (not classic). I hope this will be useful to someone.

 

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
Edited by Yashied
Link to comment
Share on other sites

Great script. This will be rather useful. But what is state 4 (blue progress)?

Global Const $PBM_NORMAL = 0x0001
Global Const $PBM_ERROR = 0x0002
Global Const $PBM_PAUSED = 0x0003

As far as I know there is only three states? What is the fourth state that makes it blue?

Also in this example state 4 does nothing?

#include <GUIConstantsEx.au3>
#include <ProgressConstants.au3>
#include <SendMessage.au3>
$status = 0
$hGUI = GUICreate("Test", 500, 50)
$hbar = GUICtrlCreateProgress(10, 10, 400, 20)
GUICtrlSetData($hbar, 80)
GUISetState()

While 1
    Sleep(1000)
    $status += 1
    If $status > 4 Then $status = 0
    _SendMessage(GUICtrlGetHandle($hbar), $PBM_SETSTATE, 0x000 & $status, 0)
    WinSetTitle($hGUI, "", "State -> " & $status)
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

[left][sub]We're trapped in the belly of this horrible machine.[/sub][sup]And the machine is bleeding to death...[/sup][sup][/sup][/left]

Link to comment
Share on other sites

I don't use GUICtrlCreateProgress(), I draw a Progress Bar by using DrawThemeBackground() function. The reason for which I wrote _SetProgress() is getting rid of the animation in Windows Vista/7. Different colors are of secondary importance. I don't know why PBM_SETSTATE message not support PBFS_PARTIAL (blue), but it's present in the theme.

EDIT:

Moreover, your example is not working properly (the state 100...).

Edited by Yashied
Link to comment
Share on other sites

This is a workaround to "disable" the animation

GUICreate("Progressbar Win7/Vista Test", 220, 50)
$cProgress = GUICtrlCreateProgress(10, 10, 200, 20, 0x01)
GUISetState()

While 1
    $iValue = Random(0, 99, 1)
    GUICtrlSetData($cProgress, $iValue + 1)
    GUICtrlSetData($cProgress, $iValue)
    Sleep(1000)
WEnd

E

Edited by eukalyptus
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...