;Author: Kanashius@autoit.de

;WARNING
;If you Register your own $WM_PAINT Notification you need to call the Function
;__Chart_WM_PAINT($hWnd, $Msg, $wParam, $lParam) in this Function!
;If you Register your own $WM_SYSCOMMAND Notification you need to call the Function
;__Chart_WM_EXTRACTOR($hWnd, $Msg, $wParam, $lParam) in this Function!

#include <GDIplus.au3>
#include <GuiConstants.au3>
#include <WindowsConstants.au3>
#include <MenuConstants.au3>

global $__Chart_ChartArray[0],$__Chart_Gui=0
_GDIPlus_Startup()
GUIRegisterMsg($WM_PAINT, '__Chart_WM_PAINT')
GUIRegisterMsg($WM_SYSCOMMAND, "__Chart_WM_EXTRACTOR")

;===============================================================================
;
; Function Name:    __Chart_showChart()
; Description:      Draws an Chart at an Window
; Parameter(s):     $hGui	  : Handle to the Gui to draw
;					$X		  : X-Position to draw to
;					$Y		  : Y-Position to draw to
;					$Width	  : Width of the Chart
;					$Height	  : Height of the Chart
;					$Names	  : 2D Array. First Entry: Name, Second Entry: Value
;					 or $Names: 3D Array. First Entry: Name, Second Entry: Value, Third Entry: Color
;								Color: 0xAARRGGBB
;					$Entrys   : Number of Sections
;					$start	  : Startsection
;					$end	  : EndSection
;					$direction: "vert" or "hori", aso vertikal oder horizontale Ausrichtung
;					$endNull  : just set this to true if $end have to be 0
; Requirement(s):   none.
; Return Value(s):  ID of Chart
; Author(s):        Kanashius
;
;===============================================================================
Func __Chart_showChart($hGui,$X,$Y,$Width,$Height,$Names,$Entrys,$direction="vert",$start=0,$end=0,$endNull=false)
	local $gWidth=WinGetPos($hGui)[2],$gHeight=WinGetPos($hGui)[3]
	local $hGraphicBuff = _GDIPlus_GraphicsCreateFromHWND($hGui)
	local $hBitmap = _GDIPlus_BitmapCreateFromGraphics($gWidth, $gHeight, $hGraphicBuff)
	local $graphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
	local $Abstand=39
	local $Balkenbreite=15
	if $end=0 and NOT $endNull then
		for $i=0 to UBound($Names)-1 step 1
			if $end<$Names[$i][1] then
				$end=$Names[$i][1]
			endif
		next
	endif
	local $white=_GDIPlus_BrushCreateSolid(0xFFFFFFFF)
	_GDIPlus_GraphicsFillRect($graphics,$X,$Y,$Width,$Height,$white)
	if $direction="hori" then
		;Zeichne Balkennamen
		local $MaxWidth=0
		for $i=0 to UBound($Names)-1 step 1
			_GDIPlus_GraphicsDrawString($graphics,$Names[$i][0],$X+5,$Y+5+$Abstand*$i)
			local $MaxSize=__Chart_GetTextLabelWidth($Names[$i][0], "Arial", 10)
			if $MaxWidth<$MaxSize then
				$MaxWidth=$MaxSize
			endif
		next
		;Zeichne kleine Balkentrenner
		local $MaxSize=$MaxWidth+4
		local $count=0
		for $i=0 to UBound($Names)-1 step 1
			_GDIPlus_GraphicsDrawLine($graphics,$X+$MaxSize,$Y+2+$i*$Abstand,$X+$MaxSize+4,$Y+2+$i*$Abstand)
			$count+=1
		Next
		_GDIPlus_GraphicsDrawLine($graphics,$X+$MaxSize,$Y+2+$count*$Abstand,$X+$Width-20,$Y+2+$count*$Abstand)
		;Gebe Breite
		local $luecke=(($Abstand-$Balkenbreite)/2)
		local $MaxNumber=0
		for $i=0 to UBound($Names)-1 step 1
			$Names[$i][1]-=$start
			$MaxNumber=$Names[$i][1]>$MaxNumber?$Names[$i][1]:$MaxNumber
		next
		;Zeichne Balken
		local $MaxBalkenSize=($Width-(20+$MaxSize+6))/($end-$start)
		;$MaxBalkenSize-=10
		for $i=0 to UBound($Names)-1 step 1
			if $Names[$i][1]>=0 then
				local $white
				if UBound($Names,2)>2 then
					$white=_GDIPlus_BrushCreateSolid($Names[$i][2])
				else
					$white=_GDIPlus_BrushCreateSolid(0xFF4f81bd)
				endif
				_GDIPlus_GraphicsFillRect($graphics,$X+$MaxSize+6,$Y+$luecke*($i+1)+$luecke*$i+$i*$Balkenbreite,$MaxBalkenSize*$Names[$i][1],$Balkenbreite,$white)
			endif
		next
		;Zeichne Texte
		local $oneEntry=($end-$start)/$Entrys
		local $oneEntryWidth=($Width-(20+$MaxSize+5))/$Entrys
		local $MaxWidthText=0
		for $i=0 to $Entrys Step 1
			$MaxSizeTmp=__Chart_GetTextLabelWidth(Round($start+$oneEntry*$i,2), "Arial", 10)
			if $MaxWidthText<$MaxSizeTmp then
				$MaxWidthText=$MaxSizeTmp
			endif
		next
		$MaxWidthText/=2
		for $i=0 to $Entrys Step 1
			_GDIPlus_GraphicsDrawString($graphics,Round($start+$oneEntry*$i,2),$X+$MaxSize+5+$oneEntryWidth*$i-$MaxWidthText,$Y+2+$count*$Abstand+4+5)
			_GDIPlus_GraphicsDrawLine($graphics,$X+$MaxSize+5+$oneEntryWidth*$i,$Y+2,$X+$MaxSize+5+$oneEntryWidth*$i,$Y+2+$count*$Abstand+4)
		next
	else
		;Zeichne Balkennamen
		local $MaxWidth=0
		for $i=0 to UBound($Names)-1 step 1
			local $MaxSize=__Chart_GetTextLabelWidth($Names[$i][0], "Arial", 10)
			if $MaxWidth<$MaxSize then
				$MaxWidth=$MaxSize
			endif
		next
		;Zeichne Texte
		local $oneEntry=($end-$start)/$Entrys
		local $oneEntryWidth=($Height-(5)-$MaxSize-4)/($Entrys+1)
		local $MaxWidthText=0
		for $i=0 to $Entrys Step 1
			local $MaxSizeTmp=__Chart_GetTextLabelWidth(Round($start+$oneEntry*$i,2), "Arial", 10)
			if $MaxWidthText<$MaxSizeTmp then
				$MaxWidthText=$MaxSizeTmp
			endif
		next
		local $oneEntryWidthText=0;($oneEntryWidth-10)/2
		local $count=0
		for $i=0 to $Entrys Step 1
			_GDIPlus_GraphicsDrawString($graphics,Round($start+$oneEntry*$i,2),$X+5+$MaxWidthText,$Y+$oneEntryWidth*($Entrys-$i)+$oneEntryWidthText,"Arial",10,0x0001)
			_GDIPlus_GraphicsDrawLine($graphics,$X+$MaxWidthText+5,$Y+$oneEntryWidth*($Entrys-$i)+10,$X+$Width,$Y+$oneEntryWidth*($Entrys-$i)+10)
			$count+=1
		next
		_GDIPlus_GraphicsDrawLine($graphics,$X+$MaxWidthText+10,$Y+10,$X+$MaxWidthText+10,$Y+$oneEntryWidth*($count-1)+5+10)
		;Zeichne Balkennamen
		$MaxWidth=0
		local $NewNameWidth=($Width-$MaxWidthText+10)/UBound($Names)
		$NewNameWidth-=10
		for $i=0 to UBound($Names)-1 step 1
			_GDIPlus_GraphicsDrawString($graphics,$Names[$i][0],$X+$MaxWidthText+15+$NewNameWidth*$i,$Y+$oneEntryWidth*($count-1)+5+10,"Arial",10,0x0002)
			_GDIPlus_GraphicsDrawLine($graphics,$X+$MaxWidthText+10+$NewNameWidth*($i+1),$Y+$oneEntryWidth*($count-1)+10,$X+$MaxWidthText+10+$NewNameWidth*($i+1),$Y+$oneEntryWidth*($count-1)+5+10)
			local $MaxSize=__Chart_GetTextLabelWidth($Names[$i][0], "Arial", 10)
			if $MaxWidth<$MaxSize then
				$MaxWidth=$MaxSize
			endif
		next
		;Gebe Breite
		;$luecke=(($Abstand-$Balkenbreite)/2)
		local $luecke=($NewNameWidth-$Balkenbreite)/2
		local $MaxNumber=0
		for $i=0 to UBound($Names)-1 step 1
			$Names[$i][1]=$Names[$i][1]-$start-(($Names[$i][1]-$end)>0?($Names[$i][1]-$end):0)
			$MaxNumber=$Names[$i][1]>$MaxNumber?$Names[$i][1]:$MaxNumber
		next
		;Zeichne Balken
		local $MaxBalkenSize=($Height-$Y-($Height-($Y+$oneEntryWidth*($count-1))))/($end-$start)
		;msgbox(48,"","("&$Height&"-("&$Y&"+"&$oneEntryWidth&"+"&10&"))/("&$end&"-"&$start&")")
		;$MaxBalkenSize-=10
		for $i=0 to UBound($Names)-1 step 1
			if $Names[$i][1]>=0 then
				local $white
				if UBound($Names,2)>2 then
					$white=_GDIPlus_BrushCreateSolid($Names[$i][2])
				else
					$white=_GDIPlus_BrushCreateSolid(0xFF4f81bd)
				endif
				_GDIPlus_GraphicsFillRect($graphics,$X+$luecke*($i+1)+$luecke*$i+$i*$Balkenbreite+$MaxWidthText+5,$Y+10+$MaxBalkenSize*($end-$start-$Names[$i][1]),$Balkenbreite,$MaxBalkenSize*$Names[$i][1],$white)
				;_GDIPlus_GraphicsFillRect($graphics,$X+$luecke*($i+1)+$luecke*$i+$i*$Balkenbreite+$MaxWidthText+10,$Y+10+$MaxBalkenSize*($MaxNumber-$Names[$i][1]),$Balkenbreite,$MaxBalkenSize*$Names[$i][1],$white)
				;msgbox(48,"",$X+$luecke*($i+1)+$luecke*$i+$i*$Balkenbreite+$MaxWidthText+10&","&$Y&","&$Balkenbreite&","&$MaxBalkenSize*$Names[$i][1]&"  "&$MaxBalkenSize&"*"&$Names[$i][1])
			endif
		next
	endif
	_GDIPlus_GraphicsDrawImage($hGraphicBuff, $hBitmap, 0, 0)
	_GDIPlus_GraphicsDispose($graphics)
	_GDIPlus_GraphicsDispose($hGraphicBuff)
	;Aktualisiere __Chart_ChartArray
	for $i=0 to UBound($__Chart_ChartArray)-1 step 1
		if $__Chart_ChartArray[$i]="" then
			$__Chart_ChartArray[$i]=$hBitmap
			return $i
		EndIf
	next
	ReDim $__Chart_ChartArray[UBound($__Chart_ChartArray)+1]
	$__Chart_ChartArray[UBound($__Chart_ChartArray)-1]=$hBitmap
	return UBound($__Chart_ChartArray)-1
