Jump to content

_CircularProgress


Go to solution Solved by UEZ,

Recommended Posts

Posted (edited)

  3i7dy.png


I created _CircularProgress , with the idea of calling it as a single function.

; https://www.autoitscript.com/forum/topic/213118-_circularprogress/
;----------------------------------------------------------------------------------------
; Title...........: _CircularProgress.au3
; Description.....: Creates a customizable circular progress bar using GDI+ graphics.
; AutoIt Version..: 3.3.16.1   Author: ioa747  Script Version: 0.6
; Note............: Testet in Win10 22H2       Date:09/09/2025
; Based on post ..: https://www.autoitscript.com/forum/topic/213118-_circularprogress/#findComment-1545797
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <WinAPIConstants.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>
#include <Array.au3>


_Example() ; as demo

;~ _Example2() ; as demo


Func _Example()
    Local $aList[2000]
    Local $iCnt = UBound($aList)
    ConsoleWrite("$iCnt=" & $iCnt & @CRLF)
    Local $nProgress

    For $i = 1 To UBound($aList)
        $nProgress = Int($i / $iCnt * 100)
        ConsoleWrite($i & ")  $nProgress=" & $nProgress & @CRLF)
        _CircularProgress($nProgress)
    Next

    Sleep(500) ; Give it some time to show the 100%.
    _CircularProgress(101) ; Clean up the progress bar window
EndFunc   ;==>_Example

Func _Example2()
    Local $aList[2000]
    Local $iCnt = UBound($aList)
    Local $nProgress
    _CircularProgress(0, 300, @DesktopWidth * 0.8, @DesktopHeight * 0.3)
    For $i = 1 To UBound($aList)
        $nProgress = Int($i / $iCnt * 100)
        _CircularProgress($nProgress)
    Next

    For $i = 1 To 2
        _CircularProgress($nProgress, -1, -1, -1, -1, 0xFFBFBFBF, 0xFF4CFF00, 0xFFFFFF00)
        Sleep(500)
        _CircularProgress($nProgress, -1, -1, -1, -1, 0xFFBFBFBF, 0xFFFFFF00, 0xFF4CFF00)
        Sleep(500)
    Next

    _CircularProgress(101) ; Clean up the progress bar window
EndFunc   ;==>_Example

