﻿; Date: 08.03.2018

#Region ;************ Includes ************
#include-once
#include <GDIPlus.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#EndRegion ;************ Includes ************

Global Const $PE_NOTEXT = 0, $PE_TEXT = 1, $PE_TEXTVERTICAL = 2, $PE_VERTICAL = 4
Global Const $PE_AppDPI = RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'AppliedDPI')

If $__g_hGDIPDll = 0 Then
	_GDIPlus_Startup()
	OnAutoItExitRegister('__ProgressEx_Exit')
EndIf

Func __ProgressEx_Exit()
	_GDIPlus_Shutdown()
EndFunc

;===============================================================================
; Function Name:   _ProgressEx_Create($iLeft, $iTop, $iWidth, $iHeight[, $iStyle])
; Description:     Erstellt eine horizontale oder vertikale Progressbar
;                  ohne oder mit Prozentanzeige in auswaehlbarer Farbe
; Parameter(s):    $iLeft, $iTop = Gui-Koordinaten
;                  $iWidth, $iHeight = Breite und Hoehe
;                  $iStyle (Kombination aus folgenden Werten):
;                     $PE_NOTEXT = Prozentanzeige nicht vorhanden
;                     $PE_TEXT = Prozentanzeige vorhanden
;                     $PE_TEXTVERTICAL = Prozentanzeige vertikal ausrichten
;                     $PE_VERTICAL = Progressbar vertikal ausrichten
; Requirement(s):  obige Includes
; Return Value(s): Im Erfolgsfall ein Array, mit dem die anderen Funktionen aufgerufen werden
;                  Ansonsten: @error = 1 (Es konnte kein Pic-Control erstellt werden)
; Author(s):       Oscar  (www.autoit.de)
;===============================================================================
Func _ProgressEx_Create($iLeft, $iTop, $iWidth, $iHeight, $iStyle = $PE_NOTEXT)
	Local $aProgress[4], $hColorBitmap, $hColorGfx, $hGreyBitmap, $hGrayGfx, $hPen, $iColor, $iGrey
	Local Const $fDegToRad = 3.14159265358979 / 180
	$aProgress[0] = GUICtrlCreatePic('', $iLeft, $iTop, $iWidth, $iHeight)
	If $aProgress[0] = 0 Then Return SetError(1, 0, 0)
	$hColorBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
	$hColorGfx = _GDIPlus_ImageGetGraphicsContext($hColorBitmap)
	_GDIPlus_GraphicsClear($hColorGfx, 0xFF000000)
	$hGreyBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
	$hGrayGfx = _GDIPlus_ImageGetGraphicsContext($hGreyBitmap)
	_GDIPlus_GraphicsClear($hGrayGfx, 0xFF000000)
	$hPen = _GDIPlus_PenCreate(0xFF000000, 1)
	If BitAND($iStyle, $PE_VERTICAL) Then
		For $iLine = 0 To $iWidth - 1
			$iColor = Int(255 * Sin($iLine * (180 / $iWidth) * $fDegToRad)) * 256 * 256
			$iGrey = 0
			For $i = 0 To 2
				$iGrey += Int(245 * Sin($iLine * (180 / $iWidth) * $fDegToRad)) * 256 ^ $i
			Next
			_GDIPlus_PenSetColor($hPen, 0xFF000000 + $iColor)
			_GDIPlus_GraphicsDrawLine($hColorGfx, $iLine, 0, $iLine, $iHeight, $hPen)
			_GDIPlus_PenSetColor($hPen, 0xFF000000 + $iGrey)
			_GDIPlus_GraphicsDrawLine($hGrayGfx, $iLine, 0, $iLine, $iHeight, $hPen)
		Next
	Else
		For $iLine = 0 To $iHeight - 1
			$iColor = Int(255 * Sin($iLine * (180 / $iHeight) * $fDegToRad)) * 256 * 256
			$iGrey = 0
			For $i = 0 To 2
				$iGrey += Int(245 * Sin($iLine * (180 / $iHeight) * $fDegToRad)) * 256 ^ $i
			Next
			_GDIPlus_PenSetColor($hPen, 0xFF000000 + $iColor)
			_GDIPlus_GraphicsDrawLine($hColorGfx, 0, $iLine, $iWidth, $iLine, $hPen)
			_GDIPlus_PenSetColor($hPen, 0xFF000000 + $iGrey)
			_GDIPlus_GraphicsDrawLine($hGrayGfx, 0, $iLine, $iWidth, $iLine, $hPen)
		Next
	EndIf
	$aProgress[1] = $hGreyBitmap
	$aProgress[2] = $hColorBitmap
	$aProgress[3] = $iStyle
	_ProgressEx_SetData($aProgress, 0)
	_GDIPlus_PenDispose($hPen)
	_GDIPlus_GraphicsDispose($hGrayGfx)
	_GDIPlus_GraphicsDispose($hColorGfx)
	Return $aProgress
EndFunc

