Jump to content

3D Pie Chart


 Share

Recommended Posts

  • 4 weeks later...

Can someone help me resolve the following error?

Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

Local $iStart = Mod($Angles[^ ERROR

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUISlider.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <Date.au3>

; Let's be strict here
Opt("MustDeclareVars", 1)

; Controls the size of the pie and also the depth
Global Const $PIE_DIAMETER = 400
Global Const $PIE_MARGIN = $PIE_DIAMETER * 0.025
Global Const $PIE_DEPTH = $PIE_DIAMETER * 0.2
Global Const $PIE_AREA = $PIE_DIAMETER + 2 * $PIE_MARGIN

; Random data for values and colours
Global Const $NUM_VALUES = 5
Global $aChartValue[$NUM_VALUES]
Global $aChartColour[$NUM_VALUES]


Global $aChartColour[5] = ["0xFF8204", "0x0000FF", "0xFF0000", "0x008000", "0xEEF3F6"]

$aChartValue[0] = 0
$aChartValue[1] = 0
$aChartValue[2] = 0
$aChartValue[3] = 0
$aChartValue[4] = 100

; The value of PI
Global Const $PI = ATan(1) * 4

; Start GDI+
_GDIPlus_Startup()

; Create the brushes and pens
Global $ahBrush[$NUM_VALUES][2], $ahPen[$NUM_VALUES]
For $i = 0 To $NUM_VALUES - 1
    $ahBrush[$i][0] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, $aChartColour[$i]))
    $ahBrush[$i][1] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, _GetDarkerColour($aChartColour[$i])))
    $ahPen[$i] = _GDIPlus_PenCreate(BitOR(0xff000000, _GetDarkerColour(_GetDarkerColour($aChartColour[$i]))))
Next

; Create the GUI with sliders to control the aspect, rotation, style and hole size (for donuts)
Global $hWnd = GUICreate("Pie Chart", $PIE_AREA, $PIE_AREA + 100, Default, Default)
Global $hSlideAspect = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 10, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideAspect, 10, 100)
_GUICtrlSlider_SetPos($hSlideAspect, 50)
Global $hSlideRotation = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 40, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideRotation, 0, 360)
Global $cStyle = GUICtrlCreateCheckbox("Donut", $PIE_MARGIN, $PIE_AREA + 70, $PIE_DIAMETER / 2 - $PIE_MARGIN, 20)
Global $hStyle = GUICtrlGetHandle($cStyle)
Global $hHoleSize = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN + $PIE_DIAMETER / 2, $PIE_AREA + 70, $PIE_DIAMETER / 2, 20)
_GUICtrlSlider_SetRange($hHoleSize, 2, $PIE_DIAMETER - 4 * $PIE_MARGIN)
_GUICtrlSlider_SetPos($hHoleSize, $PIE_DIAMETER / 2)
GUISetState()

; Set up GDI+
Global $hDC = _WinAPI_GetDC($hWnd)
Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($PIE_AREA, $PIE_AREA, $hGraphics)
Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)

; Draw the initial pie chart
_DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
        _GUICtrlSlider_GetPos($hSlideRotation), _
        (GUICtrlRead($cStyle) = $GUI_CHECKED), _
        _GUICtrlSlider_GetPos($hHoleSize))

; The sliders will send WM_NOTIFY messages
GUIRegisterMsg($WM_NOTIFY, "_OnNotify")

; Wait until the user quits
While GUIGetMsg() <> $GUI_EVENT_CLOSE
    Sleep(10)
WEnd

; Release the resources
For $i = 0 To UBound($aChartColour) - 1
    _GDIPlus_PenDispose($ahPen[$i])
    _GDIPlus_BrushDispose($ahBrush[$i][0])
    _GDIPlus_BrushDispose($ahBrush[$i][1])
Next
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_ReleaseDC($hWnd, $hDC)

; Shut down GDI+
_GDIPlus_Shutdown()

; Done
Exit

; Get a darker version of a colour by extracting the RGB components
Func _GetDarkerColour($Colour)
    Local $Red, $Green, $Blue
    $Red = (BitAND($Colour, 0xff0000) / 0x10000) - 40
    $Green = (BitAND($Colour, 0x00ff00) / 0x100) - 40
    $Blue = (BitAND($Colour, 0x0000ff)) - 40
    If $Red < 0 Then $Red = 0
    If $Green < 0 Then $Green = 0
    If $Blue < 0 Then $Blue = 0
    Return ($Red * 0x10000) + ($Green * 0x100) + $Blue
EndFunc ;==>_GetDarkerColour

; Draw the pie chart
Func _DrawPie($Percentage, $Aspect, $rotation, $style = 0, $holesize = 100)
    If $style <> 0 Then $Aspect = 1
    Local $nCount, $nTotal = 0, $angleStart, $angleSweep, $X, $Y
    Local $pieLeft = $PIE_MARGIN, $pieTop = $PIE_AREA / 2 - ($PIE_DIAMETER / 2) * $Aspect
    Local $pieWidth = $PIE_DIAMETER, $pieHeight = $PIE_DIAMETER * $Aspect, $hPath

; Total up the values
    For $nCount = 0 To UBound($Percentage) - 1
        $nTotal += $Percentage[$nCount]
    Next

; Set the fractional values
    For $nCount = 0 To UBound($Percentage) - 1
        $Percentage[$nCount] /= $nTotal
    Next

; Make sure we don't over-rotate
    $rotation = Mod($rotation, 360)

; Clear the graphics buffer
    _GDIPlus_GraphicsClear($hBuffer, 0xffc0c0c0)

; Set the initial angles based on the fractional values
    Local $Angles[UBound($Percentage) + 1]
    For $nCount = 0 To UBound($Percentage)
        If $nCount = 0 Then
            $Angles[$nCount] = $rotation
        Else
            $Angles[$nCount] = $Angles[$nCount - 1] + ($Percentage[$nCount - 1] * 360)
        EndIf
    Next

    Switch $style
        Case 0
    ; Adjust the angles based on the aspect
            For $nCount = 0 To UBound($Percentage)
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $PIE_DIAMETER * Sin($Angles[$nCount] * $PI / 180)
                $Y -= ($PIE_DIAMETER - $pieHeight) * Sin($Angles[$nCount] * $PI / 180)
                If $X = 0 Then
                    $Angles[$nCount] = 90 + ($Y < 0) * 180
                Else
                    $Angles[$nCount] = ATan($Y / $X) * 180 / $PI
                EndIf
                If $X < 0 Then $Angles[$nCount] += 180
                If $X >= 0 And $Y < 0 Then $Angles[$nCount] += 360
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $pieHeight * Sin($Angles[$nCount] * $PI / 180)
            Next

    ; Decide which pieces to draw first and last
            Local $nStart = -1, $nEnd = -1
            For $nCount = 0 To UBound($Percentage) - 1
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                If $angleStart <= 270 And ($angleStart + $angleSweep) >= 270 Then
                    $nStart = $nCount
                EndIf
                If ($angleStart <= 90 And ($angleStart + $angleSweep) >= 90) _
                        Or ($angleStart <= 450 And ($angleStart + $angleSweep) >= 450) Then
                    $nEnd = $nCount
                EndIf
                If $nEnd >= 0 And $nStart >= 0 Then ExitLoop
            Next

    ; Draw the first piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nStart, $Angles)
            
    ; Draw pieces "to the right"
            $nCount = Mod($nStart + 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + 1, UBound($Percentage))
            WEnd
            
    ; Draw pieces "to the left"
            $nCount = Mod($nStart + UBound($Percentage) - 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + UBound($Percentage) - 1, UBound($Percentage))
            WEnd
            
    ; Draw the last piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nEnd, $Angles)
        Case 1
    ; Draw the donut pieces
            For $nCount = 0 To UBound($Percentage) - 1
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                
        ; Draw the outer arc in a darker colour
                $hPath = _GDIPlus_GraphicsPathCreate()
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft, $pieTop, $pieWidth, $pieHeight, $angleStart, $angleSweep)
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_GraphicsPathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][1], $hPath)
                _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
                _GDIPlus_GraphicsPathDispose($hPath)
                
        ; Draw the inner piece in a lighter colour - leave room for the hole
                $hPath = _GDIPlus_GraphicsPathCreate()
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart, $angleSweep)
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + ($PIE_DIAMETER - $holesize) / 2, $pieTop + ($PIE_DIAMETER - $holesize) / 2, _
                        $holesize, $holesize, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_GraphicsPathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][0], $hPath)
                _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
                _GDIPlus_GraphicsPathDispose($hPath)
            Next
    EndSwitch