; #FUNCTION# ====================================================================================================================
; Name...........: _CircularProgress
; Description....: Creates a customizable circular progress bar using GDI+ graphics.
; Syntax.........: _CircularProgress($iPercent [, $iSize = 300 [, $iLeft = -1 [, $iTop = -1 [, $iThickness = 23 [, $TextCol = 0xFFBFBFBF [, $StartCol = 0xFFFFFF00, $EndCol = 0xFFFF0000]]]]]])
; Parameters.....: $iPercent     - The percentage complete for the progress bar (0 to 100).
;                  $iSize        - [optional] width and height of the circular progress bar. (Default is 300)
;                  $iLeft        - [optional] X-coordinate of the top-left corner. (Default is -1 for center)
;                  $iTop         - [optional] Y-coordinate of the top-left corner. (Default is -1 for center)
;                  $iThickness   - [optional] Thickness of the progress arc. (Default is 23)
;                  $TextCol      - [optional] Color of the text within the progress bar. (Default is Silver)
;                  $StartCol     - [optional] Start color of the progress arc gradient. (Default is Yellow)
;                  $EndCol       - [optional] End color of the progress arc gradient. (Default is Red)
; Return values .: Success: create the progress bar GUI
; Author ........: ioa747 , Thank to UEZ
; Modified ......: 09/09/2025 - v0.6
; Remarks .......: Cleanup is handled automatically by passing an $iPercent > 100.
;                  Avoid using 0x050505 Color for $TextCol, $StartCol, or $EndCol, as it is used as a transparency color for the background.
; Related .......: _GDIPlus_Startup, _GDIPlus_GraphicsCreateFromHWND, etc.
; Link ..........: https://www.autoitscript.com/forum/topic/213113-simple-circular-progressbar-with-smooth-edges-gradient-color/#findComment-1545755
; Example .......: _CircularProgress(50, 300, -1, -1, 23, 0xFFBFBFBF, 0xFFFFFF00, 0xFFFF0000)
; ===============================================================================================================================
Func _CircularProgress($iPercent, $iSize = 300, $iLeft = -1, $iTop = -1, $iThickness = 23, $TextCol = 0xFFDCDCDC, $StartCol = 0xFFFFFF00, $EndCol = 0xFFFF0000)
    Local Static $hGUI, $inSize, $inThickness, $iRadius, $iX, $iY, $bInit = False

    If Not $bInit Then
        _GDIPlus_Startup()
        $inThickness = $iThickness
        $inSize = $iSize
        $iRadius = ($inSize - 4) / 2
        $iX = $inSize / 2
        $iY = $iX
        $hGUI = GUICreate("RingProgressBar", $inSize, $inSize, $iLeft, $iTop, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
        GUISetState(@SW_SHOWNOACTIVATE)
        $bInit = True
    EndIf

    If $iPercent > 100 Then
        _GDIPlus_Shutdown()
        GUIDelete($hGUI)
        $bInit = False
        Return
    EndIf

    ; Create an off-screen bitmap for double-buffering
    Local $hBmp = _GDIPlus_BitmapCreateFromScan0($inSize, $inSize)
    Local $hBmpGraphics = _GDIPlus_ImageGetGraphicsContext($hBmp)
    _GDIPlus_GraphicsSetSmoothingMode($hBmpGraphics, 4)
    _GDIPlus_GraphicsSetTextRenderingHint($hBmpGraphics, 4)

    ; Draw progress arc as pie
    Local $angle = ($iPercent / 100) * 360
    Local $hBrushProg = _GDIPlus_LineBrushCreate($iX - $iRadius, $iY, $iX + $iRadius, $iY, $EndCol, $StartCol, 1)
    Local $hPen = _GDIPlus_PenCreate2($hBrushProg, $inThickness)
    _GDIPlus_GraphicsDrawArc($hBmpGraphics, $iX - $iRadius + $inThickness / 2, $iY - $iRadius + $inThickness / 2, _
            $iRadius * 2 - $inThickness, $iRadius * 2 - $inThickness, -90, $angle, $hPen)

    _GDIPlus_BrushDispose($hBrushProg)
    _GDIPlus_PenDispose($hPen)

    ; Draw percentage text
    Local $hFontFamily = _GDIPlus_FontFamilyCreate("Times New Roman")
    Local $iFontSize = $iRadius * 0.23
    Local $hFont = _GDIPlus_FontCreate($hFontFamily, $iFontSize, 1)
    Local $hFormat = _GDIPlus_StringFormatCreate()
    Local $hBrushText = _GDIPlus_BrushCreateSolid($TextCol)
    _GDIPlus_StringFormatSetAlign($hFormat, 2)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 2)

    ; black outline
    Local $hBrushOutline = _GDIPlus_BrushCreateSolid(0xFF000000)
    Local $rect = _GDIPlus_RectFCreate(($inSize - ($iFontSize * 4)) / 2, ($inSize - ($iFontSize * 2)) / 2, $iFontSize * 4, $iFontSize * 2)
    Local $iOffset = 1 ; Offset for the outline, Adjust this value for thicker/thinner outline

    ; Draw outline text by offsetting the position
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X - $iOffset, $rect.Y, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X + $iOffset, $rect.Y, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X, $rect.Y - $iOffset, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X, $rect.Y + $iOffset, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)

    ; Draw the main text on top
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, $rect, $hFormat, $hBrushText)

    _GDIPlus_BrushDispose($hBrushOutline)
    _GDIPlus_FontFamilyDispose($hFontFamily)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrushText)

    ; Create HBITMAP and display
    Local $hHBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
    ;_WinAPI_BitmapDisplayTransparentInGUI($hHBmp, $hGUI)
    Local $iOpacity = 0xFF, $iFlags = $ULW_ALPHA, $bReleaseGDI = True, $tDest = Null, $iBGR = 0
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBmp, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBmp)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, $tDest, $tSize, $hMemDC, $tSource, $iBGR, $tBlend, $iFlags)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBmp)
    ;Return True

    _GDIPlus_BitmapDispose($hBmp)
    _GDIPlus_GraphicsDispose($hBmpGraphics)
EndFunc   ;==>_CircularProgress

 

Please, every comment is appreciated!
leave your comments and experiences here!
Thank you very much  :)

 

 

 

Edited by ioa747
update to Version: 0.6

I know that I know nothing

Posted (edited)

It looks ugly on my Notebook:

 

Circular-Progress.jpg

You may use:

