#Region - TimeStamp
; 2012-06-13 12:10:01   v 0.1
#EndRegion - TimeStamp
#include-once
#Include <GuiTreeView.au3>

Global Const $__MAX_COUNT_TREEVIEWCTRL = 100

;===============================================================================
; Function Name....: _GUICtrlTreeView_CheckBoxAsRadio
; Description......: Checkboxen in einem Treeview werden wie Radio-Ctrl behandelt
; .................: Es kann immer nur eine Checkbox aktiv sein. Wird eine andere Checkbox aktiviert,
; .................: wird automatisch die zuletzt gecheckte deaktiviert.
; .................: Zeitgleich für verschiedene Treeview im Skript einsetzbar
; Parameter(s).....: $_hWnd    Das Handle des Treeviews
; .................: $_fFocus  Wenn TRUE (Standard) wird Funktion nur ausgeführt bei Fokus auf dem Treeview
; Requirement(s)...: Treeview mit Style: $TVS_CHECKBOXES
; Return Value(s)..: Erfolg    Handle des momentan selektierten Item (unabhängig ob gecheckt oder nicht)
; .................: Fehler    0  @error=1  Treeview hat nicht den Fokus
; Note.............: Die Funktion sollte sinnvollerweise immer initialisiert werden, wenn ein Event stattfindet,
; .................: das ein de/aktivieren der Checkboxen zur Folge haben könnte (Mausklick oder Leertaste)
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GUICtrlTreeView_CheckBoxAsRadio($_hWnd, $_fFocus=True)
	If Not IsHWnd($_hWnd) Then $_hWnd = GUICtrlGetHandle($_hWnd)
	If $_fFocus Then
		Local $hCtrl = DllCall("user32.dll", "hwnd", "GetFocus")
		If $hCtrl[0] <> $_hWnd Then Return SetError(1,0,0)
	EndIf
	Local Static $a_hWnd[$__MAX_COUNT_TREEVIEWCTRL][2] = [[0]]  ; == [[hWnd,hLastCheck]]
	Local $index_hWnd = 0, $hLastCheck = 0, $fFound = False
	If $a_hWnd[0][0] = 0 Then                               ; == erstmaliger Aufruf der Funktion
		$a_hWnd[0][0] = $_hWnd
	Else                                                    ; == weitere Aufrufe
		For $i = 0 To $__MAX_COUNT_TREEVIEWCTRL -1
			If $a_hWnd[$i][0] = $_hWnd Then                 ; == für dieses Treeview erfolgte bereits ein Aufruf
				$index_hWnd = $i
				$hLastCheck = $a_hWnd[$i][1]
				$fFound = True
				ExitLoop
			ElseIf $a_hWnd[$i][0] = '' Then
				ExitLoop
			EndIf
		Next
		If Not $fFound Then                                 ; == für dieses Treeview erstmaliger Aufruf
			$index_hWnd = $i
			$a_hWnd[$index_hWnd][0] = $_hWnd
		EndIf
	EndIf
	Local $aCheck = _GUICtrlTreeView_GetCheckedInSelectionLevel($_hWnd)
	If $aCheck[0] = $hLastCheck Then                        ; == selektiertes Item war gecheckt
		$a_hWnd[$index_hWnd][1] = 0
	Else
		_GUICtrlTreeView_SetChecked($_hWnd, $hLastCheck, False)
		_GUICtrlTreeView_SetChecked($_hWnd, $aCheck[0], True)
		$a_hWnd[$index_hWnd][1] = $aCheck[0]
	EndIf
	Return $aCheck[0]
EndFunc  ;==>_GUICtrlTreeView_CheckBoxAsRadio

