#include <GDIPlus.au3>
#include <GUIConstants.au3>
#include <Misc.au3>
#include <Sound.au3>

Opt("MouseCoordMode", 2)

$GUIWidth = 800
$GUIHeight = 400
$iX_Line = 0
$iY_Line = 0
$iSpeed = 1
$iSpeedOld = $iSpeed
$Pause = False
$sPath = @ScriptDir & "\Sounds"

If DirGetSize($sPath) = -1 Then
    MsgBox(16, "Fehler", "Das Verzeichnis '" & $sPath & "' existiert nicht")
	Exit
EndIf
$aFiles = _GetFilesFolder_Rekursiv($sPath, "wav", 0)
If $aFiles[0] = 0 Then
    MsgBox(16, "Fehler", "Keine .wav Dateien im 'Sounds' Verzeichnis gefunden")
	Exit
EndIf

Global $aNames[$aFiles[0]]
Global $szDrive, $szDir, $szFName, $szExt

For $i = 0 To UBound($aFiles) - 2
    $aSplit = _PathSplit($aFiles[$i + 1], $szDrive, $szDir, $szFName, $szExt)
	$aNames[$i] = $aSplit[3]
Next

_GDIPlus_Startup()

$hPen = _GDIPlus_PenCreate("0x" & Hex(20, 2) & "FFFFFF", 4)
$Brush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
$hPenTrans = _GDIPlus_PenCreate(0x00FFFFFF, 4)

Global $aBlock[$aFiles[0]][6]
$X = 20
$Y = 20

For $i = 0 To $aFiles[0] - 1
	$aBlock[$i][0] = $X
    $aBlock[$i][1] = $Y
    $aBlock[$i][2] = _SoundOpen($aFiles[$i + 1])
    $aBlock[$i][3] = False
    $aBlock[$i][4] = 0
    $aBlock[$i][5] = $hPen
	$X += 40
	If $X >= $GUIWidth - 40 Then
	    $Y += 40
		$X = 20
	EndIf
Next

$hWnd = GUICreate("Test", $GUIWidth, $GUIHeight)
GUISetState()

$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($GUIWidth, $GUIHeight, $hGraphic)
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)
_GDIPlus_GraphicsClear($hGraphic)

AdlibRegister("_DrawBlocks", 20)
HotKeySet("{NUMPADADD}", "_SpeedUp")
HotKeySet("{NUMPADSUB}", "_SlowDown")
HotKeySet("{END}", "_Pause")
HotKeySet("{ESC}", "_Capture")

While 1
	$nMsg = GUIGetMsg(1)
	Switch $nMsg[0]
		Case $GUI_EVENT_CLOSE
			_GDIPlus_GraphicsDispose($hGraphic)
			_GDIPlus_GraphicsDispose($hBuffer)
			_GDIPlus_BitmapDispose($hBitmap)
			_GDIPlus_PenDispose($hPen)
			_GDIPlus_PenDispose($hPenTrans)
			_GDIPlus_BrushDispose($Brush)
			_GDIPlus_Shutdown()
			For $i = 0 To UBound($aBlock) - 1
				_SoundClose($aBlock[$i][2])
			Next
			Exit
		Case $GUI_EVENT_PRIMARYDOWN
			For $i = 0 To UBound($aBlock) - 1
				If $nMsg[3] >= $aBlock[$i][0] And $nMsg[3] <= $aBlock[$i][0] + 20 And $nMsg[4] >= $aBlock[$i][1] And $nMsg[4] <= $aBlock[$i][1] + 20 Then
					$DistanceX = $nMsg[3] - $aBlock[$i][0]
					$DistanceY = $nMsg[4] - $aBlock[$i][1]
					While _IsPressed("01")
						$aBlock[$i][0] = MouseGetPos(0) - $DistanceX
						$aBlock[$i][1] = MouseGetPos(1) - $DistanceY
						$Off = WinGetPos($hWnd)
						ToolTip($aNames[$i], $aBlock[$i][0] + $Off[0], $aBlock[$i][1] + $Off[1])
					WEnd
				EndIf
			Next
	EndSwitch
WEnd