; Now draw the bitmap on to the device context of the window
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
EndFunc ;==>_DrawPie

Func _OnNotify($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Switch $hWndFrom
        Case $hSlideAspect, $hSlideRotation, $hStyle, $hHoleSize
    ; Update the pie chart
            _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
                    _GUICtrlSlider_GetPos($hSlideRotation), _
                    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
                    _GUICtrlSlider_GetPos($hHoleSize))
    EndSwitch
EndFunc ;==>_OnNotify

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

; Draw side
    ConsoleWrite(_Now() & @CRLF)
    $hPath = _GDIPlus_GraphicsPathCreate()
    If $iStart < 180 And ($iStart + $iSweep > 180) Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, 180 - $iStart)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, 180, $iStart - 180)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
        $fDrawn = True
    EndIf
    If $iStart + $iSweep > 360 Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, 0, $iStart + $iSweep - 360)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep - 360, 360 - $iStart - $iSweep)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
        $fDrawn = True
    EndIf
    If $iStart < 180 And (Not $fDrawn) Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep, -$iSweep)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    EndIf
    _GDIPlus_GraphicsPathDispose($hPath)

; Draw top
    _GDIPlus_GraphicsFillPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahBrush[$nCount][0])
    _GDIPlus_GraphicsDrawPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahPen[$nCount])

EndFunc ;==>_DrawPiePiece

Func _GDIPlus_GraphicsPathCreate($iFillMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreatePath", "int", $iFillMode, "int*", 0);
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, $aResult[2])
EndFunc ;==>_GDIPlus_GraphicsPathCreate

Func _GDIPlus_GraphicsPathAddLine($hGraphicsPath, $iX1, $iY1, $iX2, $iY2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathLine", "hwnd", $hGraphicsPath, "float", $iX1, "float", $iY1, _
            "float", $iX2, "float", $iY2)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddLine

Func _GDIPlus_GraphicsPathAddArc($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathArc", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
            "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddArc

Func _GDIPlus_GraphicsPathAddPie($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathPie", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
            "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddPie

Func _GDIPlus_GraphicsPathCloseFigure($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipClosePathFigure", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathCloseFigure

Func _GDIPlus_GraphicsPathDispose($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDeletePath", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathDispose

Func _GDIPlus_GraphicsDrawPath($hGraphics, $hPen, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawPath", "hwnd", $hGraphics, "hwnd", $hPen, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsDrawPath

Func _GDIPlus_GraphicsFillPath($hGraphics, $hBrush, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipFillPath", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsFillPath
Link to comment
Share on other sites

Try replace

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

to this

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
MsgBox(0,"nCount value","$nCount = " & $nCount)
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

I obtained

$nCount = -1

And it's clear that error occurs.

Do you what is a value of $Angles[-1]?

The point of world view

Link to comment
Share on other sites

Try replace

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

to this

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
MsgBox(0,"nCount value","$nCount = " & $nCount)
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

I obtained

$nCount = -1

And it's clear that error occurs.

Do you what is a value of $Angles[-1]?

@Valery...I agree and that is exactly what I found out as well, that the error occurs because of the -1 value for $nCount. I think it comes back with a -1 because no other pie piece has been drawn since they are all 0s. I think the following code will need to be updated but not sure how.

; Decide which pieces to draw first and last
            Local $nStart = -1, $nEnd = -1
            For $nCount = 0 To UBound($Percentage) -1
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                If $angleStart <= 270 And ($angleStart + $angleSweep) >= 270 Then
                    $nStart = $nCount
                EndIf
                If ($angleStart <= 90 And ($angleStart + $angleSweep) >= 90) _
                        Or ($angleStart <= 450 And ($angleStart + $angleSweep) >= 450) Then
                    $nEnd = $nCount
                EndIf
                If $nEnd >= 0 And $nStart >= 0 Then ExitLoop
            Next

Thanks.

Link to comment
Share on other sites

This works fine, I think:

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUISlider.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <Date.au3>

; Let's be strict here
Opt("MustDeclareVars", 1)

; Controls the size of the pie and also the depth
Global Const $PIE_DIAMETER = 400
Global Const $PIE_MARGIN = $PIE_DIAMETER * 0.025
Global Const $PIE_DEPTH = $PIE_DIAMETER * 0.2
Global Const $PIE_AREA = $PIE_DIAMETER + 2 * $PIE_MARGIN

; Random data for values and colours
Global Const $NUM_VALUES = 5
Global $aChartValue[$NUM_VALUES]
Global $aChartColour[$NUM_VALUES]


Global $aChartColour[5] = ["0xFF8204", "0x0000FF", "0xFF0000", "0x008000", "0xEEF3F6"]

$aChartValue[0] = 3
$aChartValue[1] = 15
$aChartValue[2] = 45
$aChartValue[3] = 20
$aChartValue[4] = 30

; The value of PI
Global Const $PI = ATan(1) * 4

; Start GDI+
_GDIPlus_Startup()

; Create the brushes and pens
Global $ahBrush[$NUM_VALUES][2], $ahPen[$NUM_VALUES]
For $i = 0 To $NUM_VALUES - 1
    $ahBrush[$i][0] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, $aChartColour[$i]))
    $ahBrush[$i][1] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, _GetDarkerColour($aChartColour[$i])))
    $ahPen[$i] = _GDIPlus_PenCreate(BitOR(0xff000000, _GetDarkerColour(_GetDarkerColour($aChartColour[$i]))))
Next

; Create the GUI with sliders to control the aspect, rotation, style and hole size (for donuts)
Global $hWnd = GUICreate("Pie Chart", $PIE_AREA, $PIE_AREA + 100, Default, Default)
Global $hSlideAspect = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 10, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideAspect, 10, 100)
_GUICtrlSlider_SetPos($hSlideAspect, 50)
Global $hSlideRotation = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 40, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideRotation, 0, 360)
Global $cStyle = GUICtrlCreateCheckbox("Donut", $PIE_MARGIN, $PIE_AREA + 70, $PIE_DIAMETER / 2 - $PIE_MARGIN, 20)
Global $hStyle = GUICtrlGetHandle($cStyle)
Global $hHoleSize = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN + $PIE_DIAMETER / 2, $PIE_AREA + 70, $PIE_DIAMETER / 2, 20)
_GUICtrlSlider_SetRange($hHoleSize, 2, $PIE_DIAMETER - 4 * $PIE_MARGIN)
_GUICtrlSlider_SetPos($hHoleSize, $PIE_DIAMETER / 2)
GUISetState()

; Set up GDI+
Global $hDC = _WinAPI_GetDC($hWnd)
Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($PIE_AREA, $PIE_AREA, $hGraphics)
Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)

; Draw the initial pie chart
_DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
        _GUICtrlSlider_GetPos($hSlideRotation), _
        (GUICtrlRead($cStyle) = $GUI_CHECKED), _
        _GUICtrlSlider_GetPos($hHoleSize))

; The sliders will send WM_NOTIFY messages
GUIRegisterMsg($WM_NOTIFY, "_OnNotify")

; Wait until the user quits
While GUIGetMsg() <> $GUI_EVENT_CLOSE
    Sleep(10)
