#include-once
#include <GUIConstantsEx.au3>
#include <GuiStatusBar.au3>
#include <InetConstants.au3>
#include <StaticConstants.au3>
#include <WinAPIMisc.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>

; #INDEX# ======================================================================
; Title .........: _DownloadWithProgress
; AutoIt Version : 3.3.12.0 oder höher
; Date ..........: 25.09.2014
; Language ......: Deutsch/English
; Description ...: Download einer Datei aus dem Internet mit Progressbar und zusätzlichen Infos
; Author(s) .....: Oscar (www.autoit.de)
;===============================================================================

;===============================================================================
; Funktion        :  _DownloadWithProgress($sURL[, $sDownloadDir][, $sTitle][, $iLeft][, $iTop][, $hParent])
; Beschreibung    :  Download einer Datei aus dem Internet mit Progressbar und zusätzlichen Infos
; Parameter       :  $sURL = die komplette URL zu der Datei
;                    $sDownloadDir = das Verzeichnis, in das die Datei heruntergeladen werden soll (muss existieren!)
;                    $iLanguage = Language-Code (1031 = deutsch, 1033 = english)
;                    $sTitle = Fenstertitel
;                    $iLeft und $iTop = Position für das Fenster
;                    $hParent = Handle zum Parentfenster
;                    $iShowButtonMode (Default = 0)
;                       0 = Keine Buttons angezeigen
;                       1 = Button [Download abbrechen] wird angezeigt
;                       2 = Button [Fenster schließen] wird angezeigt
;                       3 = Button [Download abbrechen] und [Fenster schließen] angezeigen
;
; Return Value(s) : im Fehlerfall wird @error gesetzt und kann folgende Werte annehmen :
;                       1 = $sURL ist ein Leerstring
;                       2 = das Downloadverzeichnis existiert nicht
;                       3 = der Download wurde vom Benutzer abgebrochen
;                       4 = während des Downloads ist ein Fehler aufgetreten
;                       5 = der Speicherplatz auf dem Datenträger reicht nicht
;                       6 = die Dateigröße konnte nicht ermittelt werden
; Author(s):       Oscar (www.autoit.de)
;                    (GDI+ Variante der Progressbar von @UEZ)
;===============================================================================
;
Func _DownloadWithProgress($sURL, $sDownloadDir = @ScriptDir, $iLanguage = @OSLang, $sTitle = 'Download', $iLeft = -1, $iTop = -1, $hParent = 0, $iShowButtonMode = 0)
	If $sURL = '' Then Return SetError(1, 0, 0)
	If StringRight($sDownloadDir, 1) <> '\' Then $sDownloadDir &= '\'
	If Not FileExists($sDownloadDir) Then Return SetError(2, 0, 0)
	HttpSetUserAgent('Downloadmanager')
	Local $iOldEventMode = Opt('GUIOnEventMode', 0)
	_GDIPlus_Startup()
	If Not $hParent Then TraySetState(2)
	Local $iDownloadSize = 0, $aDownloadData, $iTimer = TimerInit(), $iError = 0, $iPercent = 0, $hDownload
	Local $iDownSpeedTimer = TimerInit(), $iDownSpeed = 0, $iRestTime = 0, $iOldTime = 0, $sDownloadFile = ''
	If $iLanguage = Default Or $iLanguage = -1 Then $iLanguage = @OSLang
	Local $aLanguage = _DWP_GetLanguage($iLanguage)
	Local $hGui = GUICreate($sTitle, 400, 240, $iLeft, $iTop, -1, -1, $hParent)

	GUISetFont(10, 400, 0, 'Arial', $hGui, 5)
	GUISetBkColor(0xD9DBDA, $hGui)

