Jump to content

Recommended Posts

Posted

Example of customizable GDI+ circular slider 

 

;======== SciTEHopper TimeStamp : Friday 13 November 2026 (16:42:00) ========
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Run_Tidy=y

#Region    ;************ Includes ************
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#EndRegion ;************ Includes ************

Opt('MustDeclareVars', 1)

#Region ------ Global Variables ------------------------------
Global Const $iGuiBkColor = 0x1E1E2E        ; AutoIt background color (RGB)
Global Const $fRatioRadius = 0.314          ; ~31.4% of the window
Global Const $fRatioTrackWidth = 0.040      ; ~4.0% of the window
Global Const $fRatioThumbRadius = 0.046     ; ~4.6% of the window
Global Const $iThumbInnerRatio = 0.5        ; Size of the central point (0.0 to 1.0)
Global Const $fRatioHitboxMargin = 0.034    ; Click margin around the track
Global Const $fRatioFontSize = 0.068        ; Proportional font size
Global Const $iZeroAngle = 270              ; Start angle 0% (0=Right, 90=Down, 180=Left, 270=Up)
Global Const $iInitialPercent = 35          ; Starting value (0 to 100)
Global Const $iMinValue = 0                 ; Minimum value displayed
Global Const $iMaxValue = 100               ; Maximum value displayed
Global Const $iStepSnap = 0                 ; No magnetization (e.g. 5 to jump 5%, 0 = fluid)
Global Const $ColorBackground = 0xFF1E1E2E  ; GDI+ Canvas Background
Global Const $ColorTrack = 0xFF313244       ; Inactive Circular Track
Global Const $ColorProgress = 0xFF89B4FA    ; Active Progress Arc
Global Const $ColorThumbOuter = 0xFFFFFFFF  ; Outer circle of the cursor
Global Const $ColorThumbInner = 0xFF89B4FA  ; Cursor Center Point
Global Const $ColorText = 0xFFCDD6F4        ; Center text color
Global Const $bShowText = True              ; True = show value in center, False = hide
Global Const $sFontName = 'Segoe UI'
Global Const $iFontStyle = 1                ; 0=Normal, 1=Bold, 2=Italic, 3=BoldItalic
Global Const $sValuePrefix = ''             ; Prefix before number (e.g. '$')
Global Const $sValueSuffix = '%'            ; Suffix after the number (e.g. '%', ' px', '°')
Global Const $fPi = ACos(-1)
Global $sWindowTitle = 'Custom Circular Slider'
Global $iGuiWidth = 350
Global $iGuiHeight = 350
Global $iBaseSize, $iCenterX, $iCenterY, $iRadius, $iTrackWidth, $iThumbRadius, $iHitboxMargin
Global $iFontSize, $iTextBoxWidth, $iTextBoxHeight
Global $fCurrentPercent = $iInitialPercent
Global $fCurrentAngle = Mod($iZeroAngle + (($fCurrentPercent / 100) * 360), 360)
Global $bDragging = False
Global $bNeedResize = False
Global $iPendingW = $iGuiWidth
Global $iPendingH = $iGuiHeight
Global $hGui, $hGraphics, $hBitmap, $hBackbuffer, $hPenTrack, $hPenProgress
Global $hBrushThumbOuter, $hBrushThumbInner, $hBrushText, $hFormat, $hFamily, $hFont
#EndRegion ------ Global Variables ------------------------------

#Region ------ Init ------------------------------
_GDIPlus_Startup()
$hGui = GUICreate($sWindowTitle, $iGuiWidth, $iGuiHeight, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX, $WS_MAXIMIZEBOX))
GUISetBkColor($iGuiBkColor, $hGui)
$hBrushThumbOuter = _GDIPlus_BrushCreateSolid($ColorThumbOuter)
$hBrushThumbInner = _GDIPlus_BrushCreateSolid($ColorThumbInner)
$hBrushText = _GDIPlus_BrushCreateSolid($ColorText)
$hFormat = _GDIPlus_StringFormatCreate()
_GDIPlus_StringFormatSetAlign($hFormat, 1)
_GDIPlus_StringFormatSetLineAlign($hFormat, 1)
$hFamily = _GDIPlus_FontFamilyCreate($sFontName)
_UpdateLayout($iGuiWidth, $iGuiHeight)
GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
GUIRegisterMsg($WM_ERASEBKGND, '_WM_ERASEBKGND')
GUIRegisterMsg($WM_PAINT, '_WM_PAINT')
GUISetState()
_DrawSlider()
#EndRegion ------ Init ------------------------------