WEnd

; Release the resources
For $i = 0 To UBound($aChartColour) - 1
    _GDIPlus_PenDispose($ahPen[$i])
    _GDIPlus_BrushDispose($ahBrush[$i][0])
    _GDIPlus_BrushDispose($ahBrush[$i][1])
Next
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_ReleaseDC($hWnd, $hDC)

; Shut down GDI+
_GDIPlus_Shutdown()

; Done
Exit

; Get a darker version of a colour by extracting the RGB components
Func _GetDarkerColour($Colour)
    Local $Red, $Green, $Blue
    $Red = (BitAND($Colour, 0xff0000) / 0x10000) - 40
    $Green = (BitAND($Colour, 0x00ff00) / 0x100) - 40
    $Blue = (BitAND($Colour, 0x0000ff)) - 40
    If $Red < 0 Then $Red = 0
    If $Green < 0 Then $Green = 0
    If $Blue < 0 Then $Blue = 0
    Return ($Red * 0x10000) + ($Green * 0x100) + $Blue
EndFunc ;==>_GetDarkerColour

; Draw the pie chart
Func _DrawPie($Percentage, $Aspect, $rotation, $style = 0, $holesize = 100)
    If $style <> 0 Then $Aspect = 1
    Local $nCount, $nTotal = 0, $angleStart, $angleSweep, $X, $Y
    Local $pieLeft = $PIE_MARGIN, $pieTop = $PIE_AREA / 2 - ($PIE_DIAMETER / 2) * $Aspect
    Local $pieWidth = $PIE_DIAMETER, $pieHeight = $PIE_DIAMETER * $Aspect, $hPath

; Total up the values
    For $nCount = 0 To UBound($Percentage) - 1
        $nTotal += $Percentage[$nCount]
    Next

; Set the fractional values
    For $nCount = 0 To UBound($Percentage) - 1
        $Percentage[$nCount] /= $nTotal
    Next

; Make sure we don't over-rotate
    $rotation = Mod($rotation, 360)

; Clear the graphics buffer
    _GDIPlus_GraphicsClear($hBuffer, 0xffc0c0c0)

; Set the initial angles based on the fractional values
    Local $Angles[UBound($Percentage) + 1]
    For $nCount = 0 To UBound($Percentage)
        If $nCount = 0 Then
            $Angles[$nCount] = $rotation
        Else
            $Angles[$nCount] = $Angles[$nCount - 1] + ($Percentage[$nCount - 1] * 360)
        EndIf
    Next

    Switch $style
        Case 0
    ; Adjust the angles based on the aspect
            For $nCount = 0 To UBound($Percentage)
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $PIE_DIAMETER * Sin($Angles[$nCount] * $PI / 180)
                $Y -= ($PIE_DIAMETER - $pieHeight) * Sin($Angles[$nCount] * $PI / 180)
                If $X = 0 Then
                    $Angles[$nCount] = 90 + ($Y < 0) * 180
                Else
                    $Angles[$nCount] = ATan($Y / $X) * 180 / $PI
                EndIf
                If $X < 0 Then $Angles[$nCount] += 180
                If $X >= 0 And $Y < 0 Then $Angles[$nCount] += 360
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $pieHeight * Sin($Angles[$nCount] * $PI / 180)
            Next


    ; Decide which pieces to draw first and last
            Local $nStart = -1, $nEnd = -1
            For $nCount = 0 To UBound($Percentage)
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                If $angleStart <= 270 And ($angleStart + $angleSweep) >= 270 Then
                    $nStart = $nCount
                EndIf
                If ($angleStart <= 90 And ($angleStart + $angleSweep) >= 90) _
                        Or ($angleStart <= 450 And ($angleStart + $angleSweep) >= 450) Then
                    $nEnd = $nCount
                EndIf
                If $nEnd >= 0 And $nStart >= 0 Then ExitLoop
            Next


    ; Draw the first piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nStart, $Angles)
            
    ; Draw pieces "to the right"
            $nCount = Mod($nStart + 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + 1, UBound($Percentage))
            WEnd
            
    ; Draw pieces "to the left"
            $nCount = Mod($nStart + UBound($Percentage) - 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + UBound($Percentage) - 1, UBound($Percentage))
            WEnd
            
    ; Draw the last piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nEnd, $Angles)
        Case 1
    ; Draw the donut pieces
            For $nCount = 0 To UBound($Percentage) - 1
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                
        ; Draw the outer arc in a darker colour
                $hPath = _GDIPlus_GraphicsPathCreate()
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft, $pieTop, $pieWidth, $pieHeight, $angleStart, $angleSweep)
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_GraphicsPathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][1], $hPath)
                _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
                _GDIPlus_GraphicsPathDispose($hPath)
                
        ; Draw the inner piece in a lighter colour - leave room for the hole
                $hPath = _GDIPlus_GraphicsPathCreate()
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart, $angleSweep)
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + ($PIE_DIAMETER - $holesize) / 2, $pieTop + ($PIE_DIAMETER - $holesize) / 2, _
                        $holesize, $holesize, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_GraphicsPathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][0], $hPath)
                _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
                _GDIPlus_GraphicsPathDispose($hPath)
            Next
    EndSwitch

; Now draw the bitmap on to the device context of the window
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
EndFunc ;==>_DrawPie

Func _OnNotify($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Switch $hWndFrom
        Case $hSlideAspect, $hSlideRotation, $hStyle, $hHoleSize
    ; Update the pie chart
            _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
                    _GUICtrlSlider_GetPos($hSlideRotation), _
                    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
                    _GUICtrlSlider_GetPos($hHoleSize))
    EndSwitch
EndFunc ;==>_OnNotify

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath
    Local $cX = $iX + ($iWidth / 2)
    Local $cY = $iY + ($iHeight / 2)
    Local $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360)
    Local $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

; Draw side
    ConsoleWrite(_Now() & @CRLF)
    $hPath = _GDIPlus_GraphicsPathCreate()
    If $iStart < 180 And ($iStart + $iSweep > 180) Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, 180 - $iStart)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, 180, $iStart - 180)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
        $fDrawn = True
    EndIf
    If $iStart + $iSweep > 360 Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, 0, $iStart + $iSweep - 360)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep - 360, 360 - $iStart - $iSweep)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
        $fDrawn = True
    EndIf
    If $iStart < 180 And (Not $fDrawn) Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep, -$iSweep)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    EndIf
    _GDIPlus_GraphicsPathDispose($hPath)

; Draw top
    _GDIPlus_GraphicsFillPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahBrush[$nCount][0])
    _GDIPlus_GraphicsDrawPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahPen[$nCount])

EndFunc ;==>_DrawPiePiece

Func _GDIPlus_GraphicsPathCreate($iFillMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreatePath", "int", $iFillMode, "int*", 0);
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, $aResult[2])
EndFunc ;==>_GDIPlus_GraphicsPathCreate

Func _GDIPlus_GraphicsPathAddLine($hGraphicsPath, $iX1, $iY1, $iX2, $iY2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathLine", "hwnd", $hGraphicsPath, "float", $iX1, "float", $iY1, _
            "float", $iX2, "float", $iY2)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddLine

Func _GDIPlus_GraphicsPathAddArc($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathArc", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
            "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddArc

Func _GDIPlus_GraphicsPathAddPie($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathPie", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
            "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddPie

Func _GDIPlus_GraphicsPathCloseFigure($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipClosePathFigure", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathCloseFigure

Func _GDIPlus_GraphicsPathDispose($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDeletePath", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathDispose

Func _GDIPlus_GraphicsDrawPath($hGraphics, $hPen, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawPath", "hwnd", $hGraphics, "hwnd", $hPen, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsDrawPath

Func _GDIPlus_GraphicsFillPath($hGraphics, $hBrush, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipFillPath", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsFillPath

The point of world view

Link to comment
Share on other sites

This works fine, I think:

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUISlider.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <Date.au3>

; Let's be strict here
Opt("MustDeclareVars", 1)

; Controls the size of the pie and also the depth
Global Const $PIE_DIAMETER = 400
Global Const $PIE_MARGIN = $PIE_DIAMETER * 0.025
Global Const $PIE_DEPTH = $PIE_DIAMETER * 0.2
Global Const $PIE_AREA = $PIE_DIAMETER + 2 * $PIE_MARGIN

; Random data for values and colours
Global Const $NUM_VALUES = 5
Global $aChartValue[$NUM_VALUES]
Global $aChartColour[$NUM_VALUES]


Global $aChartColour[5] = ["0xFF8204", "0x0000FF", "0xFF0000", "0x008000", "0xEEF3F6"]

$aChartValue[0] = 3
$aChartValue[1] = 15
$aChartValue[2] = 45
$aChartValue[3] = 20
$aChartValue[4] = 30

; The value of PI
Global Const $PI = ATan(1) * 4

; Start GDI+
_GDIPlus_Startup()

; Create the brushes and pens
Global $ahBrush[$NUM_VALUES][2], $ahPen[$NUM_VALUES]
For $i = 0 To $NUM_VALUES - 1
    $ahBrush[$i][0] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, $aChartColour[$i]))
    $ahBrush[$i][1] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, _GetDarkerColour($aChartColour[$i])))
    $ahPen[$i] = _GDIPlus_PenCreate(BitOR(0xff000000, _GetDarkerColour(_GetDarkerColour($aChartColour[$i]))))
Next

; Create the GUI with sliders to control the aspect, rotation, style and hole size (for donuts)
Global $hWnd = GUICreate("Pie Chart", $PIE_AREA, $PIE_AREA + 100, Default, Default)
Global $hSlideAspect = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 10, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideAspect, 10, 100)
_GUICtrlSlider_SetPos($hSlideAspect, 50)
Global $hSlideRotation = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 40, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideRotation, 0, 360)
Global $cStyle = GUICtrlCreateCheckbox("Donut", $PIE_MARGIN, $PIE_AREA + 70, $PIE_DIAMETER / 2 - $PIE_MARGIN, 20)
Global $hStyle = GUICtrlGetHandle($cStyle)
Global $hHoleSize = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN + $PIE_DIAMETER / 2, $PIE_AREA + 70, $PIE_DIAMETER / 2, 20)
_GUICtrlSlider_SetRange($hHoleSize, 2, $PIE_DIAMETER - 4 * $PIE_MARGIN)
_GUICtrlSlider_SetPos($hHoleSize, $PIE_DIAMETER / 2)
GUISetState()

; Set up GDI+
Global $hDC = _WinAPI_GetDC($hWnd)
Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($PIE_AREA, $PIE_AREA, $hGraphics)
Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)

; Draw the initial pie chart
_DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
        _GUICtrlSlider_GetPos($hSlideRotation), _
        (GUICtrlRead($cStyle) = $GUI_CHECKED), _
        _GUICtrlSlider_GetPos($hHoleSize))

; The sliders will send WM_NOTIFY messages
GUIRegisterMsg($WM_NOTIFY, "_OnNotify")

; Wait until the user quits
While GUIGetMsg() <> $GUI_EVENT_CLOSE
    Sleep(10)
WEnd

; Release the resources
For $i = 0 To UBound($aChartColour) - 1
    _GDIPlus_PenDispose($ahPen[$i])
    _GDIPlus_BrushDispose($ahBrush[$i][0])
    _GDIPlus_BrushDispose($ahBrush[$i][1])
Next
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_ReleaseDC($hWnd, $hDC)

; Shut down GDI+
_GDIPlus_Shutdown()

; Done
Exit

; Get a darker version of a colour by extracting the RGB components
Func _GetDarkerColour($Colour)
    Local $Red, $Green, $Blue
    $Red = (BitAND($Colour, 0xff0000) / 0x10000) - 40
    $Green = (BitAND($Colour, 0x00ff00) / 0x100) - 40
    $Blue = (BitAND($Colour, 0x0000ff)) - 40
    If $Red < 0 Then $Red = 0
    If $Green < 0 Then $Green = 0
    If $Blue < 0 Then $Blue = 0
    Return ($Red * 0x10000) + ($Green * 0x100) + $Blue
EndFunc ;==>_GetDarkerColour

; Draw the pie chart
Func _DrawPie($Percentage, $Aspect, $rotation, $style = 0, $holesize = 100)
    If $style <> 0 Then $Aspect = 1
    Local $nCount, $nTotal = 0, $angleStart, $angleSweep, $X, $Y
    Local $pieLeft = $PIE_MARGIN, $pieTop = $PIE_AREA / 2 - ($PIE_DIAMETER / 2) * $Aspect
    Local $pieWidth = $PIE_DIAMETER, $pieHeight = $PIE_DIAMETER * $Aspect, $hPath

; Total up the values
    For $nCount = 0 To UBound($Percentage) - 1
        $nTotal += $Percentage[$nCount]
    Next

; Set the fractional values
    For $nCount = 0 To UBound($Percentage) - 1
        $Percentage[$nCount] /= $nTotal
    Next

; Make sure we don't over-rotate
    $rotation = Mod($rotation, 360)

; Clear the graphics buffer
    _GDIPlus_GraphicsClear($hBuffer, 0xffc0c0c0)

; Set the initial angles based on the fractional values
    Local $Angles[UBound($Percentage) + 1]
    For $nCount = 0 To UBound($Percentage)
        If $nCount = 0 Then
            $Angles[$nCount] = $rotation
        Else
            $Angles[$nCount] = $Angles[$nCount - 1] + ($Percentage[$nCount - 1] * 360)
        EndIf
    Next

    Switch $style
        Case 0
    ; Adjust the angles based on the aspect
            For $nCount = 0 To UBound($Percentage)
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $PIE_DIAMETER * Sin($Angles[$nCount] * $PI / 180)
                $Y -= ($PIE_DIAMETER - $pieHeight) * Sin($Angles[$nCount] * $PI / 180)
                If $X = 0 Then
                    $Angles[$nCount] = 90 + ($Y < 0) * 180
                Else
                    $Angles[$nCount] = ATan($Y / $X) * 180 / $PI
                EndIf
                If $X < 0 Then $Angles[$nCount] += 180
                If $X >= 0 And $Y < 0 Then $Angles[$nCount] += 360
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $pieHeight * Sin($Angles[$nCount] * $PI / 180)
            Next


    ; Decide which pieces to draw first and last
            Local $nStart = -1, $nEnd = -1
            For $nCount = 0 To UBound($Percentage)
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                If $angleStart <= 270 And ($angleStart + $angleSweep) >= 270 Then
                    $nStart = $nCount
                EndIf
                If ($angleStart <= 90 And ($angleStart + $angleSweep) >= 90) _
                        Or ($angleStart <= 450 And ($angleStart + $angleSweep) >= 450) Then
                    $nEnd = $nCount
                EndIf
                If $nEnd >= 0 And $nStart >= 0 Then ExitLoop
            Next


    ; Draw the first piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nStart, $Angles)
            
    ; Draw pieces "to the right"
            $nCount = Mod($nStart + 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + 1, UBound($Percentage))
            WEnd
            
    ; Draw pieces "to the left"
            $nCount = Mod($nStart + UBound($Percentage) - 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + UBound($Percentage) - 1, UBound($Percentage))
            WEnd
            
    ; Draw the last piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nEnd, $Angles)
        Case 1
    ; Draw the donut pieces
            For $nCount = 0 To UBound($Percentage) - 1
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                
        ; Draw the outer arc in a darker colour
                $hPath = _GDIPlus_GraphicsPathCreate()
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft, $pieTop, $pieWidth, $pieHeight, $angleStart, $angleSweep)
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_GraphicsPathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][1], $hPath)
                _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
                _GDIPlus_GraphicsPathDispose($hPath)
                
        ; Draw the inner piece in a lighter colour - leave room for the hole
                $hPath = _GDIPlus_GraphicsPathCreate()
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart, $angleSweep)
                _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + ($PIE_DIAMETER - $holesize) / 2, $pieTop + ($PIE_DIAMETER - $holesize) / 2, _
                        $holesize, $holesize, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_GraphicsPathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][0], $hPath)
                _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
                _GDIPlus_GraphicsPathDispose($hPath)
            Next
    EndSwitch