; Original -> falls der Dateiname zu lang ist, dann wird er nicht angezeigt :
;~ 	GUICtrlCreateGroup('', 10, 5, 380, 165)
;~ 	GUICtrlCreateLabel(StringFormat('%s "%s"', $aLanguage[0], StringRegExpReplace($sURL, '.+\/(.+)', '$1')), 25, 22, 350, 20)
;~ 	GUICtrlSetFont(-1, 12, 400, 0, 'Arial', 5)
; *** modfiziert : Anzeige des Dateinamens in kleiner Schrift :
	GUICtrlCreateGroup('', 10, 5, 380, 165)
	GUICtrlCreateLabel(StringFormat('%s "%s"', $aLanguage[0], StringRegExpReplace($sURL, '.+\/(.+)', '$1')), 25, 22, 350, 20)
	GUICtrlSetFont(-1, 9, 400, 0, 'Arial', 5)


	GUICtrlCreateLabel($aLanguage[1], 25, 50, 170, 16)
	Local $idDownloadSize = GUICtrlCreateLabel('', 200, 50, 170, 16)
	GUICtrlCreateLabel($aLanguage[2], 25, 70, 170, 16)
	Local $idDownloadSpeed = GUICtrlCreateLabel('', 200, 70, 170, 16)
	GUICtrlCreateLabel($aLanguage[3], 25, 90, 170, 16)
	Local $idDownloadTime = GUICtrlCreateLabel('', 200, 90, 170, 16)
	GUICtrlCreateLabel($aLanguage[4], 25, 110, 170, 16)
		Local $idRestTime = GUICtrlCreateLabel('', 200, 110, 170, 16)
	Local $iW = 360, $iH = 24, $iBGColor = 0xFEFEFE, $hHBmp_BG, $hB, $iSleep
	Local $idProgress = GUICtrlCreatePic('', 20, 138, $iW, $iH)

	Local $aColors[8][2] = [[0xFFEE5F5B, 0xFFF07673], _
	                        [0xFF57D338, 0xFF57D338], _
							[0xFF13558F, 0xFF13558F], _
							[0xFF6689BD, 0xFF6689BD], _
							[0xFFFFBB58, 0xFFFFC97A], _
							[0xFFFF6677, 0xFFFF8795], _
							[0xFF78CCEE, 0xFFFFC97A], _
							[0xFF78CCEE, 0xFFE8E5D9]]

	$hHBmp_BG = _GDIPlus_StripProgressbar($iPercent, $iW, $iH, 0xFF000000 + $iBGColor, $aColors[3][0], $aColors[3][1], '')
	$hB = GUICtrlSendMsg($idProgress, 0x0172, $IMAGE_BITMAP, $hHBmp_BG)
	If $hB Then _WinAPI_DeleteObject($hB)
	_WinAPI_DeleteObject($hHBmp_BG)

	GUICtrlCreateGroup('', -99, -99, 1, 1)

	Local $idCancelButton = GUICtrlCreateButton($aLanguage[5], 100, 180, 180, 28)
	GUICtrlSetState($idCancelButton, $GUI_HIDE)
	If ($iShowButtonMode == 1) Or ($iShowButtonMode == 3) Then GUICtrlSetState($idCancelButton, $GUI_SHOW)

	Local $hStatus = _GUICtrlStatusBar_Create($hGui)
	_GUICtrlStatusBar_SetText($hStatus, $aLanguage[6])

	GUISetState(@SW_SHOW, $hGui)
	Local $iDriveSpaceFree = DriveSpaceFree($sDownloadDir) * 2 ^ 20
	Local $iFileSize = InetGetSize($sURL)
	If Not @error Then
		If $iDriveSpaceFree > $iFileSize Then
			_GUICtrlStatusBar_SetText($hStatus, $aLanguage[7])
			$iDownSpeedTimer = TimerInit()
			GUICtrlSetData($idDownloadSize, StringFormat('%s / %s', _WinAPI_StrFormatByteSize($iDownloadSize), _WinAPI_StrFormatByteSize($iFileSize)))
			GUICtrlSetData($idDownloadSpeed, StringFormat('%s/s', $iDownSpeed))
			$sDownloadFile = $sDownloadDir & StringRegExpReplace($sURL, '.+\/(.+)', '$1')

			$hDownload = InetGet($sURL, $sDownloadFile, BitOR($INET_FORCERELOAD, $INET_FORCEBYPASS), 1) ; *** geändert : statt 1

			$iSleep = TimerInit()
			Do
				Switch GUIGetMsg()
					Case $idCancelButton
						$iError = 3
						ExitLoop
					Case $GUI_EVENT_CLOSE
						InetClose($hDownload)
						If FileExists($sDownloadFile) Then FileDelete($sDownloadFile)
						HttpSetUserAgent('')
						Opt('GUIOnEventMode', $iOldEventMode)
						GUIDelete($hGui)
						_GDIPlus_Shutdown()
						Return SetError(3, 0, 0)
				EndSwitch
				$aDownloadData = InetGetInfo($hDownload)
				If $aDownloadData[$INET_DOWNLOADERROR] Then
					$iError = 4
					ExitLoop
				EndIf
				$iDownloadSize = $aDownloadData[$INET_DOWNLOADREAD]
				If TimerDiff($iTimer) > 250 Then
					$iDownSpeed = _WinAPI_StrFormatByteSize($iDownloadSize / TimerDiff($iDownSpeedTimer) * 1000)
					$iTimer = TimerInit()
					$iPercent = Int(100 / $iFileSize * $iDownloadSize)
					GUICtrlSetData($idDownloadSize, StringFormat('%s / %s', _WinAPI_StrFormatByteSize($iDownloadSize), _WinAPI_StrFormatByteSize($iFileSize)))
					GUICtrlSetData($idDownloadSpeed, StringFormat('%s/s', $iDownSpeed))
					GUICtrlSetData($idDownloadTime, StringFormat('%s', _WinAPI_StrFromTimeInterval(TimerDiff($iDownSpeedTimer))))
					$iRestTime = ($iFileSize - $iDownloadSize) / ($iDownloadSize / TimerDiff($iDownSpeedTimer))
					If $iRestTime <> $iOldTime Then
						$iOldTime = $iRestTime
						GUICtrlSetData($idRestTime, StringFormat('%s', _WinAPI_StrFromTimeInterval($iRestTime)))
					EndIf
				EndIf
				If TimerDiff($iSleep) > 50 Then
					$hHBmp_BG = _GDIPlus_StripProgressbar($iPercent, $iW, $iH, 0xFF000000 + $iBGColor, $aColors[3][0], $aColors[3][1], $iPercent & '%')
					$hB = GUICtrlSendMsg($idProgress, 0x0172, $IMAGE_BITMAP, $hHBmp_BG)
					If $hB Then _WinAPI_DeleteObject($hB)
					_WinAPI_DeleteObject($hHBmp_BG)
					$iSleep = TimerInit()
				EndIf
			Until $aDownloadData[$INET_DOWNLOADCOMPLETE]

			InetClose($hDownload)
			If $iError Then
				If FileExists($sDownloadFile) Then FileDelete($sDownloadFile)
				$hHBmp_BG = _GDIPlus_StripProgressbar($iPercent, $iW, $iH, 0xFF000000 + $iBGColor, $aColors[3][0], $aColors[3][1], $iPercent & '%')
				_GUICtrlStatusBar_SetText($hStatus, $aLanguage[8])
			Else
				$hHBmp_BG = _GDIPlus_StripProgressbar(100, $iW, $iH, 0xFF000000 + $iBGColor, $aColors[3][0], $aColors[3][1], '100%')
				GUICtrlSetData($idDownloadSize, StringFormat('%s / %s', _WinAPI_StrFormatByteSize($iDownloadSize), _WinAPI_StrFormatByteSize($iFileSize)))
				GUICtrlSetData($idDownloadSpeed, StringFormat('%s/s', $iDownSpeed))
				_GUICtrlStatusBar_SetText($hStatus, $aLanguage[9])
			EndIf
			$hB = GUICtrlSendMsg($idProgress, 0x0172, $IMAGE_BITMAP, $hHBmp_BG)
			If $hB Then _WinAPI_DeleteObject($hB)
			_WinAPI_DeleteObject($hHBmp_BG)
		Else
			$iError = 5
			_GUICtrlStatusBar_SetText($hStatus, $aLanguage[10])
		EndIf
	Else
		$iError = 6
		_GUICtrlStatusBar_SetText($hStatus, $aLanguage[11])
	EndIf

	GUICtrlSetData($idCancelButton, $aLanguage[12])
	GUICtrlSetState($idCancelButton, $GUI_HIDE)
	If ($iShowButtonMode == 2) Or ($iShowButtonMode == 3) Then
		GUICtrlSetState($idCancelButton, $GUI_SHOW)
		While True
			Switch GUIGetMsg()
				Case $idCancelButton, $GUI_EVENT_CLOSE
					HttpSetUserAgent('')
					Opt('GUIOnEventMode', $iOldEventMode)
					GUIDelete($hGui)
					_GDIPlus_Shutdown()
					Return SetError($iError, 0, 0)
			EndSwitch
		WEnd
	Else
		HttpSetUserAgent('')
		Opt('GUIOnEventMode', $iOldEventMode)
		GUIDelete($hGui)
		_GDIPlus_Shutdown()
		Return SetError($iError, 0, 0)
	EndIf