EndFunc

;===============================================================================
;
; Function Name:    __Chart_deleteChart
; Description:      Deletes an Chart
; Parameter(s):     $hGui	  : Handle to the Gui where the Chart was drawn
;					$ChartId  : ID of the Chart (returned by __Chart_showChart)
; Requirement(s):   none.
; Return Value(s):  none.
; Author(s):        Kanashius
;
;===============================================================================
Func __Chart_deleteChart($hGui,$Number)
	_GDIPlus_BitmapDispose($__Chart_ChartArray[$Number])
	$__Chart_ChartArray[$Number]=""
	_WinAPI_RedrawWindow($hGui)
	__Chart_WM_PAINT($hGui,0,0,0)
EndFunc


;======Internel Use Mostly======================================================
;
; Function Name:    __Chart_WM_PAINT
; Description:      Redraw Gui
; Parameter(s):     look GuiRegisterMsg()
; Requirement(s):   none.
; Return Value(s):  none.
; Author(s):        Kanashius
;
;===============================================================================
Func __Chart_WM_PAINT($hWnd, $Msg, $wParam, $lParam)
	local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
	for $i=0 to UBound($__Chart_ChartArray)-1 step 1
		_GDIPlus_GraphicsDrawImage($hGraphic, $__Chart_ChartArray[$i], 0, 0)
	next