; Now draw the bitmap on to the device context of the window
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
EndFunc ;==>_DrawPie

Func _OnNotify($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Switch $hWndFrom
        Case $hSlideAspect, $hSlideRotation, $hStyle, $hHoleSize
    ; Update the pie chart
            _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
                    _GUICtrlSlider_GetPos($hSlideRotation), _
                    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
                    _GUICtrlSlider_GetPos($hHoleSize))
    EndSwitch
EndFunc ;==>_OnNotify

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath
    Local $cX = $iX + ($iWidth / 2)
    Local $cY = $iY + ($iHeight / 2)
    Local $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360)
    Local $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

; Draw side
    ConsoleWrite(_Now() & @CRLF)
    $hPath = _GDIPlus_GraphicsPathCreate()
    If $iStart < 180 And ($iStart + $iSweep > 180) Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, 180 - $iStart)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, 180, $iStart - 180)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
        $fDrawn = True
    EndIf
    If $iStart + $iSweep > 360 Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, 0, $iStart + $iSweep - 360)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep - 360, 360 - $iStart - $iSweep)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
        $fDrawn = True
    EndIf
    If $iStart < 180 And (Not $fDrawn) Then
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep)
        _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep, -$iSweep)
        _GDIPlus_GraphicsPathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
        _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    EndIf
    _GDIPlus_GraphicsPathDispose($hPath)

; Draw top
    _GDIPlus_GraphicsFillPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahBrush[$nCount][0])
    _GDIPlus_GraphicsDrawPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahPen[$nCount])

EndFunc ;==>_DrawPiePiece

Func _GDIPlus_GraphicsPathCreate($iFillMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreatePath", "int", $iFillMode, "int*", 0);
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, $aResult[2])
EndFunc ;==>_GDIPlus_GraphicsPathCreate

Func _GDIPlus_GraphicsPathAddLine($hGraphicsPath, $iX1, $iY1, $iX2, $iY2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathLine", "hwnd", $hGraphicsPath, "float", $iX1, "float", $iY1, _
            "float", $iX2, "float", $iY2)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddLine

Func _GDIPlus_GraphicsPathAddArc($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathArc", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
            "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddArc

Func _GDIPlus_GraphicsPathAddPie($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathPie", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
            "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddPie

Func _GDIPlus_GraphicsPathCloseFigure($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipClosePathFigure", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathCloseFigure

Func _GDIPlus_GraphicsPathDispose($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDeletePath", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathDispose

Func _GDIPlus_GraphicsDrawPath($hGraphics, $hPen, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawPath", "hwnd", $hGraphics, "hwnd", $hPen, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsDrawPath

Func _GDIPlus_GraphicsFillPath($hGraphics, $hBrush, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipFillPath", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsFillPath

@Valery...Did you run the code that I posted? I am having problems with the following area of the code:

$aChartValue[0] = 0
$aChartValue[1] = 0
$aChartValue[2] = 0
$aChartValue[3] = 0
$aChartValue[4] = 100

Thanks.

Link to comment
Share on other sites

  • 2 months later...

Try this:

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUISlider.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <Date.au3>

; Let's be strict here
Opt("MustDeclareVars", 1)

; Controls the size of the pie and also the depth
Global Const $PIE_DIAMETER = 400
Global Const $PIE_MARGIN = $PIE_DIAMETER * 0.025
Global Const $PIE_DEPTH = $PIE_DIAMETER * 0.2
Global Const $PIE_AREA = $PIE_DIAMETER + 2 * $PIE_MARGIN

; Random data for values and colours
Global Const $NUM_VALUES = 8
Global $aChartValue[$NUM_VALUES]
Global $aChartColour[$NUM_VALUES]
For $i = 0 To $NUM_VALUES - 1
    $aChartValue[$i] = Random(5, 25, 1)
    $aChartColour[$i] = (Random(0, 255, 1) * 0x10000) + (Random(0, 255, 1) * 0x100) + Random(0, 255, 1)
Next

; The value of PI
Global Const $PI = ATan(1) * 4
Global $counter = 0

; Start GDI+
_GDIPlus_Startup()

; Create the brushes and pens
Global $ahBrush[$NUM_VALUES][2], $ahPen[$NUM_VALUES]
For $i = 0 To $NUM_VALUES - 1
    $ahBrush[$i][0] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, $aChartColour[$i]))
    $ahBrush[$i][1] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, _GetDarkerColour($aChartColour[$i])))
    $ahPen[$i] = _GDIPlus_PenCreate(BitOR(0xff000000, _GetDarkerColour(_GetDarkerColour($aChartColour[$i]))))
Next

; Create the GUI with sliders to control the aspect, rotation, style and hole size (for donuts)
Global $hWnd = GUICreate("Pie Chart", $PIE_AREA, $PIE_AREA + 100, Default, Default)
Global $hSlideAspect = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 10, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideAspect, 10, 100)
_GUICtrlSlider_SetPos($hSlideAspect, 50)
Global $hSlideRotation = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 40, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideRotation, 0, 360)
Global $cStyle = GUICtrlCreateCheckbox("Donut", $PIE_MARGIN, $PIE_AREA + 70, $PIE_DIAMETER / 2 - $PIE_MARGIN, 20)
Global $hStyle = GUICtrlGetHandle($cStyle)
Global $hHoleSize = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN + $PIE_DIAMETER / 2, $PIE_AREA + 70, $PIE_DIAMETER / 2, 20)
_GUICtrlSlider_SetRange($hHoleSize, 2, $PIE_DIAMETER - 4 * $PIE_MARGIN)
_GUICtrlSlider_SetPos($hHoleSize, $PIE_DIAMETER / 2)
GUISetState()

; Set up GDI+
Global $hDC = _WinAPI_GetDC($hWnd)
Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($PIE_AREA, $PIE_AREA, $hGraphics)
Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)

; Draw the initial pie chart
_DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
    _GUICtrlSlider_GetPos($hSlideRotation), _
    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
    _GUICtrlSlider_GetPos($hHoleSize))

; The sliders will send WM_NOTIFY messages
GUIRegisterMsg($WM_NOTIFY, "_OnNotify")

; Wait until the user quits
While GUIGetMsg() <> $GUI_EVENT_CLOSE
    Sleep(10)
WEnd

; Release the resources
For $i = 0 To UBound($aChartColour) - 1
    _GDIPlus_PenDispose($ahPen[$i])
    _GDIPlus_BrushDispose($ahBrush[$i][0])
    _GDIPlus_BrushDispose($ahBrush[$i][1])
Next
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_ReleaseDC($hWnd, $hDC)

; Shut down GDI+
_GDIPlus_Shutdown()

; Done
Exit

; Get a darker version of a colour by extracting the RGB components
Func _GetDarkerColour($Colour)
    Local $Red, $Green, $Blue
    $Red = (BitAND($Colour, 0xff0000) / 0x10000) - 40
    $Green = (BitAND($Colour, 0x00ff00) / 0x100) - 40
    $Blue = (BitAND($Colour, 0x0000ff)) - 40
    If $Red < 0 Then $Red = 0
    If $Green < 0 Then $Green = 0
    If $Blue < 0 Then $Blue = 0
    Return ($Red * 0x10000) + ($Green * 0x100) + $Blue
