#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <File.au3>
#include <GuiToolbar.au3>

; --- $SCROLLINFO
Global Const $SCROLLINFO = _
	"UINT cbSize;"& _
	"UINT fMask;"& _
	"INT nMin;"& _
	"INT nMax;"& _
	"UINT nPage;"& _
	"INT nPos;"& _
	"INT nTrackPos;"


Global Const $SB_HORZ =  0
Global Const $SB_VERT =  1
Global Const $SB_CTL =  2
Global Const $SB_BOTH =  3
Global Const $SB_LINEUP =  0
Global Const $SB_LINELEFT =  0
Global Const $SB_LINEDOWN =  1
Global Const $SB_LINERIGHT =  1
Global Const $SB_PAGEUP =  2
Global Const $SB_PAGELEFT =  2
Global Const $SB_PAGEDOWN =  3
Global Const $SB_PAGERIGHT =  3
Global Const $SB_THUMBPOSITION =  4
Global Const $SB_THUMBTRACK =  5
Global Const $SB_TOP =  6
Global Const $SB_LEFT =  6
Global Const $SB_BOTTOM =  7
Global Const $SB_RIGHT =  7
Global Const $SB_ENDSCROLL =  8


Global Const $SIF_RANGE = 0x0001
Global Const $SIF_PAGE = 0x0002
Global Const $SIF_POS = 0x0004
Global Const $SIF_DISABLENOSCROLL = 0x0008
Global Const $SIF_TRACKPOS = 0x0010
Global Const $SIF_ALL = BitOR($SIF_RANGE, $SIF_PAGE, $SIF_POS, $SIF_TRACKPOS)

Global Const $SW_SCROLLCHILDREN = 0x0001
Global Const $SW_INVALIDATE = 0x0002
Global Const $SW_ERASE =  0x0004

;-- Global variables
Global $sDataDir = @ScriptDir & "\Data"
Global $idButton [1], $idcbo
Global $sCurComboSel
Global $hwndMain
Global $hwndChild

Global $g_nBtnHeight = 35
Global $g_nWindowLines
Global $g_nLineCount
Global $g_nLineHeight
Global $g_nColumns = 2


;-- Start script
Exit (ScriptMain ( ))


;-- Main function of the script
Func ScriptMain ( )

	Local $nMsg
	Local $rcClient


	$hwndMain = GUICreate ("Form1", 625, 443, 192, 124, _
				BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS));, $WS_VSCROLL))

	GUICtrlCreateLabel ("Auswahl", 12, 5)
	$idcbo = GUICtrlCreateCombo ("", 12, 23, 145, 25)
	InitComboData ($idcbo)

	$hwndChild = GUICreate ("", 625, 390, 0, 50, _
				BitOR($WS_CHILD, $WS_TABSTOP, $WS_VISIBLE, $WS_VSCROLL, $WS_GROUP), $WS_EX_CLIENTEDGE, $hwndMain)

	CreateButtons ($idcbo)

	GUISwitch ($hwndChild)

	GUIRegisterMsg ($WM_SIZE, "OnSize")
	GUIRegisterMsg ($WM_MOUSEWHEEL, "OnMouseWheel")
	GUIRegisterMsg ($WM_VSCROLL, "OnVScroll")
	GUISetState (@SW_SHOW, $hwndMain)


	While 1
		$nMsg = GUIGetMsg ( )
		Switch ($nMsg)
			Case $GUI_EVENT_CLOSE
				ExitLoop

			Case $idButton[0] To $idButton[UBound($idButton) - 1]
				MsgBox(4096, "", StringFormat ("Es wurde eine Schaltfläche gedrückt.\nID: %d\nText: %s", $nMsg, GUICtrlRead ($nMsg)))

			Case $idcbo
				If ($sCurComboSel <> GUICtrlRead ($idcbo)) Then

					$sCurComboSel = GUICtrlRead ($idcbo)

					DeleteButtons ( )
					CreateButtons ($idcbo)
					$rcClient = WinGetClientSize ($hwndMain)
					OnSize ($hwndMain, $WM_SIZE, 0, MAKELPARAM($rcClient[0], $rcClient[1]))
				EndIf
		EndSwitch
	WEnd

	Return 0

EndFunc