;===============================================================================
; Function Name....: _GUICtrlTreeView_CheckBoxAsRadioInLevel
; Description......: Checkboxen eines Levels in einem Treeview werden wie Radio-Ctrl behandelt
; .................: Es kann immer nur eine Checkbox eines Item-Levels aktiv sein. Wird eine andere Checkbox aktiviert,
; .................: wird automatisch die zuletzt gecheckte deaktiviert.
; .................: Zeitgleich für verschiedene Treeview im Skript einsetzbar
; Parameter(s).....: $_hWnd         Das Handle des Treeviews
; .................: $_hLevelOnly   Erstes Handle des Levels, für dessen Siblings ausschließlich die Funktion wirksam wird
; .................: $_fFocus       Wenn TRUE (Standard) wird Funktion nur ausgeführt bei Fokus auf dem Treeview
; Requirement(s)...: Treeview mit Style: $TVS_CHECKBOXES
; Return Value(s)..: Erfolg    Handle des momentan selektierten Item (unabhängig ob gecheckt oder nicht)
; .................: Fehler    0  @error=1  Treeview hat nicht den Fokus
; Note.............: Die Funktion sollte sinnvollerweise immer initialisiert werden, wenn ein Event stattfindet,
; .................: das ein De/aktivieren der Checkboxen zur Folge haben könnte (Mausklick oder Leertaste)
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GUICtrlTreeView_CheckBoxAsRadioInLevel($_hWnd, $_hLevelOnly=-1, $_fFocus=True)
	If Not IsHWnd($_hWnd) Then $_hWnd = GUICtrlGetHandle($_hWnd)
	If $_fFocus Then
		Local $hCtrl = DllCall("user32.dll", "hwnd", "GetFocus")
		If $hCtrl[0] <> $_hWnd Then Return SetError(1,0,0)
	EndIf
	Local Static $a_hWnd[$__MAX_COUNT_TREEVIEWCTRL][3] = [[0]]  ; == [[hWnd,hParent,hLastCheck]]
	Local $index_hWnd = 0, $hLastCheck = -1, $fFound = False, $hSel, $hParent, $hFirst, $aLvlOnly[1]
	$hSel = _GUICtrlTreeView_GetSelection($_hWnd)
	$hParent = _GUICtrlTreeView_GetParentHandle($_hWnd, $hSel)
	If Not $hParent Then
		$hParent = 'root'
		$hFirst = _GUICtrlTreeView_GetFirstItem($_hWnd)
	Else
		$hFirst = _GUICtrlTreeView_GetFirstChild($_hWnd, $hParent)
	EndIf
	If $_hLevelOnly <> -1 Then
		If Not IsArray($_hLevelOnly) Then
			$aLvlOnly[0] = $_hLevelOnly
		Else
			$aLvlOnly = $_hLevelOnly
		EndIf
		For $i = 0 To UBound($aLvlOnly) -1
			If $aLvlOnly[$i] = $hFirst Then Return
		Next
	EndIf
	If $a_hWnd[0][0] = 0 Then                               ; == erstmaliger Aufruf der Funktion
		$a_hWnd[0][0] = $_hWnd                              ; == TV-Handle
		$a_hWnd[0][1] = $hParent                            ; == Parent-Handle ('root' bei Root)
	Else                                                    ; == weitere Aufrufe
		For $i = 0 To $__MAX_COUNT_TREEVIEWCTRL -1
			If ($a_hWnd[$i][0] = $_hWnd And $a_hWnd[$i][1] = $hParent) Then  ; == für dieses Treeview erfolgte bereits ein Aufruf
				$index_hWnd = $i
				$hLastCheck = $a_hWnd[$i][2]
				$fFound = True
				ExitLoop
			ElseIf $a_hWnd[$i][0] = '' Then
				ExitLoop
			EndIf
		Next
		If Not $fFound Then                                 ; == für dieses Treeview erstmaliger Aufruf
			$index_hWnd = $i
			$a_hWnd[$index_hWnd][0] = $_hWnd
			$a_hWnd[$index_hWnd][1] = $hParent
		EndIf
	EndIf
	Local $aCheck = _GUICtrlTreeView_GetCheckedInSelectionLevel($_hWnd)
	If $aCheck[0] = $hLastCheck Then                        ; == selektiertes Item war gecheckt
		$a_hWnd[$index_hWnd][2] = 0
	Else
		_GUICtrlTreeView_SetChecked($_hWnd, $hLastCheck, False)
		_GUICtrlTreeView_SetChecked($_hWnd, $aCheck[0], True)
		$a_hWnd[$index_hWnd][2] = $aCheck[0]
	EndIf
	Return $aCheck[0]
EndFunc  ;==>_GUICtrlTreeView_CheckBoxAsRadioInLevel