EndFunc ;==>_GetDarkerColour

; Draw the pie chart
Func _DrawPie($Percentage, $Aspect, $rotation, $style = 0, $holesize = 100)
    If $style <> 0 Then $Aspect = 1
    Local $nCount, $nTotal = 0, $angleStart, $angleSweep, $X, $Y
    Local $pieLeft = $PIE_MARGIN, $pieTop = $PIE_AREA / 2 - ($PIE_DIAMETER / 2) * $Aspect
    Local $pieWidth = $PIE_DIAMETER, $pieHeight = $PIE_DIAMETER * $Aspect, $hPath

; Total up the values
    For $nCount = 0 To UBound($Percentage) - 1
    $nTotal += $Percentage[$nCount]
    Next

; Set the fractional values
    For $nCount = 0 To UBound($Percentage) - 1
    $Percentage[$nCount] /= $nTotal
    Next

; Make sure we don't over-rotate
    $rotation = Mod($rotation, 360)

; Clear the graphics buffer
    _GDIPlus_GraphicsClear($hBuffer, 0xffc0c0c0)

; Set the initial angles based on the fractional values
    Local $Angles[UBound($Percentage) + 1]
    For $nCount = 0 To UBound($Percentage)
    If $nCount = 0 Then
    $Angles[$nCount] = $rotation
    Else
    $Angles[$nCount] = $Angles[$nCount - 1] + ($Percentage[$nCount - 1] * 360)
    EndIf
    Next

    Switch $style
    Case 0
    ; Adjust the angles based on the aspect
    For $nCount = 0 To UBound($Percentage)
    $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
    $Y = $PIE_DIAMETER * Sin($Angles[$nCount] * $PI / 180)
    $Y -= ($PIE_DIAMETER - $pieHeight) * Sin($Angles[$nCount] * $PI / 180)
    If $X = 0 Then
    $Angles[$nCount] = 90 + ($Y < 0) * 180
    Else
    $Angles[$nCount] = ATan($Y / $X) * 180 / $PI
    EndIf
    If $X < 0 Then $Angles[$nCount] += 180
    If $X >= 0 And $Y < 0 Then $Angles[$nCount] += 360
    $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
    $Y = $pieHeight * Sin($Angles[$nCount] * $PI / 180)
    Next

    ; Decide which pieces to draw first and last
    Local $nStart = -1, $nEnd = -1
    For $nCount = 0 To UBound($Percentage) - 1
    $angleStart = Mod($Angles[$nCount], 360)
    $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
    If $angleStart <= 270 And ($angleStart + $angleSweep) >= 270 Then
    $nStart = $nCount
    EndIf
    If ($angleStart <= 90 And ($angleStart + $angleSweep) >= 90) _
    Or ($angleStart <= 450 And ($angleStart + $angleSweep) >= 450) Then
    $nEnd = $nCount
    EndIf
    If $nEnd >= 0 And $nStart >= 0 Then ExitLoop
    Next

    ; Draw the first piece
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nStart, $Angles)

    ; Draw pieces "to the right"
    $nCount = Mod($nStart + 1, UBound($Percentage))
    While $nCount <> $nEnd
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
    $nCount = Mod($nCount + 1, UBound($Percentage))
    WEnd

    ; Draw pieces "to the left"
    $nCount = Mod($nStart + UBound($Percentage) - 1, UBound($Percentage))
    While $nCount <> $nEnd
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
    $nCount = Mod($nCount + UBound($Percentage) - 1, UBound($Percentage))
    WEnd

    ; Draw the last piece
    _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nEnd, $Angles)
    Case 1
    ; Draw the donut pieces
    For $nCount = 0 To UBound($Percentage) - 1
    $angleStart = Mod($Angles[$nCount], 360)
    $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

    ; Draw the outer arc in a darker colour
    $hPath = _GDIPlus_GraphicsPathCreate()
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft, $pieTop, $pieWidth, $pieHeight, $angleStart, $angleSweep)
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
    $pieHeight - $PIE_MARGIN * 2, $angleStart + $angleSweep, -$angleSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
    _GDIPlus_GraphicsPathDispose($hPath)

    ; Draw the inner piece in a lighter colour - leave room for the hole
    $hPath = _GDIPlus_GraphicsPathCreate()
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
    $pieHeight - $PIE_MARGIN * 2, $angleStart, $angleSweep)
    _GDIPlus_GraphicsPathAddArc($hPath, $pieLeft + ($PIE_DIAMETER - $holesize) / 2, $pieTop + ($PIE_DIAMETER - $holesize) / 2, _
    $holesize, $holesize, $angleStart + $angleSweep, -$angleSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hBuffer, $ahBrush[$nCount][0], $hPath)
    _GDIPlus_GraphicsDrawPath($hBuffer, $ahPen[$nCount], $hPath)
    _GDIPlus_GraphicsPathDispose($hPath)
    Next
    EndSwitch

; Now draw the bitmap on to the device context of the window
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\" & $counter & ".jpg")
    $counter += 1
EndFunc ;==>_DrawPie

Func _OnNotify($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Switch $hWndFrom
    Case $hSlideAspect, $hSlideRotation, $hStyle, $hHoleSize
    ; Update the pie chart
    _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
    _GUICtrlSlider_GetPos($hSlideRotation), _
    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
    _GUICtrlSlider_GetPos($hHoleSize))
    EndSwitch
EndFunc ;==>_OnNotify

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

; Draw side
    ConsoleWrite(_Now() & @CRLF)
    $hPath = _GDIPlus_GraphicsPathCreate()
    If $iStart < 180 And ($iStart + $iSweep > 180) Then
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, 180 - $iStart)
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, 180, $iStart - 180)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    $fDrawn = True
    EndIf
    If $iStart + $iSweep > 360 Then
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, 0, $iStart + $iSweep - 360)
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep - 360, 360 - $iStart - $iSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    $fDrawn = True
    EndIf
    If $iStart < 180 And (Not $fDrawn) Then
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep)
    _GDIPlus_GraphicsPathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep, -$iSweep)
    _GDIPlus_GraphicsPathCloseFigure($hPath)
    _GDIPlus_GraphicsFillPath($hGraphics, $ahBrush[$nCount][1], $hPath)
    _GDIPlus_GraphicsDrawPath($hGraphics, $ahPen[$nCount], $hPath)
    EndIf
    _GDIPlus_GraphicsPathDispose($hPath)

; Draw top
    _GDIPlus_GraphicsFillPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahBrush[$nCount][0])
    _GDIPlus_GraphicsDrawPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahPen[$nCount])

EndFunc ;==>_DrawPiePiece

Func _GDIPlus_GraphicsPathCreate($iFillMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreatePath", "int", $iFillMode, "int*", 0);
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, $aResult[2])
EndFunc ;==>_GDIPlus_GraphicsPathCreate

Func _GDIPlus_GraphicsPathAddLine($hGraphicsPath, $iX1, $iY1, $iX2, $iY2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathLine", "hwnd", $hGraphicsPath, "float", $iX1, "float", $iY1, _
    "float", $iX2, "float", $iY2)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddLine

Func _GDIPlus_GraphicsPathAddArc($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathArc", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
    "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddArc

Func _GDIPlus_GraphicsPathAddPie($hGraphicsPath, $iX, $iY, $iWidth, $iHeight, $iStartAngle, $iSweepAngle)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathPie", "hwnd", $hGraphicsPath, "float", $iX, "float", $iY, _
    "float", $iWidth, "float", $iHeight, "float", $iStartAngle, "float", $iSweepAngle)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathAddPie

Func _GDIPlus_GraphicsPathCloseFigure($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipClosePathFigure", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathCloseFigure

Func _GDIPlus_GraphicsPathDispose($hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDeletePath", "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsPathDispose

Func _GDIPlus_GraphicsDrawPath($hGraphics, $hPen, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawPath", "hwnd", $hGraphics, "hwnd", $hPen, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsDrawPath

Func _GDIPlus_GraphicsFillPath($hGraphics, $hBrush, $hGraphicsPath)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipFillPath", "hwnd", $hGraphics, "hwnd", $hBrush, "hwnd", $hGraphicsPath)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, 0)
EndFunc ;==>_GDIPlus_GraphicsFillPath

Line221: _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\" & $counter & ".jpg") did it!

It will save all movements additionally to script dir as JPGs named xx.jpg whereas xx = integer starting from 0!

UEZ

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Try this:

Line221: _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\" & $counter & ".jpg") did it!

It will save all movements additionally to script dir as JPGs named xx.jpg whereas xx = integer starting from 0!

UEZ

Thanks a lot. But it still requires that the window opens? Can it render it without opening the window? (so you could generate the picture on a computer which might be running at a very low 2 color resolution desktop?)

Link to comment
Share on other sites

  • 6 months later...
  • 9 months later...
  • 3 years later...

Post your whole script or a reproducer that gives you this error. :)

Snips & Scripts


My Snips: graphCPUTemp ~ getENVvars
My Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4

Feel free to use any of my code for your own use.                                                                                                                                                           Forum FAQ

 

Link to comment
Share on other sites

  • 2 years later...

@DjDeep00

I realise this is an old thread now, but im trying to use this pie chart and have the same issues.

If I setup my value something like this:

Global Const $NUM_VALUES = 3

$aChartValue[0] = 100
$aChartValue[1] = 10
$aChartValue[2] = 10

The pie starts out ok, but then rotating the pie ends up failing to draw as expected and then crashing as you go further along.
has anybody fixed this code at all? GDI can be confusing to me, let alone all of the maths involved in drawing/rotating/sizing pie pieces!

Link to comment
Share on other sites

Here is the problem i'm trying to describe in a nice little gif. when the pie is rotated i lose the side walls/fill.

pie_gif.gif

If you rotate too much then it crashes with:

"D:\Projects\Testing\3d pie.au3" (254) : ==> Variable subscript badly formatted.:
Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
Local $iStart = Mod($Angles[^ ERROR

 

I believe it crashes because $nCount = -1 but i think the root of the problem lies with some of the pie drawing maths thats a little too complicated for me.
can anybody solve this?

 

code im using:

;http://www.autoitscript.com/forum/index.php?showtopic=97241
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUISlider.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <Date.au3>
#include <array.au3>

; Let's be strict here
Opt("MustDeclareVars", 1)

;colours
Const $Red = 0xFFC7CE
Const $Green = 0xC6EFCE
Const $Orange = 0xFFEB9C

; Controls the size of the pie and also the depth
Global Const $PIE_DIAMETER = 400
Global Const $PIE_MARGIN = $PIE_DIAMETER * 0.025
Global Const $PIE_DEPTH = $PIE_DIAMETER * 0.2
Global Const $PIE_AREA = $PIE_DIAMETER + 2 * $PIE_MARGIN

; Random data for values and colours
Global Const $NUM_VALUES = 3
Global $aChartValue[$NUM_VALUES]
Global $aChartColour[$NUM_VALUES]

$aChartValue[0] = 100
$aChartValue[1] = 10
$aChartValue[2] = 10

For $i = 0 To $NUM_VALUES - 1
    ;$aChartValue[$i] = Random(5, 25, 1)
    ;$aChartColour[$i] = (Random(0, 255, 1) * 0x10000) + (Random(0, 255, 1) * 0x100) + Random(0, 255, 1)
    if $i = 0 then $aChartColour[$i] = $Red
    if $i = 1 then $aChartColour[$i] = $Orange
    if $i = 2 then $aChartColour[$i] = $Green
Next
;_ArrayDisplay($aChartValue)
;_ArrayDisplay($aChartColour)
; The value of PI
Global Const $PI = ATan(1) * 4

; Start GDI+
_GDIPlus_Startup()

; Create the brushes and pens
Global $ahBrush[$NUM_VALUES][2], $ahPen[$NUM_VALUES]
For $i = 0 To $NUM_VALUES - 1
    $ahBrush[$i][0] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, $aChartColour[$i]))
    $ahBrush[$i][1] = _GDIPlus_BrushCreateSolid(BitOR(0xff000000, _GetDarkerColour($aChartColour[$i])))
    $ahPen[$i] = _GDIPlus_PenCreate(BitOR(0xff000000, _GetDarkerColour(_GetDarkerColour($aChartColour[$i]))))
Next

; Create the GUI with sliders to control the aspect, rotation, style and hole size (for donuts)
Global $hWnd = GUICreate("Pie Chart", $PIE_AREA, $PIE_AREA + 100, Default, Default)
Global $hSlideAspect = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 10, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideAspect, 10, 100)
_GUICtrlSlider_SetPos($hSlideAspect, 50)
Global $hSlideRotation = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN, $PIE_AREA + 40, $PIE_DIAMETER, 20)
_GUICtrlSlider_SetRange($hSlideRotation, 0, 360)
Global $cStyle = GUICtrlCreateCheckbox("Donut", $PIE_MARGIN, $PIE_AREA + 70, $PIE_DIAMETER / 2 - $PIE_MARGIN, 20)
Global $hStyle = GUICtrlGetHandle($cStyle)
Global $hHoleSize = _GUICtrlSlider_Create($hWnd, $PIE_MARGIN + $PIE_DIAMETER / 2, $PIE_AREA + 70, $PIE_DIAMETER / 2, 20)
_GUICtrlSlider_SetRange($hHoleSize, 2, $PIE_DIAMETER - 4 * $PIE_MARGIN)
_GUICtrlSlider_SetPos($hHoleSize, $PIE_DIAMETER / 2)
GUISetState()

; Set up GDI+
Global $hDC = _WinAPI_GetDC($hWnd)
Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($PIE_AREA, $PIE_AREA, $hGraphics)
Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)

; Draw the initial pie chart
_DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
        _GUICtrlSlider_GetPos($hSlideRotation), _
        (GUICtrlRead($cStyle) = $GUI_CHECKED), _
        _GUICtrlSlider_GetPos($hHoleSize))

; The sliders will send WM_NOTIFY messages
GUIRegisterMsg($WM_NOTIFY, "_OnNotify")

; Wait until the user quits
While GUIGetMsg() <> $GUI_EVENT_CLOSE
    Sleep(20)
WEnd

; Release the resources
For $i = 0 To UBound($aChartColour) - 1
    _GDIPlus_PenDispose($ahPen[$i])
    _GDIPlus_BrushDispose($ahBrush[$i][0])
    _GDIPlus_BrushDispose($ahBrush[$i][1])
Next
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_ReleaseDC($hWnd, $hDC)

; Shut down GDI+
_GDIPlus_Shutdown()

; Done
Exit

; Get a darker version of a colour by extracting the RGB components
Func _GetDarkerColour($Colour)
    Local $Red, $Green, $Blue
    $Red = (BitAND($Colour, 0xff0000) / 0x10000) - 40
    $Green = (BitAND($Colour, 0x00ff00) / 0x100) - 40
    $Blue = (BitAND($Colour, 0x0000ff)) - 40
    If $Red < 0 Then $Red = 0
    If $Green < 0 Then $Green = 0
    If $Blue < 0 Then $Blue = 0
    Return ($Red * 0x10000) + ($Green * 0x100) + $Blue
EndFunc ;==>_GetDarkerColour

; Draw the pie chart
Func _DrawPie($Percentage, $Aspect, $rotation, $style = 0, $holesize = 100)
    If $style <> 0 Then $Aspect = 1
    Local $nCount, $nTotal = 0, $angleStart, $angleSweep, $X, $Y
    Local $pieLeft = $PIE_MARGIN, $pieTop = $PIE_AREA / 2 - ($PIE_DIAMETER / 2) * $Aspect
    Local $pieWidth = $PIE_DIAMETER, $pieHeight = $PIE_DIAMETER * $Aspect, $hPath