;===============================================================================
; Function Name:   _ProgressEx_SetData($aProgress, $fValue[, $iHue])
; Description:     Mit dieser Funktion kann man die Progressbar fuellen
;                  und/oder die Farbe aendern.
; Parameter(s):    $aProgress = ist das Rueckgabe-Array von "_ProgressEx_Create"
;                  $fValue = ist der Prozentwert (Kommawerte moeglich)
;                  $iHue = ist der Farbwert (-180 bis +180)
; Requirement(s):  obige Includes
; Return Value(s): Im Erfolgsfall wird "1" zurueckgegeben
;                  Ansonsten:
;                     @error = 1 ($aProgress ist kein Array)
;                     @error = 2 ($aProgress ist ein falsches Array)
;                     @error = 3 ("_GDIPlus_ImageGetDimension" ist fehlgeschlagen)
; Author(s):       Oscar  (www.autoit.de)
;===============================================================================
Func _ProgressEx_SetData(ByRef $aProgress, $fValue, $iHue = 0)
	Local $aDim, $hBitmap, $hGraphic, $hClone, $hEffect, $hBMP, $iFontSize
	Local $hBrush, $hFamily, $hFont, $tLayout, $hStringFormat
	If Not IsArray($aProgress) Then Return SetError(1, 0, 0)
	If UBound($aProgress) <> 4 Then Return SetError(2, 0, 0)
	If $fValue < 0 Then $fValue = 0
	If $fValue > 100 Then $fValue = 100
	If $iHue < -180 Then $iHue = -180
	If $iHue > 180 Then $iHue = 180
	$aDim = _GDIPlus_ImageGetDimension($aProgress[1])
	If @error Then Return SetError(3, @extended, 0)
	$hBitmap = _GDIPlus_BitmapCreateFromScan0($aDim[0], $aDim[1])
	$hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap)
	_GDIPlus_GraphicsSetSmoothingMode($hGraphic, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
	_GDIPlus_GraphicsSetTextRenderingHint($hGraphic, 4)
	_GDIPlus_GraphicsDrawImage($hGraphic, $aProgress[1], 0, 0)
	$hClone = _GDIPlus_BitmapCloneArea($aProgress[2], 0, 0, $aDim[0], $aDim[1])
	If $iHue <> 0 Then
		$hEffect = _GDIPlus_EffectCreateHueSaturationLightness($iHue,0,-10);Grün wird dunkler Rot bleibt unverändert
		_GDIPlus_BitmapApplyEffect($hClone, $hEffect)
	EndIf
	If BitAND($aProgress[3], $PE_VERTICAL) Then
		_GDIPlus_GraphicsDrawImageRect($hGraphic, $hClone, 0, $aDim[1] - ($aDim[1] / 100 * $fValue), $aDim[0], $aDim[1])
		$iFontSize = Int($aDim[0] / (BitAND($aProgress[3], $PE_TEXTVERTICAL) ? 3 : 6))
	Else
		_GDIPlus_GraphicsDrawImageRect($hGraphic, $hClone, 0, 0, $aDim[0] / 100 * $fValue, $aDim[1])
		$iFontSize = Int($aDim[1] / 3)
	EndIf
	$hBrush = _GDIPlus_BrushCreateSolid(0xFF000000)
	$hFamily = _GDIPlus_FontFamilyCreate('Tahoma')
	$hFont = _GDIPlus_FontCreate($hFamily, $iFontSize / $PE_AppDPI * 96)
	$tLayout = _GDIPlus_RectFCreate(0, 0, $aDim[0], $aDim[1])
	$hStringFormat = _GDIPlus_StringFormatCreate((BitAND($aProgress[3], $PE_TEXTVERTICAL) ? 0x0002 : 0))
	_GDIPlus_StringFormatSetAlign($hStringFormat, 1)
	_GDIPlus_StringFormatSetLineAlign($hStringFormat, 1)
	If BitAND($aProgress[3], $PE_TEXT) Or BitAND($aProgress[3], $PE_TEXTVERTICAL) Then
		_GDIPlus_GraphicsDrawStringEx($hGraphic, StringFormat('%i%', $fValue), $hFont, $tLayout, $hStringFormat, $hBrush)
	EndIf
	$hBMP = _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
	_WinAPI_DeleteObject(GUICtrlSendMsg($aProgress[0], $STM_SETIMAGE, $IMAGE_BITMAP, $hBMP))
	_WinAPI_DeleteObject($hBMP)
	If $hEffect Then _GDIPlus_EffectDispose($hEffect)
	_GDIPlus_BrushDispose($hBrush)
	_GDIPlus_FontFamilyDispose($hFamily)
	_GDIPlus_FontDispose($hFont)
	_GDIPlus_StringFormatDispose($hStringFormat)
	_GDIPlus_GraphicsDispose($hGraphic)
	_GDIPlus_BitmapDispose($hClone)
	_GDIPlus_BitmapDispose($hBitmap)
	Return 1
EndFunc

;===============================================================================
; Function Name:   _ProgressEx_Delete($aProgress)
; Description:     Mit dieser Funktion kann man die Progressbar wieder entfernen.
;                  Achtung!
;                  Damit die verwendeten Bitmaps wieder freigegeben werden, ist
;                  es erforderlich, dass diese Funktion vor dem loeschen der GUI
;                  fuer jede erstellte Progressbar aufgerufen wird!
; Parameter(s):    $aProgress = ist das Rueckgabe-Array von "_ProgressEx_Create"
; Requirement(s):  obige Includes
; Return Value(s): Im Erfolgsfall wird "1" zurueckgegeben
;                  Ansonsten:
;                     @error = 1 ($aProgress ist kein Array)
;                     @error = 2 ($aProgress ist ein falsches Array)
; Author(s):       Oscar  (www.autoit.de)
;===============================================================================
Func _ProgressEx_Delete(ByRef $aProgress)
	If Not IsArray($aProgress) Then Return SetError(1, 0, 0)
	If UBound($aProgress) <> 4 Then Return SetError(2, 0, 0)
	GUICtrlDelete($aProgress[0])
	_GDIPlus_BitmapDispose($aProgress[1])
	_GDIPlus_BitmapDispose($aProgress[2])
	$aProgress = 0
	Return 1
EndFunc