EndFunc   ;==>_DownloadWithProgress

Func _DWP_GetLanguage($iLanguage)
	Local $aLanguage[13]
	Switch $iLanguage
		Case 1031 ; deutsch
			$aLanguage[0] = 'Dateiname:'
			$aLanguage[1] = 'Dateigröße:'
			$aLanguage[2] = 'Geschwindigkeit:'
			$aLanguage[3] = 'Downloadzeit:'
			$aLanguage[4] = 'Restzeit (geschätzt):'
			$aLanguage[5] = 'Download abbrechen'
			$aLanguage[6] = 'Dateigröße wird ermittelt! Bitte warten...'
			$aLanguage[7] = 'Datei wird heruntergeladen...'
			$aLanguage[8] = 'Download abgebrochen!'
			$aLanguage[9] = 'Download abgeschlossen!'
			$aLanguage[10] = 'Fehler! Nicht genug Platz auf dem Datenträger!'
			$aLanguage[11] = 'Fehler! Dateigröße konnte nicht ermittelt werden!'
			$aLanguage[12] = 'Fenster schließen'
		Case Else ; english
			$aLanguage[0] = 'Filename:'
			$aLanguage[1] = 'Filesize:'
			$aLanguage[2] = 'Downloadrate:'
			$aLanguage[3] = 'Downloadtime:'
			$aLanguage[4] = 'Remaining time (estimated):'
			$aLanguage[5] = 'Cancel Download'
			$aLanguage[6] = 'Calculate Filesize! Please wait...'
			$aLanguage[7] = 'Download File...'
			$aLanguage[8] = 'Download canceled!'
			$aLanguage[9] = 'Download completed!'
			$aLanguage[10] = 'Error! Not enough free space on disk!'
			$aLanguage[11] = 'Error! Cannot calculate filesize!'
			$aLanguage[12] = 'Close Window'
	EndSwitch
	Return $aLanguage