#Region ------ Main Loop ------------------------------
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _Cleanup()
            Exit
    EndSwitch
    If $bNeedResize Then
        $bNeedResize = False
        _UpdateLayout($iPendingW, $iPendingH)
        _DrawSlider()
    EndIf
    Local $aCursor = GUIGetCursorInfo($hGui)
    If IsArray($aCursor) Then
        Local $iMouseX = $aCursor[0]
        Local $iMouseY = $aCursor[1]
        Local $bMouseDown = ($aCursor[2] = 1)
        If $bMouseDown Then
            If Not $bDragging Then
                Local $fDist = Sqrt(($iMouseX - $iCenterX) ^ 2 + ($iMouseY - $iCenterY) ^ 2)
                If Abs($fDist - $iRadius) <= ($iThumbRadius + $iHitboxMargin) Then
                    $bDragging = True
                EndIf
            EndIf
            If $bDragging Then
                GUISetCursor(0, 1, $hGui)
                Local $fRad = _ATan2($iMouseY - $iCenterY, $iMouseX - $iCenterX)
                Local $fRawAngle = Mod(($fRad * 180 / $fPi) + 360, 360)
                Local $fSweep = Mod(($fRawAngle - $iZeroAngle + 360), 360)
                Local $fPct = ($fSweep / 360) * 100
                If $iStepSnap > 0 Then
                    $fPct = Round($fPct / $iStepSnap) * $iStepSnap
                    If $fPct >= 100 Then $fPct = 0
                EndIf
                $fCurrentPercent = $fPct
                $fCurrentAngle = Mod($iZeroAngle + (($fCurrentPercent / 100) * 360), 360)
                _DrawSlider()
            EndIf
        Else
            GUISetCursor(2, 1, $hGui)
            $bDragging = False
        EndIf
    EndIf
    Sleep(30)
WEnd
#EndRegion ------ Main Loop ------------------------------

Func _ATan2($y, $x)
    If $x > 0 Then Return ATan($y / $x)
    If $x < 0 And $y >= 0 Then Return ATan($y / $x) + $fPi
    If $x < 0 And $y < 0 Then Return ATan($y / $x) - $fPi
    If $x = 0 And $y > 0 Then Return $fPi / 2
    If $x = 0 And $y < 0 Then Return -$fPi / 2
    Return 0
EndFunc   ;==>_ATan2

Func _Cleanup()
    GUIRegisterMsg($WM_SIZE, '')
    GUIRegisterMsg($WM_ERASEBKGND, '')
    GUIRegisterMsg($WM_PAINT, '')
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrushText)
    _GDIPlus_BrushDispose($hBrushThumbInner)
    _GDIPlus_BrushDispose($hBrushThumbOuter)
    _GDIPlus_PenDispose($hPenProgress)
    _GDIPlus_PenDispose($hPenTrack)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
EndFunc   ;==>_Cleanup