; Total up the values
    For $nCount = 0 To UBound($Percentage) - 1
        $nTotal += $Percentage[$nCount]
    Next

; Set the fractional values
    For $nCount = 0 To UBound($Percentage) - 1
        $Percentage[$nCount] /= $nTotal
    Next

; Make sure we don't over-rotate
    $rotation = Mod($rotation, 360)

; Clear the graphics buffer
    _GDIPlus_GraphicsClear($hBuffer, 0xffc0c0c0)

; Set the initial angles based on the fractional values
    Local $Angles[UBound($Percentage) + 1]
    For $nCount = 0 To UBound($Percentage)
        If $nCount = 0 Then
            $Angles[$nCount] = $rotation
        Else
            $Angles[$nCount] = $Angles[$nCount - 1] + ($Percentage[$nCount - 1] * 360)
        EndIf
    Next

    Switch $style
        Case 0

    ; Adjust the angles based on the aspect
            For $nCount = 0 To UBound($Percentage)
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $PIE_DIAMETER * Sin($Angles[$nCount] * $PI / 180)
                $Y -= ($PIE_DIAMETER - $pieHeight) * Sin($Angles[$nCount] * $PI / 180)
                If $X = 0 Then
                    $Angles[$nCount] = 90 + ($Y < 0) * 180
                Else
                    $Angles[$nCount] = ATan($Y / $X) * 180 / $PI
                EndIf
                If $X < 0 Then $Angles[$nCount] += 180
                If $X >= 0 And $Y < 0 Then $Angles[$nCount] += 360
                $X = $PIE_DIAMETER * Cos($Angles[$nCount] * $PI / 180)
                $Y = $pieHeight * Sin($Angles[$nCount] * $PI / 180)
            Next

    ; Decide which pieces to draw first and last
            Local $nStart = -1, $nEnd = -1
            For $nCount = 0 To UBound($Percentage) - 1
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)
                If $angleStart <= 270 And ($angleStart + $angleSweep) >= 270 Then
                    $nStart = $nCount
                EndIf
                If ($angleStart <= 90 And ($angleStart + $angleSweep) >= 90) _
                        Or ($angleStart <= 450 And ($angleStart + $angleSweep) >= 450) Then
                    $nEnd = $nCount
                EndIf
                If $nEnd >= 0 And $nStart >= 0 Then ExitLoop
            Next

    ; Draw the first piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nStart, $Angles)

    ; Draw pieces "to the right"
            $nCount = Mod($nStart + 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + 1, UBound($Percentage))
            WEnd

    ; Draw pieces "to the left"
            $nCount = Mod($nStart + UBound($Percentage) - 1, UBound($Percentage))
            While $nCount <> $nEnd
                _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nCount, $Angles)
                $nCount = Mod($nCount + UBound($Percentage) - 1, UBound($Percentage))
            WEnd

    ; Draw the last piece
            _DrawPiePiece($hBuffer, $pieLeft, $pieTop, $pieWidth, $pieHeight, $PIE_DEPTH * (1 - $Aspect), $nEnd, $Angles)
        Case 1
    ; Draw the donut pieces
            For $nCount = 0 To UBound($Percentage) - 1
                $angleStart = Mod($Angles[$nCount], 360)
                $angleSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

        ; Draw the outer arc in a darker colour
                $hPath = _GDIPlus_PathCreate()
                _GDIPlus_PathAddArc($hPath, $pieLeft, $pieTop, $pieWidth, $pieHeight, $angleStart, $angleSweep)
                _GDIPlus_PathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_PathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $hPath, $ahBrush[$nCount][1])
                _GDIPlus_GraphicsDrawPath($hBuffer, $hPath, $ahPen[$nCount])
                _GDIPlus_PathDispose($hPath)

        ; Draw the inner piece in a lighter colour - leave room for the hole
                $hPath = _GDIPlus_PathCreate()
                _GDIPlus_PathAddArc($hPath, $pieLeft + $PIE_MARGIN, $pieTop + $PIE_MARGIN, $pieWidth - $PIE_MARGIN * 2, _
                        $pieHeight - $PIE_MARGIN * 2, $angleStart, $angleSweep)
                _GDIPlus_PathAddArc($hPath, $pieLeft + ($PIE_DIAMETER - $holesize) / 2, $pieTop + ($PIE_DIAMETER - $holesize) / 2, _
                        $holesize, $holesize, $angleStart + $angleSweep, -$angleSweep)
                _GDIPlus_PathCloseFigure($hPath)
                _GDIPlus_GraphicsFillPath($hBuffer, $hPath, $ahBrush[$nCount][0])
                _GDIPlus_GraphicsDrawPath($hBuffer, $hPath, $ahPen[$nCount])
                _GDIPlus_PathDispose($hPath)
            Next
    EndSwitch

; Now draw the bitmap on to the device context of the window
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
EndFunc ;==>_DrawPie

Func _OnNotify($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Switch $hWndFrom
        Case $hSlideAspect, $hSlideRotation, $hStyle, $hHoleSize
    ; Update the pie chart
            _DrawPie($aChartValue, _GUICtrlSlider_GetPos($hSlideAspect) / 100, _
                    _GUICtrlSlider_GetPos($hSlideRotation), _
                    (GUICtrlRead($cStyle) = $GUI_CHECKED), _
                    _GUICtrlSlider_GetPos($hHoleSize))
    EndSwitch
EndFunc ;==>_OnNotify

Func _DrawPiePiece($hGraphics, $iX, $iY, $iWidth, $iHeight, $iDepth, $nCount, $Angles)
    Local $hPath, $cX = $iX + ($iWidth / 2), $cY = $iY + ($iHeight / 2), $fDrawn = False
    Local $iStart = Mod($Angles[$nCount], 360), $iSweep = Mod($Angles[$nCount + 1] - $Angles[$nCount] + 360, 360)

; Draw side
    ConsoleWrite(_Now() & @CRLF)
    $hPath = _GDIPlus_PathCreate()
    If $iStart < 180 And ($iStart + $iSweep > 180) Then
        _GDIPlus_PathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, 180 - $iStart)
        _GDIPlus_PathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, 180, $iStart - 180)
        _GDIPlus_PathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $hPath, $ahBrush[$nCount][1])
        _GDIPlus_GraphicsDrawPath($hGraphics, $hPath, $ahPen[$nCount])
        $fDrawn = True
    EndIf
    If $iStart + $iSweep > 360 Then
        _GDIPlus_PathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, 0, $iStart + $iSweep - 360)
        _GDIPlus_PathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep - 360, 360 - $iStart - $iSweep)
        _GDIPlus_PathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $hPath, $ahBrush[$nCount][1])
        _GDIPlus_GraphicsDrawPath($hGraphics, $hPath, $ahPen[$nCount])
        $fDrawn = True
    EndIf
    If $iStart < 180 And (Not $fDrawn) Then
        _GDIPlus_PathAddArc($hPath, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep)
        _GDIPlus_PathAddArc($hPath, $iX, $iY + $iDepth, $iWidth, $iHeight, $iStart + $iSweep, -$iSweep)
        _GDIPlus_PathCloseFigure($hPath)
        _GDIPlus_GraphicsFillPath($hGraphics, $hPath, $ahBrush[$nCount][1])
        _GDIPlus_GraphicsDrawPath($hGraphics, $hPath, $ahPen[$nCount])
    EndIf
    _GDIPlus_PathDispose($hPath)

; Draw top
    _GDIPlus_GraphicsFillPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahBrush[$nCount][0])
    _GDIPlus_GraphicsDrawPie($hGraphics, $iX, $iY, $iWidth, $iHeight, $iStart, $iSweep, $ahPen[$nCount])

EndFunc ;==>_DrawPiePiece

thanks.

Edited by whopacha
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...