Func _WinAPI_BitmapDisplayTransparentInGUI(ByRef $hHBitmap, ByRef $hGUI, $iOpacity = 0xFF, $iFlags = $ULW_ALPHA, $bReleaseGDI = True, $tDest = Null, $iBGR = 0)
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBitmap, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, $tDest, $tSize, $hMemDC, $tSource, $iBGR, $tBlend, $iFlags)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBitmap)
    Return True
EndFunc   ;==>_WinAPI_BitmapDisplayTransparentInGUI

to get a proper display. See 

for an example. 

_WinAPI_SetLayeredWindowAttributes() only makes is ugly!

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)

UEZ Thank you very much for your advice.

From what I understand
the trace you see in the image is a side effect of antialiasing, (in combination with _WinAPI_SetLayeredWindowAttributes)
which can be mitigated by changing the value to 1,
or avoided by changing the value to 0,
in the line

_GDIPlus_GraphicsSetSmoothingMode($hBmpGraphics, 2)

at a small cost to quality  😞

Smoothing mode:
    0 - Smoothing is not applied
    1 - Smoothing is applied using an 8 X 4 box filter
    2 - Smoothing is applied using an 8 X 8 box filter
(The color I have chosen for the background it is almost black, is suitable for a dark environment.)

The other solution I found is
to not make the large circle transparent, so that the ring has a background color that will fill in progressively. (which will hide the trace of the antialiasing.)


I tried to adapt _WinAPI_BitmapDisplayTransparentInGUI to my script, but I couldn't make the circle above the pie transparent, so that only the ring is visible.

Edited by ioa747

I know that I know nothing

  • Solution
Posted

To use _WinAPI_BitmapDisplayTransparentInGUI() you must create a complete frame within the function.

Example:

; https://www.autoitscript.com/forum/topic/213118-_circularprogress/
;----------------------------------------------------------------------------------------
; Title...........: _CircularProgress.au3
; Description.....: Creates a customizable circular progress bar using GDI+ graphics.
; AutoIt Version..: 3.3.16.1   Author: ioa747  Script Version: 0.5
; Note............: Testet in Win10 22H2       Date:08/09/2025
; Based on post ..: https://www.autoitscript.com/forum/topic/213113-simple-circular-progressbar-with-smooth-edges-gradient-color/#findComment-1545755
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>
#include <WinAPIConstants.au3>
#include <Array.au3>

_GDIPlus_Startup()
Global $hGUI

_Example() ; as demo

_GDIPlus_Shutdown()