EndFunc   ;==>_DWP_GetLanguage

Func _GDIPlus_StripProgressbar($fPerc, $iW, $iH, $iBgColorGui = 0xFFF0F0F0, $iFgColor = 0xFFEE5F5B, $iBGColor = 0xFFF07673, $sText = 'Loading...', $iTextColor = 0x000000, $iDir = -1, $iSpeed = 1, $sFont = 'Arial', $bFlip = False, $bHBitmap = True)

	$fPerc = $fPerc < 0 ? 0 : $fPerc
	$fPerc = $fPerc > 100 ? 100 : $fPerc

	Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
	Local Const $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
	_GDIPlus_GraphicsSetPixelOffsetMode($hCtxt, $GDIP_PIXELOFFSETMODE_HIGHQUALITY)
	_GDIPlus_GraphicsClear($hCtxt, $iBgColorGui)

	Local $iWidth = $iH * 2, $iLen = $iWidth / 2, $iY
	Local $hBmp = _GDIPlus_BitmapCreateFromScan0($iWidth, $iH)
	Local Const $hCtxt_Bmp = _GDIPlus_ImageGetGraphicsContext($hBmp)
	_GDIPlus_GraphicsSetPixelOffsetMode($hCtxt_Bmp, $GDIP_PIXELOFFSETMODE_HIGHQUALITY)
	Local $hPen = _GDIPlus_PenCreate($iFgColor), $iPenSize = Int($iH / 12)
	Local $hPen2 = _GDIPlus_PenCreate(0x50000000, $iPenSize)

	_GDIPlus_GraphicsClear($hCtxt_Bmp, $iBGColor)
	Local Static $iX = 0
	For $iY = 0 To $iH - 1
		Switch $iDir
			Case 1
				_GDIPlus_GraphicsDrawLine($hCtxt_Bmp, $iX + $iY, $iY, $iX + $iY + $iLen, $iY, $hPen)
				_GDIPlus_GraphicsDrawLine($hCtxt_Bmp, $iX + $iY - 2 * $iLen, $iY, $iX + $iY - 1 * $iLen, $iY, $hPen)
			Case Else
				_GDIPlus_GraphicsDrawLine($hCtxt_Bmp, -$iX + $iY, $iY, -$iX + $iY + $iLen, $iY, $hPen)
				_GDIPlus_GraphicsDrawLine($hCtxt_Bmp, -$iX + $iY + 2 * $iLen, $iY, -$iX + $iY + 3 * $iLen, $iY, $hPen)
		EndSwitch
	Next
	Local $tPoint1 = DllStructCreate('float;float')
	Local $tPoint2 = DllStructCreate('float;float')
	DllStructSetData($tPoint1, 1, $iW / 2) ;x1
	DllStructSetData($tPoint2, 1, $iW / 2) ;x2
	Local $hLineBrush

	If $bFlip Then
		_GDIPlus_GraphicsDrawLine($hCtxt_Bmp, 0, 0, $iWidth, 0, $hPen2)
		DllStructSetData($tPoint1, 2, $iH / 3) ;y1
		DllStructSetData($tPoint2, 2, $iH * 2 / 3) ;y2
		$hLineBrush = DllCall($__g_hGDIPDll, 'uint', 'GdipCreateLineBrush', 'struct*', $tPoint1, 'struct*', $tPoint2, 'uint', 0x00FFFFFF, 'uint', 0xB0FFFFFF, 'int', 0, 'int*', 0)
		$hLineBrush = $hLineBrush[6]
		_GDIPlus_GraphicsFillRect($hCtxt_Bmp, 0, $iH * 2 / 3 + 1, $iW, $iH / 3, $hLineBrush)
	Else
		_GDIPlus_GraphicsDrawLine($hCtxt_Bmp, 0, $iH - $iPenSize / 2, $iWidth, $iH - $iPenSize / 2, $hPen2)
		DllStructSetData($tPoint1, 2, 0) ;y1
		DllStructSetData($tPoint2, 2, $iH / 3) ;y2
		$hLineBrush = DllCall($__g_hGDIPDll, 'uint', 'GdipCreateLineBrush', 'struct*', $tPoint1, 'struct*', $tPoint2, 'uint', 0xB0FFFFFF, 'uint', 0x00FFFFFF, 'int', 0, 'int*', 0)
		$hLineBrush = $hLineBrush[6]
		_GDIPlus_GraphicsFillRect($hCtxt_Bmp, 0, 0, $iW, $iH / 3, $hLineBrush)
	EndIf
	$iX = Mod($iX + $iSpeed, $iWidth)

	Local $hTextureBrush = _GDIPlus_TextureCreate($hBmp)

	_GDIPlus_GraphicsFillRect($hCtxt, 0, 0, $fPerc / 100 * $iW, $iH, $hTextureBrush)
	If $bFlip Then _GDIPlus_ImageRotateFlip($hBitmap, 6)
	_GDIPlus_GraphicsSetTextRenderingHint($hCtxt, 4)

	Local $hBrush = _GDIPlus_BrushCreateSolid(0xE0000000 + $iTextColor)
	Local $hFormat = _GDIPlus_StringFormatCreate()
	Local $hFamily = _GDIPlus_FontFamilyCreate($sFont)
	Local $hFont = _GDIPlus_FontCreate($hFamily, $iH * 3 / 7)
	Local $tLayout = _GDIPlus_RectFCreate(0, 0, $iW, $iH)
	_GDIPlus_StringFormatSetAlign($hFormat, 1)
	_GDIPlus_StringFormatSetLineAlign($hFormat, 1)
	_GDIPlus_GraphicsDrawStringEx($hCtxt, $sText, $hFont, $tLayout, $hFormat, $hBrush)

	_GDIPlus_FontDispose($hFont)
	_GDIPlus_FontFamilyDispose($hFamily)
	_GDIPlus_StringFormatDispose($hFormat)
	_GDIPlus_BrushDispose($hBrush)
	_GDIPlus_PenDispose($hPen)
	_GDIPlus_PenDispose($hPen2)
	_GDIPlus_GraphicsDispose($hCtxt)
	_GDIPlus_GraphicsDispose($hCtxt_Bmp)
	_GDIPlus_BitmapDispose($hBmp)
	_GDIPlus_BrushDispose($hTextureBrush)
	_GDIPlus_BrushDispose($hLineBrush)
	If $bHBitmap Then
		Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
		_GDIPlus_BitmapDispose($hBitmap)
		Return $hHBITMAP
	EndIf
	Return $hBitmap
EndFunc   ;==>_GDIPlus_StripProgressbar
