ioa747 Posted yesterday at 08:26 AM Posted yesterday at 08:26 AM (edited) I created _CircularProgress , with the idea of calling it as a single function. expandcollapse popup; 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 1 hour ago by ioa747 update to Version: 0.6 Parsix, mutleey and Davidyese 3 I know that I know nothing
UEZ Posted yesterday at 02:44 PM Posted yesterday at 02:44 PM (edited) It looks ugly on my Notebook: 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 yesterday at 02:46 PM by UEZ Davidyese, Parsix and ioa747 1 2 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!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
ioa747 Posted 6 hours ago Author Posted 6 hours ago (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 6 hours ago by ioa747 I know that I know nothing
Solution UEZ Posted 5 hours ago Solution Posted 5 hours ago To use _WinAPI_BitmapDisplayTransparentInGUI() you must create a complete frame within the function. Example: expandcollapse popup; 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. ioa747 1 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!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
ioa747 Posted 1 hour ago Author Posted 1 hour ago (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) Thank you very much for the intervention, and the enlightenment Update to Version: 0.6 in the first post Edited 1 hour ago by ioa747 I know that I know nothing
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now