Func _Example()
    $hGUI = GUICreate("RingProgressBar", 300, 300, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
    GUISetState(@SW_SHOW)
    Local $aList[2000]
    Local $iCnt = UBound($aList)
    ConsoleWrite("$iCnt=" & $iCnt & @CRLF)
    Local $nProgress

    For $i = 1 To UBound($aList)
        $nProgress = Int($i / $iCnt * 100)
        ConsoleWrite($i & ")  $nProgress=" & $nProgress & @CRLF)
        _CircularProgress($nProgress)
    Next

    Sleep(200) ; Give it some time to see the 100%.
EndFunc   ;==>_Example

; #FUNCTION# ====================================================================================================================
; Name...........: _CircularProgress
; Description....: Creates a customizable circular progress bar using GDI+ graphics.
; Syntax.........: _CircularProgress($iPercent [, $iLeft = -1 [, $iTop = -1 [, $iSize = 300 [, $iThickness = 30 [, $TextCol = 0xFFFFFF [, $StartCol = 0xFF0000, $EndCol = 0xFFFF00]]]]]])
; Parameters.....: $iPercent     - The percentage complete for the progress bar (0 to 100).
;                  $iLeft        - [optional] X-coordinate of the top-left corner. (Default is -1 for center)
;                  $iTop         - [optional] Y-coordinate of the top-left corner. (Default is -1 for center)
;                  $iSize        - [optional] width and height of the circular progress bar. (Default is 300)
;                  $iThickness   - [optional] Thickness of the progress arc. (Default is 30)
;                  $TextCol      - [optional] Color of the text within the progress bar. (Default is White)
;                  $StartCol     - [optional] Start color of the progress arc gradient. (Default is Yellow)
;                  $EndCol       - [optional] End color of the progress arc gradient. (Default is Red)
; Return values .: Success: create the progress bar GUI
; Author ........: ioa747
; Modified ......: 08/09/2025 - v0.5
; Remarks .......: Cleanup is handled automatically by passing an $iPercent > 100.
;                  Avoid using 0x050505 Color for $TextCol, $StartCol, or $EndCol, as it is used as a transparency color for the background.
; Related .......: _GDIPlus_Startup, _GDIPlus_GraphicsCreateFromHWND, etc.
; Link ..........: https://www.autoitscript.com/forum/topic/213113-simple-circular-progressbar-with-smooth-edges-gradient-color/#findComment-1545755
; Example .......: _CircularProgress(50, -1, -1, 300, 20, 0x00FF00, 0xFF00FF, 0xFFFFFF)
; ===============================================================================================================================
Func _CircularProgress($iPercent, $iSize = 300, $iThickness = 30, $TextCol = 0xFF404040, $StartCol = 0xFFFFFF00, $EndCol = 0xFFFF0000)
    Local $hBmp, $hBmpGraphics, $inSize, $iRadius, $iX, $iY

    $inSize = $iSize
    $iRadius = ($inSize - 4) / 2
    $iX = $inSize / 2
    $iY = $iX

    ; Create an off-screen bitmap for double-buffering
    $hBmp = _GDIPlus_BitmapCreateFromScan0($inSize, $inSize)
    $hBmpGraphics = _GDIPlus_ImageGetGraphicsContext($hBmp)
    _GDIPlus_GraphicsSetSmoothingMode($hBmpGraphics, 4)
    _GDIPlus_GraphicsSetTextRenderingHint($hBmpGraphics, 4)

    ; Draw progress arc as pie
    Local $angle = ($iPercent / 100) * 360
    Local $hBrushProg = _GDIPlus_LineBrushCreate($iX - $iRadius, $iY, $iX + $iRadius, $iY, $EndCol, $StartCol, 1)
    Local $hPen = _GDIPlus_PenCreate2($hBrushProg, $iThickness)
    _GDIPlus_GraphicsDrawArc($hBmpGraphics, $iX - $iRadius + $iThickness / 2, $iY - $iRadius + $iThickness / 2, $iRadius * 2 - $iThickness, $iRadius * 2 - $iThickness, -90, $angle, $hPen)
    _GDIPlus_BrushDispose($hBrushProg)
    _GDIPlus_PenDispose($hPen)

    Local $hFontFamily = _GDIPlus_FontFamilyCreate("Times New Roman")
    Local $iFontSize = $iRadius * 0.3
    Local $hFont = _GDIPlus_FontCreate($hFontFamily, $iFontSize, 1)
    Local $hFormat = _GDIPlus_StringFormatCreate()
    _GDIPlus_StringFormatSetAlign($hFormat, 2)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 2)
    Local $hBrushText = _GDIPlus_BrushCreateSolid($TextCol)

    ; Draw percentage text
    Local $rect = _GDIPlus_RectFCreate(($inSize - ($iFontSize * 4)) / 2, ($inSize - ($iFontSize * 2)) / 2, $iFontSize * 4, $iFontSize * 2)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, $rect, $hFormat, $hBrushText)

    _GDIPlus_FontFamilyDispose($hFontFamily)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrushText)


    Local $hHBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
    _WinAPI_BitmapDisplayTransparentInGUI($hHBmp, $hGUI)
    _GDIPlus_BitmapDispose($hBmp)

    _GDIPlus_GraphicsDispose($hBmpGraphics)
EndFunc   ;==>_CircularProgress

Func _WinAPI_BitmapDisplayTransparentInGUI(ByRef $hHBitmap, ByRef $hGUI, $iOpacity = 0xFF, $iFlags = $ULW_ALPHA, $bReleaseGDI = True, $tDest = Null, $iBGR = 0)
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBitmap, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, $tDest, $tSize, $hMemDC, $tSource, $iBGR, $tBlend, $iFlags)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBitmap)
    Return True
EndFunc   ;==>_WinAPI_BitmapDisplayTransparentInGUI

 

If you have static variable, such as bitmap, brushes, etc., you can put out these parts off the _CircularProgress() function.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)

I see that the 'trick' was the change of approach from _GDIPlus_GraphicsFillPie  to _GDIPlus_GraphicsDrawArc,
and the truth is that I tried it all afternoon yesterday, with _GDIPlus_GraphicsDrawArc, I didn't succeed (I didn't know)

:thumbsup: Thank you very much for the intervention,
and the enlightenment

 

Update to Version: 0.6  in the first post

Edited by ioa747

I know that I know nothing

Posted (edited)