;===============================================================================
; Function Name....: _GUICtrlTreeView_GetCheckedInSelectionLevel
; Description......: Ermittelt alle Item-Handle mit aktivierter Checkbox im Level des aktuell selektierten Item
; .................: Optional kann zu den Item-Handle auch gleich der Text ermittelt werden.
; Parameter(s).....: $_hWnd    Das Handle des Treeviews
; ........optional.: $_fText   FALSE (Standard) - nur Rückgabe der Handle; mit TRUE wird Array als 2D mit [[hWnd-Item, Text-Item]] zurückgegeben
; Requirement(s)...: Treeview mit Style: $TVS_CHECKBOXES
; Return Value(s)..: Array   Pos[0]     - Handle des aktuell selektierten Item (auch wenn Checkbox inaktiv!)
; .................:         Pos[n..ff] - Handle aller Item mit aktiver Checkbox (also auch das aktuell selektierte nochmals, wenn gecheckt)
; .................:  opt.   2D-Array mit Text des Item an [n][1]
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GUICtrlTreeView_GetCheckedInSelectionLevel($_hWnd, $_fText=False)
	If Not IsHWnd($_hWnd) Then $_hWnd = GUICtrlGetHandle($_hWnd)
	Local $hSel = _GUICtrlTreeView_GetSelection($_hWnd)
	Local $aRet[1] = [$hSel], $hFirst, $hNext, $hParent
	If $_fText Then
		ReDim $aRet[1][2]
		$aRet[0][0] = $hSel
		$aRet[0][1] = _GUICtrlTreeView_GetText($_hWnd, $hSel)
	EndIf
	; == erstes Item dieses Levels suchen
	$hParent = _GUICtrlTreeView_GetParentHandle($_hWnd, $hSel)
	If $hParent Then
		$hFirst = _GUICtrlTreeView_GetFirstChild($_hWnd, $hParent)
	Else
		$hFirst = _GUICtrlTreeView_GetFirstItem($_hWnd)
	EndIf
	; == erstes Item auf gecheckt prüfen
	If _GUICtrlTreeView_GetChecked($_hWnd, $hFirst) Then
		If $_fText Then
			ReDim $aRet[UBound($aRet)+1][2]
			$aRet[UBound($aRet)-1][0] = $hFirst
			$aRet[UBound($aRet)-1][1] = _GUICtrlTreeView_GetText($_hWnd, $hFirst)
		Else
			ReDim $aRet[UBound($aRet)+1]
			$aRet[UBound($aRet)-1] = $hFirst
		EndIf
	EndIf
	; == restliche Item des Levels auf gecheckt prüfen
	$hNext = $hFirst
	While True
		$hNext = _GUICtrlTreeView_GetNextSibling($_hWnd, $hNext)
		If Not $hNext Then ExitLoop
		If _GUICtrlTreeView_GetChecked($_hWnd, $hNext) Then
			If $_fText Then
				ReDim $aRet[UBound($aRet)+1][2]
				$aRet[UBound($aRet)-1][0] = $hNext
				$aRet[UBound($aRet)-1][1] = _GUICtrlTreeView_GetText($_hWnd, $hNext)
			Else
				ReDim $aRet[UBound($aRet)+1]
				$aRet[UBound($aRet)-1] = $hNext
			EndIf
		EndIf
	WEnd
	Return $aRet
EndFunc  ;==>_GUICtrlTreeView_GetCheckedInSelectionLevel

;==================================================================================================
; Function Name: _GUICtrlTreeView_ExpandOneLevel
; Description..: Aus/Einklappen nur EINER Ebene eines Items, analog zum Mausklick auf '+/-'
; Parameter(s).: $_hWnd     Handle des TreeView
; .............: $_hParent  Handle des Item, dessen Childs aus/einzuklappen sind
; .............:            Standard 0 ==> Handle des ersten Item im TreeView
; .............: $_fExpand  Standard TRUE ==> Ausklappen, Einklappen mit FALSE
; Return.......: Erfolg     Handle des Item, dessen Childs aus/eingeklappt wurden
; .............: Fehler     0  @error 1  -  TreeView enthält kein Item
; .............:               @error 2  -  Item hat keine Child-Item
; Note.........: Die Funktion sollte zwischen _GUICtrlTreeView_BeginUpdate() und _GUICtrlTreeView_EndUpdate()
; .............: ausgeführt werden um ein Flackern zu verhindern
; Author(s)....: BugFix (bugfix@autoit.de)
;==================================================================================================
Func _GUICtrlTreeView_ExpandOneLevel($_hWnd, $_hParent=0, $_fExpand=True)
	If Not IsHWnd($_hWnd) Then $_hWnd = GUICtrlGetHandle($_hWnd)
	If $_hParent = 0 Then $_hParent = _GUICtrlTreeView_GetFirstItem($_hWnd)
	If $_hParent = 0 Then Return SetError(1,0,0)
	Local $hChild, $countChild = _GUICtrlTreeView_GetChildCount($_hWnd, $_hParent)
	If $countChild = 0 Then Return SetError(2,0,0)
	_GUICtrlTreeView_Expand($_hWnd, $_hParent, $_fExpand)
	If Not $_fExpand Then Return $_hParent
	For $i = 1 To $countChild
		If $i = 1 Then
			$hChild = _GUICtrlTreeView_GetFirstChild($_hWnd, $_hParent)
		Else
			$hChild = _GUICtrlTreeView_GetNextSibling($_hWnd, $hChild)
		EndIf
		If _GUICtrlTreeView_GetChildren($_hWnd, $hChild) Then _GUICtrlTreeView_Expand($_hWnd, $hChild, False)
	Next
	Return $_hParent
EndFunc  ;==>_GUICtrlTreeView_ExpandOneLevel