#include-once
#include <WinAPI.au3>
#include <WinAPIGdi.au3>
#include <WinAPIRes.au3>
#include <WindowsConstants.au3>


;===============================================================================
;
; Function Name:   _CreateHBitmapArrayFromIconfile($sIconfile)
; Description:     erstellt ein 2D-Array mit HBitmaps aller Icons aus der Icondatei
; Parameter(s):    $sIconfile = die Icondatei
; Requirement(s):
; Return Value(s): Bei Erfolg = ein 2D-Array mit folgenden Daten (Spalten) für jedes Icon (Zeilen):
;                               0 = HBitmap-Handle des Icons
;                               1 = Breite des Icons
;                               2 = Höhe des Icons
;                               3 = Farbtiefe (Bits) des Icons
;                               4 = Größe (Bytes) des Icons
;                  Bei einem Fehler ist @error:
;                               1 = $sIconfile ist ein Leerstring
;                               2 = Datei lässt sich nicht öffnen
;                               3 = Datei enthält keine Icons
; Author(s):       eukalyptus (www.autoit.de)
; Modified:        Oscar (www.autoit.de)
; Remarks:
;===============================================================================
Func _CreateHBitmapArrayFromIconfile($sIconfile)
	; Skript von eukalyptus in https://autoit.de/index.php/Thread/83223-Icondatei-mit-mehreren-Icongr%C3%B6%C3%9Fen-mit-GDI-laden/?postID=666122#post666122
	; erweitert von Oscar
	If $sIconfile = '' Then Return SetError(1, 0, '')
	Local $hFile, $bIcon
	If IsBinary($sIconfile) Then
		$bIcon = $sIconfile
	Else
		$hFile = FileOpen($sIconfile, 16)
		If $hFile = -1 Then Return SetError(2, 0, '')
		$bIcon = FileRead($hFile)
		FileClose($hFile)
	EndIf
	Local $tIconHeader = DllStructCreate('ushort Res; ushort Type; ushort Cnt;')
	Local $tByte = DllStructCreate('byte[' & DllStructGetSize($tIconHeader) & '];', DllStructGetPtr($tIconHeader))
	Local $bHeader = BinaryMid($bIcon, 1, DllStructGetSize($tIconHeader))
	DllStructSetData($tByte, 1, $bHeader)
	Local $iCnt = DllStructGetData($tIconHeader, 'Cnt')
	If $iCnt < 1 Then Return SetError(3, 0, '')
	Local $aHBitmap[$iCnt][5], $bImageDir, $bIconEntry, $iIconEntryLen, $tIconEntry, $pIconEntry, $hIcon
	Local $iOffset = DllStructGetSize($tIconHeader) + 1
	Local $tImageDir = DllStructCreate('byte Width; byte Height; byte Colors; byte Res; ushort Planes; ushort Bits; uint Size; uint Offset;')
	Local $tByte = DllStructCreate('byte[' & DllStructGetSize($tImageDir) & '];', DllStructGetPtr($tImageDir))
	For $i = 0 To $iCnt - 1
		$bImageDir = BinaryMid($bIcon, $iOffset, DllStructGetSize($tImageDir))
		DllStructSetData($tByte, 1, $bImageDir)
		$aHBitmap[$i][1] = DllStructGetData($tImageDir, 'Width') = 0 ? 256 : DllStructGetData($tImageDir, 'Width')
		$aHBitmap[$i][2] = DllStructGetData($tImageDir, 'Height') = 0 ? 256 : DllStructGetData($tImageDir, 'Height')
		$aHBitmap[$i][3] = DllStructGetData($tImageDir, 'Bits')
		$aHBitmap[$i][4] = DllStructGetData($tImageDir, 'Size')
		$iOffset += DllStructGetSize($tImageDir)
		$bIconEntry = BinaryMid($bIcon, DllStructGetData($tImageDir, 'Offset') + 1, $aHBitmap[$i][4])
		$iIconEntryLen = BinaryLen($bIconEntry)
		$tIconEntry = DllStructCreate('byte[' & $iIconEntryLen & '];')
		$pIconEntry = DllStructGetPtr($tIconEntry)
		DllStructSetData($tIconEntry, 1, $bIconEntry)
		$hIcon = _WinAPI_CreateIconFromResourceEx($pIconEntry, $iIconEntryLen, True, $aHBitmap[$i][1], $aHBitmap[$i][2])
		If $hIcon <> 0 Then $aHBitmap[$i][0] = _WinAPI_Create32BitHBITMAP($hIcon, False, True)
		$tIconEntry = 0
	Next
	$tIconHeader = 0
	$tImageDir = 0
	$tByte = 0
	If $iCnt > 1 Then _SortHBitmapArray($aHBitmap)
	Return SetError(0, 0, $aHBitmap)
EndFunc   ;==>_CreateHBitmapArrayFromIconfile

Func _SortHBitmapArray(ByRef $array)
	Local $iRow = UBound($array, 1) - 1
	For $outerLoop = 0 To $iRow - 1
		For $innerLoop = $iRow To $outerLoop + 1 Step -1
			If $array[$outerLoop][3] < $array[$innerLoop][3] Then _SwitchElement($array, $outerLoop, $innerLoop)
			If $array[$outerLoop][3] = $array[$innerLoop][3] Then
				If $array[$outerLoop][1] < $array[$innerLoop][1] Then _SwitchElement($array, $outerLoop, $innerLoop)
			EndIf
		Next
	Next
EndFunc   ;==>_SortHBitmapArray

Func _SwitchElement(ByRef $array, $a, $b)
	Local $iCols = UBound($array, 2) - 1
	Local $c
	For $i = 0 To $iCols
		$c = $array[$a][$i]
		$array[$a][$i] = $array[$b][$i]
		$array[$b][$i] = $c
	Next
EndFunc   ;==>_SwitchElement

Func _DestroyHBitmapArray(ByRef $aHBitmap, $bConsoleWrite = True)
	If Not IsArray($aHBitmap) Then Return SetError(1, 0, False)
	For $i = 0 To UBound($aHBitmap, 1) - 1
		If $aHBitmap[$i][0] Then
			$iRet = _WinAPI_DeleteObject($aHBitmap[$i][0])
			If $bConsoleWrite Then ConsoleWrite('> DeleteObject #' & $i & ' = ' & ($iRet = 1 ? 'true' : 'false') & @CR)
		EndIf
	Next
	Return SetError(0, 0, True)
EndFunc