How can we make a black inner background circle to draw the colored progressbar over it

just like this image : (this image from old script)

can we add to the new script this black one to draw colored ring over it

 

testers.JPG

Edited by Davidyese
Posted (edited)

Update to Version: 0.7 with 

$iBgTrans     - [optional] The transparency of background, a number in the range 0 - 255. (Default is 0)

 

; https://www.autoitscript.com/forum/topic/213118-_circularprogress/
;----------------------------------------------------------------------------------------
; Title...........: _CircularProgress.au3
; Description.....: Creates a customizable circular progress bar using GDI+ graphics.
; AutoIt Version..: 3.3.16.1   Author: ioa747  Script Version: 0.7
; Note............: Testet in Win10 22H2       Date:10/09/2025
; Based on post ..: https://www.autoitscript.com/forum/topic/213118-_circularprogress/#findComment-1545797
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <WinAPIConstants.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>
#include <Array.au3>


_Example() ; as demo


Func _Example()
    Local $aList[2000]
    Local $iCnt = UBound($aList)
    ConsoleWrite("$iCnt=" & $iCnt & @CRLF)

    Local $nProgress
    _CircularProgress($nProgress, 300, -1, -1, 23, 0xFFDCDCDC, 0xFFFFFF00, 0xFFFF0000, 100)

    For $i = 1 To UBound($aList)
        $nProgress = Int($i / $iCnt * 100)
        _CircularProgress($nProgress)
    Next

    Sleep(500) ; Give it some time to show the 100%.
    _CircularProgress(101) ; Clean up the progress bar window
EndFunc   ;==>_Example