Func _DrawBlocks()
	_GDIPlus_GraphicsClear($hBuffer)
	_GDIPlus_GraphicsDrawLine($hBuffer, Round($iX_Line), $iY_Line, Round($iX_Line), $iY_Line + $GUIHeight, $hPen)
	For $i = 0 To UBound($aBlock) - 1
		_GDIPlus_GraphicsFillRect($hBuffer, $aBlock[$i][0], $aBlock[$i][1], 20, 20, $Brush)
		_GDIPlus_GraphicsDrawEllipse($hBuffer, $aBlock[$i][0] - $aBlock[$i][4] / 2 + 10, $aBlock[$i][1] - $aBlock[$i][4] / 2 + 10, $aBlock[$i][4], $aBlock[$i][4], $aBlock[$i][5])
	Next
	_GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $GUIWidth, $GUIHeight)
	$iX_Line += $iSpeed
	If $iX_Line >= $GUIWidth Then
		$iX_Line = 0
		For $i = 0 To UBound($aBlock) - 1
			$aBlock[$i][3] = False
			$aBlock[$i][4] = 0
			$aBlock[$i][5] = $hPen
		Next
	EndIf
	For $i = 0 To UBound($aBlock) - 1
		If $iX_Line >= $aBlock[$i][0] And $aBlock[$i][3] = False Then
			$aBlock[$i][3] = True
			_SoundPlay($aBlock[$i][2])
		EndIf
	Next
	For $i = 0 To UBound($aBlock) - 1
		If $aBlock[$i][3] = True And $aBlock[$i][4] < 50 Then
			$aBlock[$i][4] += 2
		ElseIf $aBlock[$i][4] >= 50 Then
			$aBlock[$i][5] = $hPenTrans
		EndIf
	Next
EndFunc   ;==>_DrawBlocks

Func _SpeedUp()
	$iSpeed += 0.1
EndFunc

Func _SlowDown()
	$iSpeed -= 0.1
EndFunc

Func _Pause()
	If $Pause = False Then
		$iSpeedOld = $iSpeed
	    $iSpeed = 0
		$Pause = True
	Else
		$iSpeed = $iSpeedOld
		$Pause = False
	EndIf
	Sleep(100)
EndFunc

Func _Capture()
	_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\Test.jpg")
EndFunc

;==================================================================================================
; Function Name:   _GetFilesFolder_Rekursiv($sPath [, $sExt='*' [, $iDir=-1 [, $iRetType=0 ,[$sDelim='0']]]])
; Description:     Rekursive Auflistung von Dateien und/oder Ordnern
; Parameter(s):    $sPath     der Basispfad für die Auflistung ('.' -aktueller Pfad, '..' -Parentpfad)
;                  $sExt      Erweiterung für Dateiauswahl '*' oder -1 für alle (Standard)
;                  $iDir      -1 Dateien+Ordner(Standard), 0 nur Dateien, 1 nur Ordner
;      optional:   $iRetType  0 gibt Array, 1 gibt String zurück
;      optional:   $sDelim    legt Trennzeichen für Stringrückgabe fest
;                             0 -@CRLF (Standard)  1 -@CR  2 -@LF  3 -';'  4 -'|'
; Return Value(s): Array (Standard) od. String mit den gefundenen Pfaden der Dateien und/oder Ordner
;                  Array[0] enthält die Anzahl der gefundenen Dateien/Ordner
; Author(s):       BugFix (bugfix@autoit.de)
;==================================================================================================
Func _GetFilesFolder_Rekursiv($sPath, $sExt='*', $iDir=-1, $iRetType=0, $sDelim='0')
    Global $oFSO = ObjCreate('Scripting.FileSystemObject')
    Global $strFiles = ''
	Switch $sDelim
		Case '1'
			$sDelim = @CR
		Case '2'
			$sDelim = @LF
		Case '3'
			$sDelim = ';'
		Case '4'
			$sDelim = '|'
		Case Else
			$sDelim = @CRLF
	EndSwitch
    If ($iRetType < 0) Or ($iRetType > 1) Then $iRetType = 0
    If $sExt = -1 Then $sExt = '*'
    If ($iDir < -1) Or ($iDir > 1) Then $iDir = -1
    _ShowSubFolders($oFSO.GetFolder($sPath),$sExt,$iDir,$sDelim)
    If $iRetType = 0 Then
        Local $aOut
        $aOut = StringSplit(StringTrimRight($strFiles, StringLen($sDelim)), $sDelim, 1)
        If $aOut[1] = '' Then
            ReDim $aOut[1]
            $aOut[0] = 0
        EndIf
        Return $aOut
    Else
        Return StringTrimRight($strFiles, StringLen($sDelim))
    EndIf
EndFunc

Func _ShowSubFolders($Folder, $Ext='*', $Dir=-1, $Delim=@CRLF)
	If Not IsDeclared("strFiles") Then Global $strFiles = ''
    If ($Dir = -1) Or ($Dir = 0) Then
        For $file In $Folder.Files
            If $Ext <> '*' Then
                If StringRight($file.Name, StringLen($Ext)) = $Ext Then _
                    $strFiles &= $file.Path & $Delim
            Else
                $strFiles &= $file.Path & $Delim
            EndIf
        Next
    EndIf
    For $Subfolder In $Folder.SubFolders
        If ($Dir = -1) Or ($Dir = 1) Then $strFiles &= $Subfolder.Path & '\' & $Delim
        _ShowSubFolders($Subfolder, $Ext, $Dir, $Delim)
    Next
EndFunc