EndFunc   ;==>WM_PAINT

;======Internel Use Only======================================================
;
; Function Name:    __Chart_WM_PAINT_akt
; Description:      Redraw Gui after minimize
; Parameter(s):     none.
; Requirement(s):   none.
; Return Value(s):  none.
; Author(s):        Kanashius
;
;===============================================================================
Func __Chart_WM_PAINT_akt()
	__Chart_WM_PAINT($__Chart_Gui,0,0,0)
	AdlibUnRegister("__Chart_WM_PAINT_akt")
EndFunc

;======Internel Use Only======================================================
;
; Function Name:    __Chart_WM_EXTRACTOR
; Description:      Redraw Gui after minimize
; Parameter(s):     look GuiRegisterMsg()
; Requirement(s):   none.
; Return Value(s):  none.
; Author(s):        Kanashius
;
;===============================================================================
Func __Chart_WM_EXTRACTOR($hWnd, $iMsg, $wParam, $lParam)
	Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0x0000FFFF)
    Local $hCtrl = $lParam
	if $iMsg=$WM_SYSCOMMAND then
		if $wParam=$SC_MINIMIZE or $wParam=$SC_RESTORE or $wParam=$SC_MAXIMIZE then
			$__Chart_Gui=$hWnd
			AdlibRegister("__Chart_WM_PAINT_akt",50)
		endif
	endif