; #FUNCTION# ====================================================================================================================
; Name...........: _CircularProgress
; Description....: Creates a customizable circular progress bar using GDI+ graphics.
; Syntax.........: _CircularProgress($iPercent [, $iSize = 300 [, $iLeft = -1 [, $iTop = -1 [, $iThickness = 23 [, $TextCol = 0xFFBFBFBF [, $StartCol = 0xFFFFFF00, $EndCol = 0xFFFF0000 [, $iBgTrans = 0]]]]]]])
; Parameters.....: $iPercent     - The percentage complete for the progress bar (0 to 100).
;                  $iSize        - [optional] width and height of the circular progress bar. (Default is 300)
;                  $iLeft        - [optional] X-coordinate of the top-left corner. (Default is -1 for center)
;                  $iTop         - [optional] Y-coordinate of the top-left corner. (Default is -1 for center)
;                  $iThickness   - [optional] Thickness of the progress arc. (Default is 23)
;                  $TextCol      - [optional] Color of the text within the progress bar. (Default is Silver)
;                  $StartCol     - [optional] Start color of the progress arc gradient. (Default is Yellow)
;                  $EndCol       - [optional] End color of the progress arc gradient. (Default is Red)
;                  $iBgTrans     - [optional] The transparency of background, a number in the range 0 - 255. (Default is 0)
; Return values .: Success: create the progress bar GUI
; Author ........: ioa747 , Thank to UEZ
; Modified ......: 10/09/2025 - v0.7
; Remarks .......: Cleanup is handled automatically by passing an $iPercent > 100.
;                  Avoid using 0x050505 Color for $TextCol, $StartCol, or $EndCol, as it is used as a transparency color for the background.
; Related .......: _GDIPlus_Startup, _GDIPlus_GraphicsCreateFromHWND, etc.
; Link ..........: https://www.autoitscript.com/forum/topic/213113-simple-circular-progressbar-with-smooth-edges-gradient-color/#findComment-1545755
; Example .......: _CircularProgress(50, 300, -1, -1, 23, 0xFFBFBFBF, 0xFFFFFF00, 0xFFFF0000)
; ===============================================================================================================================
Func _CircularProgress($iPercent, $iSize = 300, $iLeft = -1, $iTop = -1, $iThickness = 23, $TextCol = 0xFFDCDCDC, $StartCol = 0xFFFFFF00, $EndCol = 0xFFFF0000, $iBgTrans = 0)
    Local Static $hGUI, $inSize, $inThickness, $iRadius, $iX, $iY, $BackCol, $bInit = False

    If Not $bInit Then
        _GDIPlus_Startup()
        $BackCol = "0x" & Hex($iBgTrans, 2) & "000000"
        $inThickness = $iThickness
        $inSize = $iSize
        $iRadius = ($inSize - 4) / 2
        $iX = $inSize / 2
        $iY = $iX
        $hGUI = GUICreate("RingProgressBar", $inSize, $inSize, $iLeft, $iTop, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
        GUISetState(@SW_SHOWNOACTIVATE)
        $bInit = True
    EndIf

    If $iPercent > 100 Then
        _GDIPlus_Shutdown()
        GUIDelete($hGUI)
        $bInit = False
        Return
    EndIf

    ; Create an off-screen bitmap for double-buffering
    Local $hBmp = _GDIPlus_BitmapCreateFromScan0($inSize, $inSize)
    Local $hBmpGraphics = _GDIPlus_ImageGetGraphicsContext($hBmp)
    _GDIPlus_GraphicsSetSmoothingMode($hBmpGraphics, 4)
    _GDIPlus_GraphicsSetTextRenderingHint($hBmpGraphics, 4)

    ; Draw arc backround
    Local $hbackround = _GDIPlus_BrushCreateSolid($BackCol)
    _GDIPlus_GraphicsFillEllipse($hBmpGraphics, $iX - $iRadius + 1, $iY - $iRadius + 1, ($iRadius * 2) - 2, ($iRadius * 2) - 2, $hbackround)
    _GDIPlus_BrushDispose($hbackround)

    ; Draw progress arc as pie
    Local $angle = ($iPercent / 100) * 360
    Local $hBrushProg = _GDIPlus_LineBrushCreate($iX - $iRadius, $iY, $iX + $iRadius, $iY, $EndCol, $StartCol, 1)
    Local $hPen = _GDIPlus_PenCreate2($hBrushProg, $inThickness)
    _GDIPlus_GraphicsDrawArc($hBmpGraphics, $iX - $iRadius + $inThickness / 2, $iY - $iRadius + $inThickness / 2, _
            $iRadius * 2 - $inThickness, $iRadius * 2 - $inThickness, -90, $angle, $hPen)

    _GDIPlus_BrushDispose($hBrushProg)
    _GDIPlus_PenDispose($hPen)

    ; Draw percentage text
    Local $hFontFamily = _GDIPlus_FontFamilyCreate("Times New Roman")
    Local $iFontSize = $iRadius * 0.23
    Local $hFont = _GDIPlus_FontCreate($hFontFamily, $iFontSize, 1)
    Local $hFormat = _GDIPlus_StringFormatCreate()
    Local $hBrushText = _GDIPlus_BrushCreateSolid($TextCol)
    _GDIPlus_StringFormatSetAlign($hFormat, 2)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 2)

    ; black outline
    Local $hBrushOutline = _GDIPlus_BrushCreateSolid(0xFF000000)
    Local $rect = _GDIPlus_RectFCreate(($inSize - ($iFontSize * 4)) / 2, ($inSize - ($iFontSize * 2)) / 2, $iFontSize * 4, $iFontSize * 2)
    Local $iOffset = 1 ; Offset for the outline, Adjust this value for thicker/thinner outline

    ; Draw outline text by offsetting the position
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X - $iOffset, $rect.Y, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X + $iOffset, $rect.Y, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X, $rect.Y - $iOffset, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, _GDIPlus_RectFCreate($rect.X, $rect.Y + $iOffset, $rect.Width, $rect.Height), $hFormat, $hBrushOutline)

    ; Draw the main text on top
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, $rect, $hFormat, $hBrushText)

    _GDIPlus_BrushDispose($hBrushOutline)
    _GDIPlus_FontFamilyDispose($hFontFamily)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrushText)

    ; Create HBITMAP and display
    Local $hHBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
    ;_WinAPI_BitmapDisplayTransparentInGUI($hHBmp, $hGUI)
    Local $iOpacity = 0xFF, $iFlags = $ULW_ALPHA, $bReleaseGDI = True, $tDest = Null, $iBGR = 0
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBmp, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBmp)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, $tDest, $tSize, $hMemDC, $tSource, $iBGR, $tBlend, $iFlags)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBmp)
    ;Return True

    _GDIPlus_BitmapDispose($hBmp)
    _GDIPlus_GraphicsDispose($hBmpGraphics)
EndFunc   ;==>_CircularProgress

 

Edited by ioa747
correction to Hex($iBgTrans, 2)

I know that I know nothing

Posted (edited)
25 minutes ago, ioa747 said:

 