Func _DrawSlider()
    _GDIPlus_GraphicsClear($hBackbuffer, $ColorBackground)
    _GDIPlus_GraphicsDrawEllipse($hBackbuffer, $iCenterX - $iRadius, $iCenterY - $iRadius, $iRadius * 2, $iRadius * 2, $hPenTrack)
    Local $fSweepAngle = ($fCurrentPercent / 100) * 360
    If $fSweepAngle > 0 Then _
            _GDIPlus_GraphicsDrawArc($hBackbuffer, $iCenterX - $iRadius, $iCenterY - $iRadius, $iRadius * 2, $iRadius * 2, $iZeroAngle, $fSweepAngle, $hPenProgress)
    Local $fRad = $fCurrentAngle * $fPi / 180
    Local $fThumbX = $iCenterX + ($iRadius * Cos($fRad))
    Local $fThumbY = $iCenterY + ($iRadius * Sin($fRad))
    ;
    _GDIPlus_GraphicsFillEllipse($hBackbuffer, $fThumbX - $iThumbRadius, $fThumbY - $iThumbRadius, $iThumbRadius * 2, $iThumbRadius * 2, $hBrushThumbOuter)
    If $iThumbInnerRatio > 0 Then
        Local $fInnerRadius = $iThumbRadius * $iThumbInnerRatio
        _GDIPlus_GraphicsFillEllipse($hBackbuffer, $fThumbX - $fInnerRadius, $fThumbY - $fInnerRadius, $fInnerRadius * 2, $fInnerRadius * 2, $hBrushThumbInner)
    EndIf
    If $bShowText Then
        Local $iMappedVal = Round($iMinValue + (($fCurrentPercent / 100) * ($iMaxValue - $iMinValue)))
        Local $sDisplayText = $sValuePrefix & $iMappedVal & $sValueSuffix
        Local $tRect = _GDIPlus_RectFCreate($iCenterX - ($iTextBoxWidth / 2), $iCenterY - ($iTextBoxHeight / 2), $iTextBoxWidth, $iTextBoxHeight)
        _GDIPlus_GraphicsDrawStringEx($hBackbuffer, $sDisplayText, $hFont, $tRect, $hFormat, $hBrushText)
    EndIf
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
EndFunc   ;==>_DrawSlider

Func _UpdateLayout($iW, $iH)
    $iGuiWidth = $iW
    $iGuiHeight = $iH
    $iBaseSize = ($iGuiWidth < $iGuiHeight) ? $iGuiWidth : $iGuiHeight
    $iCenterX = $iGuiWidth / 2
    $iCenterY = $iGuiHeight / 2
    $iRadius = $iBaseSize * $fRatioRadius
    $iTrackWidth = ($iBaseSize * $fRatioTrackWidth < 1) ? 1 : ($iBaseSize * $fRatioTrackWidth)
    $iThumbRadius = ($iBaseSize * $fRatioThumbRadius < 2) ? 2 : ($iBaseSize * $fRatioThumbRadius)
    $iHitboxMargin = $iBaseSize * $fRatioHitboxMargin
    $iFontSize = ($iBaseSize * $fRatioFontSize < 6) ? 6 : Round($iBaseSize * $fRatioFontSize)
    $iTextBoxWidth = $iRadius * 1.6
    $iTextBoxHeight = $iRadius * 0.8
    If $hFont Then _GDIPlus_FontDispose($hFont)
    If $hPenTrack Then _GDIPlus_PenDispose($hPenTrack)
    If $hPenProgress Then _GDIPlus_PenDispose($hPenProgress)
    If $hBackbuffer Then _GDIPlus_GraphicsDispose($hBackbuffer)
    If $hBitmap Then _GDIPlus_BitmapDispose($hBitmap)
    If $hGraphics Then _GDIPlus_GraphicsDispose($hGraphics)
    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iGuiWidth, $iGuiHeight, $hGraphics)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    $hPenTrack = _GDIPlus_PenCreate($ColorTrack, $iTrackWidth)
    $hPenProgress = _GDIPlus_PenCreate($ColorProgress, $iTrackWidth)
    $hFont = _GDIPlus_FontCreate($hFamily, $iFontSize, $iFontStyle)
EndFunc   ;==>_UpdateLayout

Func _WM_ERASEBKGND($hWnd, $iMsg, $wParam, $lParam)
    If $hWnd = $hGui Then Return 1
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_ERASEBKGND

Func _WM_PAINT($hWnd, $iMsg, $wParam, $lParam)
    If $hWnd = $hGui And $hGraphics And $hBitmap Then _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_PAINT

Func _WM_SIZE($hWnd, $iMsg, $wParam, $lParam)
    If $hWnd = $hGui Then
        Local $iNewW = BitAND($lParam, 0xFFFF)
        Local $iNewH = BitShift($lParam, 16)
        If $iNewW > 10 And $iNewH > 10 Then
            $iPendingW = $iNewW
            $iPendingH = $iNewH
            $bNeedResize = True
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_SIZE

 

AutoIt 3.3.18.0 X86 - SciTE 5.6.7.0 - WIN 11 24H2 X64 - Other Examples Scripts

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...