EndFunc

;======Internel Use Only======================================================
;
; Function Name:    __Chart_WM_PAINT
; Description:      Give the legth of a String in Pixel
; Parameter(s):     ?
; Requirement(s):   none.
; Return Value(s):  none.
; Author(s):        b8bboi@www.autoitscript.com
;
;===============================================================================
Func __Chart_GetTextLabelWidth($s_WinText, $s_TextFont, $i_FontSize, $i_FontWeight = -1)
	Local Const $DEFAULT_CHARSET = 0 ; ANSI character set
	Local Const $OUT_CHARACTER_PRECIS = 2
	Local Const $CLIP_DEFAULT_PRECIS = 0
	Local Const $PROOF_QUALITY = 2
	Local Const $FIXED_PITCH = 1
	Local Const $RGN_XOR = 3
	Local Const $LOGPIXELSY = 90


	local $h_WinTitle = "Get Label Width"
	If $i_FontWeight = "" Or $i_FontWeight = -1 Then $i_FontWeight = 600 ; default Font weight
	Local $h_GUI = GUICreate($h_WinTitle, 10, 10, -100, -100, $WS_POPUPWINDOW, $WS_EX_TOOLWINDOW)
	Local $hDC = DllCall("user32.dll", "int", "GetDC", "hwnd", $h_GUI)

	Local $intDeviceCap = DllCall("gdi32.dll", "long", "GetDeviceCaps", "int", $hDC[0], "long", $LOGPIXELSY)
	$intDeviceCap = $intDeviceCap[0]

	Local $intFontHeight = DllCall("kernel32.dll", "long", "MulDiv", "long", $i_FontSize, "long", $intDeviceCap, "long", 72)
	$intFontHeight = -$intFontHeight[0]

	Local $hMyFont = DllCall("gdi32.dll", "hwnd", "CreateFont", "int", $intFontHeight, _
			"int", 0, "int", 0, "int", 0, "int", $i_FontWeight, "int", 0, _
			"int", 0, "int", 0, "int", $DEFAULT_CHARSET, _
			"int", $OUT_CHARACTER_PRECIS, "int", $CLIP_DEFAULT_PRECIS, _
			"int", $PROOF_QUALITY, "int", $FIXED_PITCH, "str", $s_TextFont)
	DllCall("gdi32.dll", "hwnd", "SelectObject", "int", $hDC[0], "hwnd", $hMyFont[0])

	Local $res = DllStructCreate("int;int")

	Local $ret = DllCall("gdi32.dll", "int", "GetTextExtentPoint32", "int", $hDC[0], "str", $s_WinText, "long", StringLen($s_WinText), "ptr", DllStructGetPtr($res))

	Local $intLabelWidth = DllStructGetData($res,1)

	GUIDelete($h_GUI)
	Return $intLabelWidth
EndFunc