; https://www.autoitscript.com/forum/topic/213118-_circularprogress/
;----------------------------------------------------------------------------------------
; Title...........: _CircularProgress.au3
; Description.....: Creates a customizable circular progress bar using GDI+ graphics.
; AutoIt Version..: 3.3.16.1   Author: ioa747  Script Version: 0.4
; Note............: Testet in Win10 22H2       Date:07/09/2025
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <Constants.au3>
#include <WindowsConstants.au3>
#include <Array.au3>


_Example() ; as demo

;~ _Example2() ; as demo


Func _Example()
    Local $aList[2000]
    Local $iCnt = UBound($aList)
    ConsoleWrite("$iCnt=" & $iCnt & @CRLF)
    Local $nProgress

    For $i = 1 To UBound($aList)
        $nProgress = Int($i / $iCnt * 100)
        ConsoleWrite($i & ")  $nProgress=" & $nProgress & @CRLF)
        _CircularProgress($nProgress)
    Next

    Sleep(200) ; Give it some time to see the 100%.
    _CircularProgress(101) ; Clean up the progress bar window
EndFunc   ;==>_Example

Func _Example2()
    Local $aList[2000]
    Local $iCnt = UBound($aList)
    Local $nProgress
    _CircularProgress(0, @DesktopWidth * 0.8, @DesktopHeight * 0.4, 200, 20)
    For $i = 1 To UBound($aList)
        $nProgress = Int($i / $iCnt * 100)
        _CircularProgress($nProgress)
    Next

    For $i = 1 To 3
        _CircularProgress($nProgress, -1, -1, -1, -1, 0xFFFFFF, 0x4CFF00, 0xF6FF00)
        Sleep(500)
        _CircularProgress($nProgress, -1, -1, -1, -1, 0xFFFFFF, 0xF6FF00, 0x4CFF00)
        Sleep(500)
    Next

    _CircularProgress(101) ; Clean up the progress bar window
EndFunc   ;==>_Example