;-- Aligns the buttons
Func OnSize ($hwnd, $message, $wParam, $lParam)

	Local $rcChild
	Local $cx, $cy
	Local $nWidth, $nHeight = 35
	Local $cnLoop = 0
	Local $cnButtons = UBound ($idButton) ; Anzahl der Schaltflächen
	Local $si = DllStructCreate ($SCROLLINFO)


	DllStructSetData ($si, "cbSize", DllStructGetSize ($si))
	DllStructSetData ($si, "fMask", $SIF_ALL)

	GetScrollInfo ($hwndChild, $SB_VERT, DllStructGetPtr ($si))

	WinMove ($hwndChild, "", 0, 50, BitAND($lParam, 0xffff), BitShift($lParam, 16) - 50)

	$cx = 10 ; Abstand links/rechts
	$cy = 10 - (DllStructGetData ($si, "nPos") * $g_nLineHeight) ; Abstand oben


	$rcChild = WinGetClientSize ($hwndChild)

	$g_nWindowLines   = min($rcChild[1] / ($g_nLineHeight), $g_nLineCount)


	$nWidth  = Int((($rcChild[0] - $cx * 2)  - (22 * ($g_nColumns - 1))) / ($g_nColumns))

	For $i = 0 To $g_nLineCount - 1
		For $j = 0 To $g_nColumns - 1

			If ($cnLoop >= $cnButtons) Then ExitLoop
			WinMove (GUICtrlGetHandle ($idButton[$cnLoop]), "", $cx, $cy, $nWidth, $g_nBtnHeight)

			$cx     += $nWidth + 20
			$cnLoop += 1
		Next
		$cx = 10
		$cy += $g_nLineHeight
	Next

	DllStructSetData ($si, "cbSize", DllStructGetSize ($si))
	DllStructSetData ($si, "fMask", BitOR($SIF_RANGE, $SIF_PAGE))
	DllStructSetData ($si, "nPage", $g_nWindowLines)
	DllStructSetData ($si, "nMin", 0)
	DllStructSetData ($si, "nMax", $g_nLineCount - 1)

	SetScrollInfo ($hwndChild, $SB_VERT, DllStructGetPtr ($si), TRUE)

	Return 0

EndFunc   ;==>OnSize

;-- Mouse-scrolling support
Func OnMouseWheel ($hwnd, $message, $wParam, $lParam)

	If ((BitShift($wParam, 16) / 120) < 0) Then

		OnVScroll ($hwndChild, $WM_VSCROLL, MAKEWPARAM($SB_LINEDOWN, 0), 0)

	ElseIf ((BitShift($wParam, 16) / 120) > 0) Then

		OnVScroll ($hwndChild, $WM_VSCROLL, MAKEWPARAM($SB_LINEUP, 0), 0)
	EndIf


	Return 0

EndFunc

Func OnVScroll ($hwnd, $message, $wParam, $lParam)

	Local $oldPos
	Local $si = DllStructCreate ($SCROLLINFO)

	DllStructSetData ($si, "cbSize", DllStructGetSize ($si))
	DllStructSetData ($si, "fMask", $SIF_ALL)

	GetScrollInfo ($hwndChild, $SB_VERT, DllStructGetPtr ($si))

	$oldPos = DllStructGetData ($si, "nPos")

	Switch (BitAND($wParam, 0xFFFF))

	case $SB_TOP
		DllStructSetData ($si, "nPos", DllStructGetData ($si, "nMin"))

	case $SB_BOTTOM
		DllStructSetData ($si, "nPos", DllStructGetData ($si, "nMax"))

	case $SB_LINEUP
		DllStructSetData ($si, "nPos", $oldPos - 1)

	case $SB_LINEDOWN
		DllStructSetData ($si, "nPos", $oldPos + 1)

	case $SB_PAGEDOWN
		DllStructSetData ($si, "nPos", $oldPos + DllStructGetData ($si, "nPage"))

	case $SB_PAGEUP
		DllStructSetData ($si, "nPos", $oldPos - DllStructGetData ($si, "nPage"))

	case $SB_THUMBPOSITION
		ContinueCase
	case $SB_THUMBTRACK

		DllStructSetData ($si, "nPos", DllStructGetData ($si, "nTrackPos"))

	EndSwitch

	DllStructSetData ($si, "fMask", $SIF_POS)
	SetScrollInfo ($hwndChild, $SB_VERT, DllStructGetPtr ($si), TRUE)
	GetScrollInfo ($hwndChild, $SB_VERT, DllStructGetPtr ($si))


	If ($oldpos <> DllStructGetData ($si, "nPos")) Then

		ScrollWindowEx ( _
			$hwndChild, _
			0, _
			($oldpos - DllStructGetData ($si, "nPos")) * $g_nLineHeight, _
			0, _
			0, _
			0, 0, BitOR($SW_INVALIDATE, $SW_ERASE, $SW_SCROLLCHILDREN) _
			)

		UpdateWindow ($hwndChild)
	EndIf

	Return $GUI_RUNDEFMSG