; #FUNCTION# ====================================================================================================================
; Name...........: _CircularProgress
; Description....: Creates a customizable circular progress bar using GDI+ graphics.
; Syntax.........: _CircularProgress($iPercent [, $iLeft = -1 [, $iTop = -1 [, $iSize = 300 [, $iThickness = 30 [, $TextCol = 0xFFFFFF [, $StartCol = 0xFF0000, $EndCol = 0xFFFF00]]]]]])
; Parameters.....: $iPercent     - The percentage complete for the progress bar (0 to 100).
;                  $iLeft        - [optional] X-coordinate of the top-left corner. (Default is -1 for center)
;                  $iTop         - [optional] Y-coordinate of the top-left corner. (Default is -1 for center)
;                  $iSize        - [optional] width and height of the circular progress bar. (Default is 300)
;                  $iThickness   - [optional] Thickness of the progress arc. (Default is 30)
;                  $TextCol      - [optional] Color of the text within the progress bar. (Default is White)
;                  $StartCol     - [optional] Start color of the progress arc gradient. (Default is Yellow)
;                  $EndCol       - [optional] End color of the progress arc gradient. (Default is Red)
; Return values .: Success: create the progress bar GUI
; Author ........: ioa747
; Modified ......: 07/09/2025 - v0.4
; Remarks .......: Cleanup is handled automatically by passing an $iPercent > 100.
;                  Avoid using 0x050505 Color for $TextCol, $StartCol, or $EndCol, as it is used as a transparency color for the background.
; Related .......: _GDIPlus_Startup, _GDIPlus_GraphicsCreateFromHWND, etc.
; Link ..........: https://www.autoitscript.com/forum/topic/213113-simple-circular-progressbar-with-smooth-edges-gradient-color/#findComment-1545755
; Example .......: _CircularProgress(50, -1, -1, 300, 20, 0x00FF00, 0xFF00FF, 0xFFFFFF)
; ===============================================================================================================================
Func _CircularProgress($iPercent, $iLeft = -1, $iTop = -1, $iSize = 300, $iThickness = 30, $TextCol = 0xFFFFFF, $StartCol = 0xFFFF00, $EndCol = 0xFF0000)
    Local Static $hGUI, $hGraphics, $hBmp, $hBmpGraphics, $inSize, $iRadius, $inThickness, $iX, $iY, $bInit = False

    ; initialize RingProgressBar (if not)
    If Not $bInit Then
        _GDIPlus_Startup()
        $inThickness = $iThickness
        $inSize = $iSize
        $iRadius = ($inSize - 4) / 2
        $iX = $inSize / 2
        $iY = $iX
        ; transparent layered window
        $hGUI = GUICreate("RingProgressBar", $inSize, $inSize, $iLeft, $iTop, $WS_POPUP, $WS_EX_LAYERED)
        GUISetBkColor(0x050505) ; 0x050505
        _WinAPI_SetLayeredWindowAttributes($hGUI, 0x050505)
        GUISetState(@SW_SHOWNOACTIVATE)

        ; Create a graphics object linked to the GUI
        $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)

        ; Create an off-screen bitmap for double-buffering
        $hBmp = _GDIPlus_BitmapCreateFromScan0($inSize, $inSize)
        $hBmpGraphics = _GDIPlus_ImageGetGraphicsContext($hBmp)
        $bInit = True
    EndIf

    ; Clean up the RingProgressBar (if $iPercent > 100)
    If $iPercent > 100 Then
        ; Cleanup
        _GDIPlus_GraphicsDispose($hBmpGraphics)
        _GDIPlus_BitmapDispose($hBmp)
        _GDIPlus_GraphicsDispose($hGraphics)
        _GDIPlus_Shutdown()
        GUIDelete($hGUI)
        $bInit = False
        Return
    EndIf

    ; Colors from RGB to ARGB
    $TextCol = "0xFF" & StringTrimLeft(Hex($TextCol), 2)
    $StartCol = "0xFF" & StringTrimLeft(Hex($StartCol), 2)
    $EndCol = "0xFF" & StringTrimLeft(Hex($EndCol), 2)

    _GDIPlus_GraphicsClear($hBmpGraphics, 0x00050505)
    _GDIPlus_GraphicsSetSmoothingMode($hBmpGraphics, 2)
    _GDIPlus_GraphicsSetTextRenderingHint($hBmpGraphics, 5)

    ; Draw full ring background
    Local $hBrushBG = _GDIPlus_BrushCreateSolid(0xFF000000)
    _GDIPlus_GraphicsFillEllipse($hBmpGraphics, $iX - $iRadius, $iY - $iRadius, $iRadius * 2, $iRadius * 2, $hBrushBG)
    _GDIPlus_BrushDispose($hBrushBG)

    ; Draw progress arc as pie
    Local $angle = ($iPercent / 100) * 360
    Local $hBrushProg = _GDIPlus_LineBrushCreate($iX - $iRadius, $iY, $iX + $iRadius, $iY, $EndCol, $StartCol, 1)
    _GDIPlus_GraphicsFillPie($hBmpGraphics, $iX - $iRadius, $iY - $iRadius, $iRadius * 2, $iRadius * 2, -90, $angle, $hBrushProg)
    _GDIPlus_BrushDispose($hBrushProg)

    ; Draw inner circle
    Local $innerR = $iRadius - $inThickness
    Local $hBrushWhite = _GDIPlus_BrushCreateSolid(0xFF000000)
    _GDIPlus_GraphicsFillEllipse($hBmpGraphics, $iX - $innerR, $iY - $innerR, $innerR * 2, $innerR * 2, $hBrushWhite)
    _GDIPlus_BrushDispose($hBrushWhite)

    Local $hFontFamily = _GDIPlus_FontFamilyCreate("Times New Roman")
    Local $iFontSize = $iRadius * 0.3
    Local $hFont = _GDIPlus_FontCreate($hFontFamily, $iFontSize, 1)
    Local $hFormat = _GDIPlus_StringFormatCreate()
    _GDIPlus_StringFormatSetAlign($hFormat, 2)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 2)
    Local $hBrushText = _GDIPlus_BrushCreateSolid($TextCol)

    ; Draw percentage text
    Local $rect = _GDIPlus_RectFCreate(($inSize - ($iFontSize * 4)) / 2, ($inSize - ($iFontSize * 2)) / 2, $iFontSize * 4, $iFontSize * 2)
    _GDIPlus_GraphicsDrawStringEx($hBmpGraphics, $iPercent & "%", $hFont, $rect, $hFormat, $hBrushText)

    _GDIPlus_FontFamilyDispose($hFontFamily)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrushText)

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmp, 0, 0)
EndFunc   ;==>_CircularProgress

 

This not good my dear

I'm asking to edit UEZ script or your Final 0.6 script and modify to show inner black ring to draw colored ring over it

don't mention again the old one because the colored ring is ugly and hizitated

Edited by Davidyese

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
×
×
  • Create New...