EndFunc

;-- Initializes the content of the combo box
Func InitComboData ($idCombo)

	Local $aInis
	Local $sFileName

	$aInis = _FileListToArray ($sDataDir, "*.ini", 1)

	If IsArray ($aInis) Then

		For $i = 0 To $aInis[0]

			$sFileName = StringTrimRight ($aInis[$i], 4)
			GUICtrlSetData ($idcbo, $sFileName, $sFileName)
		Next
	EndIf

	$sCurComboSel = GUICtrlRead ($idcbo)

	Return 0

EndFunc

;-- Creates a button for each entry in the INI section "Name"
Func CreateButtons ($idCombo)

	Local $var
	Local $iniwahl


	GUISwitch ($hwndChild)

	$iniwahl = StringFormat ("%s\\%s.ini", $sDataDir, GUICtrlRead ($idCombo))

	$var = IniReadSection ($iniwahl, "Namen")

	ReDim $idButton[$var[0][0]]

	For $i = 1 To $var[0][0]

		$idButton[$i - 1] = GUICtrlCreateButton ($var[$i][1], 0, 0);, 0, 0, BitOR($GUI_SS_DEFAULT_BUTTON, $WS_GROUP, $WS_TABSTOP))
	Next

	$g_nLineCount = Ceiling (UBound($idButton) / $g_nColumns)  ; Anzahl der Reihen
	$g_nLineHeight = $g_nBtnHeight + 20

	Return 0

EndFunc

;-- Deletes all buttons
Func DeleteButtons ( )

	For $i = 0 To UBound($idButton) - 1

		GUICtrlDelete ($idButton[$i])
	Next

	Return 0

EndFunc

;-- API functions
Func ScrollWindowEx ($hWnd, $dx, $dy, $prcScroll, $prcClip, $hrgnUpdate, $prcUpdate, $flags)

	Local $aRes = DllCall ("user32.dll", "INT", "ScrollWindowEx", _
								"HWND", $hWnd, _
								"INT", $dx, _
								"INT", $dy, _
								"PTR", $prcScroll, _
								"PTR", $prcClip, _
								"HANDLE", $hrgnUpdate, _
								"PTR", $prcUpdate, _
								"UINT", $flags)
	$prcUpdate = $aRes[7]
	Return $aRes[0]

EndFunc

Func GetScrollInfo ($hwnd, $fnBar, $lpsi)

	Local $aRes = DllCall ("user32.dll", "int", "GetScrollInfo", _
								"HWND", $hwnd, _
								"int", $fnBar, _
								"ptr", $lpsi)
	Return $aRes[0]

EndFunc

Func SetScrollInfo ($hwnd, $fnBar, $lpsi, $fRedraw)

	Local $aRes = DllCall ("user32.dll", "int", "SetScrollInfo", _
								"HWND", $hwnd, _
								"int", $fnBar, _
								"ptr", $lpsi, _
								"BOOL", $fRedraw)
	Return $aRes[0]

EndFunc

Func UpdateWindow ($hWnd)

	Local $aRes = DllCall ("user32.dll", "BOOL", "UpdateWindow", _
								"HWND", $hWnd)
	Return $aRes[0]

EndFunc

;-- Helper functions
Func MAKEWPARAM($wLow, $wHigh)
	Return BitOR ( BitAND ( $wLow, 0xFFFF ), BitShift (BitAND ( $wHigh, 0xFFFF ), -16) )
EndFunc

Func MAKELPARAM($wLow, $wHigh)
	Return BitOR ( BitAND ( $wLow, 0xFFFF ), BitShift (BitAND ( $wHigh, 0xFFFF ), -16) )
EndFunc

Func min ($a, $b)

	If ($a < $b) Then
		Return $a
	Else
		Return $b
	EndIf

EndFunc

