#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GuiConstantsEx.au3>
#include <ButtonConstants.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>
#include <array.au3>
#include <Date.au3>
; #include "_Array2DSearch.au3"

Opt('MustDeclareVars', 1)

$Debug_LV = False ; Check ClassName being passed to ListView functions, set to True and use a handle to another control to see it work

#Region Vars-Declaration
Global Const $MyColorRed = 0xff0000 ; Red
Global Const $MyColorGreen = 0x00FF00 ; Grün leuchtend
Global Const $MyColorBlue = 0x0000FF ; Blau
Global Const $MyColorWhite = 0xFFFFFF ; Weiß
Global Const $MyColorBlack = 0x000000 ; Schwarz

Global $MyGui, $GuiListView, $GuiFilterInput, $GuiStatusLabel, $GuiButtonFiltern, $GuiButtonClear, $GuiButtonLast, $GuiButtonNext, $GuiMSG, $hImage
Global $GuiWidth = 700, $GuiHeight = 400 ; GUI-Größe
Global $MaxRows = 999, $MaxCol = 5 ; Reihen und Spalten
Global $MyDataArray ; Daten-Array für die ListView
Global $TempRowContent
Global $aRowsWithHits, $PositionInArrayRWH ; Hilfsarray für die gefundenen Elemente
Global $MyInitTimer
Global Const $ItemDistance = 10
Global $LastX
#EndRegion Vars-Declaration


#Region Gui-Creation
; -- GUI erzeugen --
$MyGui = GUICreate("Filter in ListView", $GuiWidth, $GuiHeight)
$LastX = $ItemDistance
GUICtrlCreateLabel("Filter:", $LastX, 20, 30, 20)
$LastX += 30 + $ItemDistance
$GuiFilterInput = GUICtrlCreateInput("999", $LastX, 20 - 3, 200)
$LastX += 200 + $ItemDistance
$GuiButtonFiltern = GUICtrlCreateButton("Filtern/Suchen", $LastX, 20 - 4, 90, 24, $BS_DEFPUSHBUTTON)
$LastX += 90 + $ItemDistance
$GuiButtonClear = GUICtrlCreateButton("Löschen", $LastX, 20 - 4, 90, 24)
$LastX += 90 + $ItemDistance
$GuiButtonLast = GUICtrlCreateButton("<<", $LastX, 20 - 4, 20, 24)
GUICtrlSetState(-1, $GUI_DISABLE)
$LastX += 20 + $ItemDistance
$GuiButtonNext = GUICtrlCreateButton(">>", $LastX, 20 - 4, 20, 24)
GUICtrlSetState(-1, $GUI_DISABLE)
; $GuiListView = GUICtrlCreateListView("", 10, 60, $GuiWidth - 20, 290, BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER), $LVS_EX_FULLROWSELECT)
$GuiListView = GUICtrlCreateListView("", 10, 60, $GuiWidth - 20, 290, BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER), BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_CHECKBOXES))
$GuiStatusLabel = GUICtrlCreateLabel("Gui erzeugen...", 10, $GuiHeight - 20, $GuiWidth - 20, 20)
GUISetState(@SW_SHOW, $MyGui)
#EndRegion Gui-Creation

; -- Load images --
$hImage = _GUIImageList_Create(16, 16, 5, 3)
_GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap(GUICtrlGetHandle($GuiListView), $MyColorWhite, 16, 16)) ; weiß
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 137)
_GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap(GUICtrlGetHandle($GuiListView), $MyColorRed, 16, 16)) ; rot
_GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap(GUICtrlGetHandle($GuiListView), $MyColorGreen, 16, 16)) ; grün
_GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap(GUICtrlGetHandle($GuiListView), $MyColorBlue, 16, 16)) ; blau
_GUICtrlListView_SetImageList($GuiListView, $hImage, 1)

#Region Spalten hinzufügen
; Spalten hinzufügen
SetStatus("Spalten hinzufügen...", 1)
$MyInitTimer = TimerInit()
; _GUICtrlListView_BeginUpdate($GuiListView)
; Add columns
For $c = 1 To $MaxCol
	_GUICtrlListView_InsertColumn($GuiListView, $c - 1, "Column " & $c, 100)
Next
; _GUICtrlListView_EndUpdate($GuiListView)
_MyDebug("main", "Spalten hinzufügen", ru_TimerDiffNice($MyInitTimer))
#EndRegion Spalten hinzufügen


#cs  Geschwindigkeitsmessungen:

	>main<: Methode 1 - Tabelle füllen mit UDF-Funktionen        => 03s (3337 ticks)
	>main<: Methode 2 - Tabelle füllen über CreateListViewItem   => 04s (4061 ticks)
	>main<: Methode 3 - Tabelle füllen über Array mit UDF        =>       655 ticks
#ce

; Welche Variante um die Tabelle zu füllen?
Global $FillListViewMethode = 3 ; 3 = Array, da es die schnellste Methode ist

#Region fill the listview with UDF - methode 1
If $FillListViewMethode == 1 Then
	; -- Tabelle füllen --
	; Add items
	SetStatus("Methode 1 - Erzeugen (" & $MaxRows & " x " & $MaxCol & ")...", 1)
	$MyInitTimer = TimerInit()
	; 	_GUICtrlListView_BeginUpdate($GuiListView)
	For $r = 1 To $MaxRows
		_GUICtrlListView_AddItem($GuiListView, "Row " & $r & ", Col 1, " & Random(0, 99999, 1), $r - 1)
		For $c = 2 To $MaxCol
			_GUICtrlListView_AddSubItem($GuiListView, $r - 1, "Row " & $r & ", Col " & $c & ", " & Random(0, 99999, 1), $c - 1)
		Next
	Next
	_MyDebug("main", "Methode 1 - Tabelle füllen mit UDF-Funktionen", ru_TimerDiffNice($MyInitTimer))
	; _GUICtrlListView_EndUpdate($GuiListView)
EndIf
#EndRegion fill the listview with UDF - methode 1


#Region fill the listview with GUICtrlCreateListViewItem - methode 2
If $FillListViewMethode == 2 Then
	; -- Tabelle füllen neu --
	SetStatus("Methode 2 - Erzeugen (" & $MaxRows & " x " & $MaxCol & ")...", 1)
	$MyInitTimer = TimerInit()
	; 	_GUICtrlListView_BeginUpdate($GuiListView)
	; Add items
	For $r = 1 To $MaxRows
		$TempRowContent = ""
		; _GUICtrlListView_AddItem($GuiListView, "Row " & $r & ", Col 1, " & Random(0, 99999, 1), $r - 1)
		For $c = 1 To $MaxCol
			$TempRowContent &= "Row " & $r & ", Col " & $c & ", " & Random(0, 99999, 1) & "|"
		Next
		; Letzten "|" strippen
		$TempRowContent = StringTrimRight($TempRowContent, 1)
		GUICtrlCreateListViewItem($TempRowContent, $GuiListView)
	Next
	_MyDebug("main", "Methode 2 - Tabelle füllen über CreateListViewItem", ru_TimerDiffNice($MyInitTimer))
	; _GUICtrlListView_EndUpdate($GuiListView)
EndIf
#EndRegion fill the listview with GUICtrlCreateListViewItem - methode 2


#Region fill the listview via Array with UDF - - methode 3
If $FillListViewMethode == 3 Then
	; -- Tabelle füllen neu --
	SetStatus("Methode 3 - Erzeugen (" & $MaxRows & " x " & $MaxCol & ")...", 1)
	$MyInitTimer = TimerInit()
	Dim $MyDataArray[$MaxRows][$MaxCol]

	; Add items
	For $r = 1 To $MaxRows
		; _GUICtrlListView_AddItem($GuiListView, "Row " & $r & ", Col 1, " & Random(0, 99999, 1), $r - 1)
		For $c = 1 To $MaxCol
			$MyDataArray[$r - 1][$c - 1] = "Row " & $r & ", Col " & $c & ", " & Random(0, 99999, 1)
		Next
	Next
	_MyDebug("main", "Nur Array füllen", ru_TimerDiffNice($MyInitTimer))
	; _GUICtrlListView_BeginUpdate($GuiListView)
	_GUICtrlListView_AddArray($GuiListView, $MyDataArray)
	; _GUICtrlListView_EndUpdate($GuiListView)
	_MyDebug("main", "Methode 3 - Tabelle füllen über Array mit UDF", ru_TimerDiffNice($MyInitTimer))
EndIf
#EndRegion fill the listview via Array with UDF - - methode 3


; Icon ganz vorne mit -2 löschen
$MyInitTimer = TimerInit()
For $r = 1 To $MaxRows
	_GUICtrlListView_SetItemImage($GuiListView, $r - 1, -2) ; -2 = NoIcon
Next
_MyDebug("main", "Icon vorne löschen", ru_TimerDiffNice($MyInitTimer))

; Spaltenbreite anpassen
SetOptimalColumnWidth()

; _GUICtrlListView_BeginUpdate($GuiListView)


#Region Main
; Mainloop
SetStatus("")
While 1
	$GuiMSG = GUIGetMsg()

	Switch $GuiMSG
		Case $GUI_EVENT_CLOSE ; Window-Event-Close
			GUISetState(@SW_HIDE, $MyGui)
			GUIDelete($MyGui)
			Exit

		Case $GuiButtonFiltern ; Filtern/Suchen
			MySearch(GUICtrlRead($GuiFilterInput))

		Case $GuiButtonClear ; clear filter
			GUICtrlSetData($GuiFilterInput, "")
			MySearch("")
			SetStatus("Filter gelöscht")

		Case $GuiButtonLast ; last
			JumpToFoundedItem(-1)

		Case $GuiButtonNext ; next
			JumpToFoundedItem(+1)
	EndSwitch
WEnd
#EndRegion Main


#Region Funktionsdefinitionen
; Funktion, die im Listview nach dem Filter sucht und alle Zeilen markiert.
; Ebenfalls werden die gefundenen Rows im Array $aRowsWithHits aufgehoben, damit mit "last" und "next" umgeblättert werden kann
Func MySearch($myFilter)
	Local $MyLocalInitTimer = TimerInit(), $MyLocalInitTimerZwo
	Local $FoundInRow, $LastRow, $ReturnError
	Local $tempArray, $tempArray2

	; Filter-Eingabe
	; $myFilter = InputBox("Bitte Filter eingeben", "Z.B. 99", 99, "", 200, 120)
	If $myFilter == "" Then
		; Alle Selektionen entfernen
		; _GUICtrlListView_SetItemSelected($GuiListView, -1, False, False) ; Alle entfernen
		MarkOrUnmarkFoundedRows()
		; Button deaktivieren
		GUICtrlSetState($GuiButtonLast, $GUI_DISABLE)
		GUICtrlSetState($GuiButtonNext, $GUI_DISABLE)
		; FoundedArray löschen
		$aRowsWithHits = "" ; Array
		$PositionInArrayRWH = 0 ; Position im Array für "last" und "next"
		SetStatus("Alle anzeigen")
		Return
	EndIf

	; Alle Selektionen entfernen
	; _GUICtrlListView_SetItemSelected($GuiListView, -1, False, False) ; Alle entfernen

	; Alle Pfeile entfernen
	MarkOrUnmarkFoundedRows(0)

	SetStatus('Suchen nach "' & $myFilter & '"...', 1)

	; Welche Suchmethode soll benutzt werden?  <----- Hier die Suchmethode setzen. Derzeit funktioniert nur Methode A
	Local $SearchMethodeA = 1
	Local $SearchMethodeB = 0
	Local $SearchMethodeC = 0
	Local $SearchMethodeD = 0

	#Region Suchen mit _GUICtrlListView_FindInText - Methode A
	; -- A - Suchen mit _GUICtrlListView_FindInText --   ===> ok
	If $SearchMethodeA Then
		$MyLocalInitTimerZwo = TimerInit()
		; Parameter zurücksetzen
		$FoundInRow = -1 ; start from the beginning
		$LastRow = -2
		; Search for target item
		$aRowsWithHits = ""
		While 1
			$FoundInRow = _GUICtrlListView_FindInText($GuiListView, $myFilter, $FoundInRow)
			If $FoundInRow < 0 Or $LastRow >= $FoundInRow Then ExitLoop 1
			; "Last" aufheben, damit nicht unendlich immer wieder von vorne gesucht wird
			$LastRow = $FoundInRow
			; Reihe hinzufügen
			MyArrayAdd($aRowsWithHits, $FoundInRow)
		WEnd
		_MyDebug("Search", 'A - Suchen mit _GUICtrlListView_FindInText', ru_TimerDiffNice($MyLocalInitTimerZwo))
		_MyDebugArray("Search", $aRowsWithHits, 'A - Suchen mit _GUICtrlListView_FindInText')
		; _ArrayDisplay($aRowsWithHits, "Result via _GUICtrlListView_FindInText")
	EndIf
	#EndRegion Suchen mit _GUICtrlListView_FindInText - Methode A


	#Region Suchen mit _ArrayFindAll - Methode B
	; -- B - Suchen mit _ArrayFindAll --   ===> liefert nicht alle Ergebnisse!!!      <---------- Hilfe, warum geht das nicht?
	If $SearchMethodeB Then
		$MyLocalInitTimerZwo = TimerInit()
		; _ArrayFindAll(Const ByRef $avArray, $vValue [, $iStart = 0 [, $iEnd = 0 [, $iCase = 0 [, $iPartial = 0 [, $iSubItem = 0]]]]])
		$aRowsWithHits = _ArrayFindAll($MyDataArray, $myFilter, 0, 0, 0, 1, -1)
		$ReturnError = @error
		If $aRowsWithHits == -1 Then _MyDebug("Search", "$aRowsWithHits = " & $aRowsWithHits & " , Error = " & $ReturnError & "       MyFilter = " & $myFilter)
		_MyDebug("Search", 'B - Suchen mit _ArrayFindAll', ru_TimerDiffNice($MyLocalInitTimerZwo))
		_MyDebugArray("Search", $aRowsWithHits, 'B - Suchen mit _ArrayFindAll')
		; _ArrayDisplay($aRowsWithHits, "Result via _ArrayFindAll")
	EndIf
	#EndRegion Suchen mit _ArrayFindAll - Methode B


	#Region Suchen mit _ArraySearch - Methode C
	; -- C - Suchen in per Hand mit _ArraySearch --    ===> liefert nicht alle Ergebnisse!!!      <---------- Hilfe, warum geht das nicht?
	If $SearchMethodeC Then
		$MyLocalInitTimerZwo = TimerInit()
		$aRowsWithHits = ""
		$FoundInRow = 0
		While 1
			$FoundInRow = _ArraySearch($MyDataArray, $myFilter, $FoundInRow, 0, 0, 1)
			; _MyDebug("Search", "Erg = " & $FoundInRow)
			If $FoundInRow == -1 Then ExitLoop
			; Reihe hinzufügen
			MyArrayAdd($aRowsWithHits, $FoundInRow)
			; Zur Reihe 1 dazuzählen
			$FoundInRow += 1
		WEnd
		_MyDebug("Search", 'C - Suchen per Hand mit _ArraySearch', ru_TimerDiffNice($MyLocalInitTimerZwo))
		_MyDebugArray("Search", $aRowsWithHits, 'C - Suchen per Hand mit _ArraySearch')
		; _ArrayDisplay($aRowsWithHits, "Result via _ArrayFindAll per Hand")
	EndIf
	#EndRegion Suchen mit _ArraySearch - Methode C


	#Region Suchen mit _Array2DSearch - Methode D
	;  -- D - Suchen mit _Array2DSearch von BugFix --   ===> JumpToFoundedItem funktioniert dann nicht mehr richtig :-(      <---------- Hilfe, warum?
	If $SearchMethodeD Then
		$MyLocalInitTimerZwo = TimerInit()
		; _Array2DSearch($avArray, $vWhat2Find, $iDim=-1, $iStart=0, $iEnd=0, $iCaseSense=0, $fPartialSearch=False, $1stFound=False)
		$tempArray = _Array2DSearch($MyDataArray, $myFilter, -1, 0, 0, 0, 1)
		_MyDebug("Search", 'D - Suchen mit _Array2DSearch', ru_TimerDiffNice($MyLocalInitTimerZwo))
		_MyDebugArray("Search", $tempArray, 'D - Suchen mit _Array2DSearch')
		; _ArrayDisplay($tempArray, "Result via _Array2DSearch")
		; Reihen rausfiltern   ====> Besser _Array2DSearch modifzieren um Speed rauszuholen und gleich nur die gewünschten Reihen zu liefern
		$MyLocalInitTimerZwo = TimerInit()
		$aRowsWithHits = ""
		If IsArray($tempArray) And $tempArray[0] > 0 Then
			For $e = 1 To $tempArray[0]
				$tempArray2 = StringSplit($tempArray[$e], "|")
				; Reihe hinzufügen, nur wenn nicht schon im Array
				MyArrayAdd($aRowsWithHits, $tempArray2[1], 1)
			Next
		EndIf
		_MyDebug("Search", 'D - Suchen mit _Array2DSearch - Reihen rausfiltern', ru_TimerDiffNice($MyLocalInitTimerZwo))
		_MyDebugArray("Search", $aRowsWithHits, 'D - Suchen mit _Array2DSearch - Reihen rausgefiltert')
		; _ArrayDisplay($aRowsWithHits, 'D - Suchen mit _Array2DSearch - Reihen rausfiltern')
	EndIf
	#EndRegion Suchen mit _Array2DSearch - Methode D


	; Alle gefundenen Reihen markieren
	MarkOrUnmarkFoundedRows(1)

	; Erste Fundstelle selektieren
	$PositionInArrayRWH = 0
	JumpToFoundedItem(+1)

	; Buttons frei geben
	If IsArray($aRowsWithHits) And $aRowsWithHits[0] > 0 Then
		GUICtrlSetState($GuiButtonLast, $GUI_ENABLE)
		GUICtrlSetState($GuiButtonNext, $GUI_ENABLE)
	EndIf

	; Zeitausgabe
	_MyDebug("Search", 'Suchen nach "' & $myFilter & '"', ru_TimerDiffNice($MyLocalInitTimer))

	; Ausgabe in MsgBox
	If $aRowsWithHits[0] == 0 Then
		MsgBox(0, "Suchergebnis", 'Es wurden keine Items mit "' & $myFilter & '" gefunden!')
	Else
		MsgBox(0, "Suchergebnis", $aRowsWithHits[0] & ' Items mit "' & $myFilter & '" gefunden und markiert')
	EndIf
EndFunc   ;==>MySearch


; Funktion, die in dem $aRowsWithHits von der derzeitigen Position im Array $PositionInArrayRWH vor oder zurückblättert und an
; die betreffende Reihe springt
; $ArrayPos ist normalerweise +1 oder -1
Func JumpToFoundedItem($ArrayPos = 0)
	Local $MyLocalInitTimer = TimerInit()
	Local $GoToRow
	Local $ArrayPosNew = $PositionInArrayRWH + $ArrayPos ; Neue Array-Position

	If (Not IsArray($aRowsWithHits)) Or $aRowsWithHits[0] == 0 Then
		SetStatus("Kein Sucherergebnis vorhanden")
		Return
	EndIf

	; letztes Element überschritten?
	If $ArrayPosNew > $aRowsWithHits[0] Then $ArrayPosNew = 1

	; erstes Element unterschritten
	If $ArrayPosNew < 1 Then $ArrayPosNew = $aRowsWithHits[0]

	; Reihe nochmal setzen und hinspringen
	$GoToRow = $aRowsWithHits[$ArrayPosNew]
	_GUICtrlListView_SetItemSelected($GuiListView, -1, False, False) ; Alle Selektionen entfernen
	_GUICtrlListView_SetItemSelected($GuiListView, $GoToRow, True, True) ; Nur den einen selektieren
	_MyDebug("JumpToFoundedItem", "  $GuiListView; " & $GuiListView)
	_MyDebug("JumpToFoundedItem", "  $ArrayPosNew; " & $ArrayPosNew)
	_MyDebug("JumpToFoundedItem", "  $GoToRow;     " & $GoToRow)
	_GUICtrlListView_EnsureVisible($GuiListView, $GoToRow) ; Hinscrollen/Anzeigen

	; Pointer umsetzen
	$PositionInArrayRWH = $ArrayPosNew

	SetStatus($ArrayPosNew & " # " & $aRowsWithHits[0] & " der gefundenen Items    (in Zeile " & $GoToRow + 1 & ")")

	_MyDebug("JumpToFoundedItem", 'jump to result ' & $ArrayPosNew & " in row " & $GoToRow, ru_TimerDiffNice($MyLocalInitTimer))
EndFunc   ;==>JumpToFoundedItem


; Funktion, die den Text um unteren Rand der Gui ausgibt und ggf. den WaitingCursor setzt
Func SetStatus($Text, $WaitingCursor = 0)
	; Status ausgeben
	GUICtrlSetData($GuiStatusLabel, $Text)

	; Cursor umsetzen
	If $WaitingCursor Then
		GUISetCursor(15, 1, $MyGui) ; Waiting-Cursor
	Else
		GUISetCursor(-1, 0, $MyGui) ; Normal-Cursor
	EndIf
EndFunc   ;==>SetStatus


; Funktion, die den Content der Listview löscht
Func DeleteListView()
	; Inhalt löschen
	SetStatus("ListView löschen...")
	$MyInitTimer = TimerInit()
	; _GUICtrlListView_BeginUpdate($GuiListView)
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($GuiListView))
	; _GUICtrlListView_EndUpdate($GuiListView)
	_MyDebug("DeleteListView", "ListView löschen", ru_TimerDiffNice($MyInitTimer))
EndFunc   ;==>DeleteListView


; Funktion, die die Spaltenbreiten optimal breit macht, sodass der Text rein passt
Func SetOptimalColumnWidth()
	; Spaltenbreite anpassen
	SetStatus("Spaltenbreite setzen...")
	$MyInitTimer = TimerInit()
	For $c = 1 To $MaxCol
		_GUICtrlListView_SetColumnWidth($GuiListView, $c - 1, $LVSCW_AUTOSIZE)
	Next
	_MyDebug("SetOptimalColumnWidth", "Spaltenbreite anpassen", ru_TimerDiffNice($MyInitTimer))
EndFunc   ;==>SetOptimalColumnWidth


; Funktion, die alle markierten Zeile unmarkt oder die betreffenden Zeilen neu markt
; Werte stehen in $aRowsWithHits
;   0 = Image 0 = weisses Feld bzw. kein Icon
;   1 = Image 1 = grüner Pfeil
Func MarkOrUnmarkFoundedRows($Mark = 0)
	Local $IconIndex

	If (Not IsArray($aRowsWithHits)) Or $aRowsWithHits[0] == 0 Then
		_MyDebug("MarkOrUnmarkFoundedRows", "$aRowsWithHits ist kein Array oder leer!")
		Return
	EndIf

	; IconIndex setzen
	If $Mark == 0 Then
		$IconIndex = -2 ; -2 = NoIcon, ist in AutoIt nicht dokumentiert!
	Else
		$IconIndex = 1
	EndIf

	; TimerInit
	$MyInitTimer = TimerInit()

	; Alle Pfeile entfernen
	; _GUICtrlListView_BeginUpdate($GuiListView)
	For $r = 1 To $aRowsWithHits[0]
		_GUICtrlListView_SetItemImage($GuiListView, $aRowsWithHits[$r], $IconIndex)
	Next
	; _GUICtrlListView_EndUpdate($GuiListView)

	; Wenn alle unmarket, dann HelperArray löschen
	If $Mark == 0 Then
		; Debug-Ausgabe
		_MyDebug("MarkOrUnmarkFoundedRows", $aRowsWithHits[0] & " Reihen unmarkiert", ru_TimerDiffNice($MyInitTimer))
		; Array löschen
		$aRowsWithHits = ""
		; Pointer 0
		$PositionInArrayRWH = 0
	Else
		_MyDebug("MarkOrUnmarkFoundedRows", $aRowsWithHits[0] & " Reihen markiert", ru_TimerDiffNice($MyInitTimer))
	EndIf
EndFunc   ;==>MarkOrUnmarkFoundedRows


; Funktion, die ein Item an das Array hinzufügt und dabei den Counter in Zelle 0 um eins erhöht
; Ist das Array noch leer, wird es angelegt. Es wird der Counter zurückgeliefert
; Wenn $OnlyIfNew = 1, dann wird vorher geschaut, ob es schon im Array vorhanden ist
Func MyArrayAdd(ByRef $ArrayMitZelleNull, $value, $OnlyIfNew = 0) ; Fügt zum Array ein Item hinzu und erhöht den Wert in Zelle 0. Ist das Array leer, wird eines erzeugt

	; Schauen, ob es ein Array ist. Wenn nicht, dann wird es angelegt und der Wert hinzugefügt
	If IsArray($ArrayMitZelleNull) Then
		; es ist ein Array
		; ggf. schauen, ob es bereits enthalten ist
		If $OnlyIfNew == 1 Then
			; Raus, wenn es bereist enthalten ist, also größer als 0
			If _ArraySearch($ArrayMitZelleNull, $value, 1) > 0 Then
				Return 0
			EndIf
		EndIf

		; Element hinzufügen
		Local $ret = _ArrayAdd($ArrayMitZelleNull, $value)
		; wenn ungleich -1 dann den Counter erhöhen
		If $ret <> -1 Then
			; um 1 erhöhren in Zelle 0
			Local $Count = $ArrayMitZelleNull[0] + 1
			$ArrayMitZelleNull[0] = $Count
			; Index, also Count zurückliefern
			Return $Count
		Else
			Return -1
		EndIf
	Else
		; Es ist kein Array, daher erzeugen und Wert hinzufügen
		Dim $ArrayMitZelleNull[2]
		$ArrayMitZelleNull[0] = 1
		$ArrayMitZelleNull[1] = $value
		Return 1
	EndIf
EndFunc   ;==>MyArrayAdd


; Funktion, die Debug-Ausgaben macht
Func _MyDebug($VonFunc = "", $Text = "", $a = "", $b = "", $c = "", $d = "", $e = "", $f = "")
	Local $Message = '>' & $VonFunc & '<: ' & $Text

	If $a <> "" Then $Message &= ", " & $a
	If $b <> "" Then $Message &= ", " & $b
	If $c <> "" Then $Message &= ", " & $c
	If $d <> "" Then $Message &= ", " & $d
	If $e <> "" Then $Message &= ", " & $e
	If $f <> "" Then $Message &= ", " & $f

	ConsoleWrite($Message & @CRLF)
EndFunc   ;==>_MyDebug


; Funktion, die ein eindimensionales Array in die COnsole ausgibt
Func _MyDebugArray($VonFunc, $DasArray, $Headline = "")
	Local $temp = ""

	If IsArray($DasArray) Then
		; Array in eine Zeile ausgeben
		For $ee = 0 To UBound($DasArray, 1) - 1
			$temp &= $DasArray[$ee] & ", "
		Next
		_MyDebug($VonFunc, $Headline & "-Array:" & @CRLF & $temp)
	Else
		; Kein Array
		_MyDebug($VonFunc, $Headline & " => Es ist KEIN Array!")
	EndIf
EndFunc   ;==>_MyDebugArray


; Funktion, die einen TimerDiff in "schöne" Zeitangaben umwandelt und zurückliefert
;   $typ == "I", dann muß in $InitOrDiffZahl das Ergebnis von TimerInit stehen
;   $typ == "D", dann muß in $InitOrDiffZahl das Ergebnis von TimerDiff stehen, also das ausgerechnete TimeDifferenz
Func ru_TimerDiffNice($InitOrDiffZahl, $typ = "I")
	Local $hh, $mm, $ss, $ret
	Local $TimerDiffZahl

	If $InitOrDiffZahl <= 0 Then Return ""

	; Schauen, was übergeben wurde
	If $typ == "I" Then
		; Ist InitTimer-Zahl, daher Diff berechnen
		$TimerDiffZahl = TimerDiff($InitOrDiffZahl)
	ElseIf $typ == "D" Then
		; TimerDiff-Zahl direkt übernehmen
		$TimerDiffZahl = $InitOrDiffZahl
	Else
		; Falscher Typ, einfach nichts zurückgeben
		Return ""
	EndIf

	; Integer daraus machen
	$TimerDiffZahl = Int($TimerDiffZahl)

	; hh, mm, ss füllen
	_TicksToTime($TimerDiffZahl, $hh, $mm, $ss)

	If $hh > 0 Then $ret &= StringFormat("%02ih ", $hh)
	If $mm > 0 Then $ret &= StringFormat("%02im ", $mm)
	If $ss > 0 Then $ret &= StringFormat("%02is ", $ss)
	If $ss < 1 Then
		$ret &= $TimerDiffZahl & " ticks"
	Else
		$ret &= "(" & $TimerDiffZahl & " ticks)"
	EndIf

	Return $ret
EndFunc   ;==>ru_TimerDiffNice
#EndRegion Funktionsdefinitionen


#Region _Array2DSearch.au3 from BugFix
;----------------------------------------------------------------------------------------------------------------------
;
;	Function		_Array2DSearch($avArray, $vWhat2Find [, $iDim=-1 [, $iStart=0 [, $iEnd=0 [, $iCaseSense=0 [, $fPartialSearch=False [, $1stFound=False]]]]]])
;
;	Description		Finds all Entry's like $vWhat2Find in an 1D/2D Array
;					Works with all occurences in 2nd Dimension
;					Search in all occurences or only in a given column
;					To set numeric values for default, you can use -1
;
;	Parameter		$avArray		The array to search
;					$vWhat2Find		What to search $avArray for
;		optional	$iDim			Index of Dimension to search; default -1 (all)
;		optional	$iStart			Start array index for search; default 0
;		optional	$iEnd			End array index for search; default 0
;		optional	$iCaseSense		If set to 1 then search is case sensitive; default 0
;		optional	$fPartialSearch	If set to True then executes a partial search. default False
;		optional	$1stFound		If set to True, only one match will be searched; default False
;
;	Return			Succes			Array with Index of matches, Array[0] includes the count of matches
;									In an 2D Array you got for every match [iRow|iCol]
;									Array[0] = 0 if no element found
;									If option 1stFound is set, Array[0] = FoundIndex; if no element found Array[0] = -1
;					Failure			0 and set @error
;									@error = 1	given array is not array
;									@error = 2	given dim is out of range
;									@error = 4	$iStart is out of range
;									@error = 8  $iEnd is out of range
;
;	Author			BugFix  (bugfix@autoit.de)
;----------------------------------------------------------------------------------------------------------------------
Func _Array2DSearch($avArray, $vWhat2Find, $iDim = -1, $iStart = 0, $iEnd = 0, $iCaseSense = 0, $fPartialSearch = False, $1stFound = False)
	Local $error = 0, $1D, $arFound[1] = [0]
	If $1stFound Then $arFound[0] = -1
	If (Not IsArray($avArray)) Then
		SetError(1)
		Return 0
	EndIf
	Local $UBound2nd = UBound($avArray, 2)
	If @error = 2 Then $1D = True
	If ($iEnd = 0) Or ($iEnd = -1) Then $iEnd = UBound($avArray) - 1
	If $iStart = -1 Then $iStart = 0
	If $iCaseSense = -1 Then $iCaseSense = 0
	If $iCaseSense <> 0 Then $iCaseSense = 1
	Select
		Case ($iDim > $UBound2nd) Or ($iDim < -1)
			$error += 2
		Case ($iStart < 0) Or ($iStart > UBound($avArray) - 1)
			$error += 4
		Case ($iEnd < $iStart) Or ($iEnd > UBound($avArray) - 1)
			$error += 8
	EndSelect
	If $error <> 0 Then
		SetError($error)
		Return 0
	EndIf
	If $fPartialSearch <> True Then $fPartialSearch = False
	If $1D Then
		For $i = $iStart To $iEnd
			Select
				Case $iCaseSense = 0 And (Not $fPartialSearch)
					If $avArray[$i] = $vWhat2Find Then
						If $1stFound Then
							$arFound[0] = $i
							Return $arFound
						Else
							ReDim $arFound[UBound($arFound) + 1]
							$arFound[UBound($arFound) - 1] = $i
							$arFound[0] += 1
						EndIf
					EndIf
				Case $iCaseSense = 1 And (Not $fPartialSearch)
					If $avArray[$i] == $vWhat2Find Then
						If $1stFound Then
							$arFound[0] = $i
							Return $arFound
						Else
							ReDim $arFound[UBound($arFound) + 1]
							$arFound[UBound($arFound) - 1] = $i
							$arFound[0] += 1
						EndIf
					EndIf
				Case $iCaseSense = 0 And $fPartialSearch
					If StringInStr($avArray[$i], $vWhat2Find) Then
						If $1stFound Then
							$arFound[0] = $i
							Return $arFound
						Else
							ReDim $arFound[UBound($arFound) + 1]
							$arFound[UBound($arFound) - 1] = $i
							$arFound[0] += 1
						EndIf
					EndIf
				Case $iCaseSense = 1 And $fPartialSearch
					If StringInStr($avArray[$i], $vWhat2Find, 1) Then
						If $1stFound Then
							$arFound[0] = $i
							Return $arFound
						Else
							ReDim $arFound[UBound($arFound) + 1]
							$arFound[UBound($arFound) - 1] = $i
							$arFound[0] += 1
						EndIf
					EndIf
			EndSelect
		Next
	Else
		For $i = $iStart To $iEnd
			If $iDim = -1 Then
				Select
					Case $iCaseSense = 0 And (Not $fPartialSearch)
						For $k = 0 To $UBound2nd - 1
							If $avArray[$i][$k] = $vWhat2Find Then
								If $1stFound Then
									$arFound[0] = $i & '|' & $k
									Return $arFound
								Else
									ReDim $arFound[UBound($arFound) + 1]
									$arFound[UBound($arFound) - 1] = $i & '|' & $k
									$arFound[0] += 1
								EndIf
							EndIf
						Next
					Case $iCaseSense = 1 And (Not $fPartialSearch)
						For $k = 0 To $UBound2nd - 1
							If $avArray[$i][$k] == $vWhat2Find Then
								If $1stFound Then
									$arFound[0] = $i & '|' & $k
									Return $arFound
								Else
									ReDim $arFound[UBound($arFound) + 1]
									$arFound[UBound($arFound) - 1] = $i & '|' & $k
									$arFound[0] += 1
								EndIf
							EndIf
						Next
					Case $iCaseSense = 0 And $fPartialSearch
						For $k = 0 To $UBound2nd - 1
							If StringInStr($avArray[$i][$k], $vWhat2Find) Then
								If $1stFound Then
									$arFound[0] = $i & '|' & $k
									Return $arFound
								Else
									ReDim $arFound[UBound($arFound) + 1]
									$arFound[UBound($arFound) - 1] = $i & '|' & $k
									$arFound[0] += 1
								EndIf
							EndIf
						Next
					Case $iCaseSense = 1 And $fPartialSearch
						For $k = 0 To $UBound2nd - 1
							If StringInStr($avArray[$i][$k], $vWhat2Find, 1) Then
								If $1stFound Then
									$arFound[0] = $i & '|' & $k
									Return $arFound
								Else
									ReDim $arFound[UBound($arFound) + 1]
									$arFound[UBound($arFound) - 1] = $i & '|' & $k
									$arFound[0] += 1
								EndIf
							EndIf
						Next
				EndSelect
			Else
				Select
					Case $iCaseSense = 0 And (Not $fPartialSearch)
						If $avArray[$i][$iDim] = $vWhat2Find Then
							If $1stFound Then
								$arFound[0] = $i & '|' & $iDim
								Return $arFound
							Else
								ReDim $arFound[UBound($arFound) + 1]
								$arFound[UBound($arFound) - 1] = $i & '|' & $iDim
								$arFound[0] += 1
							EndIf
						EndIf
					Case $iCaseSense = 1 And (Not $fPartialSearch)
						If $avArray[$i][$iDim] == $vWhat2Find Then
							If $1stFound Then
								$arFound[0] = $i & '|' & $iDim
								Return $arFound
							Else
								ReDim $arFound[UBound($arFound) + 1]
								$arFound[UBound($arFound) - 1] = $i & '|' & $iDim
								$arFound[0] += 1
							EndIf
						EndIf
					Case $iCaseSense = 0 And $fPartialSearch
						If StringInStr($avArray[$i][$iDim], $vWhat2Find) Then
							If $1stFound Then
								$arFound[0] = $i & '|' & $iDim
								Return $arFound
							Else
								ReDim $arFound[UBound($arFound) + 1]
								$arFound[UBound($arFound) - 1] = $i & '|' & $iDim
								$arFound[0] += 1
							EndIf
						EndIf
					Case $iCaseSense = 1 And $fPartialSearch
						If StringInStr($avArray[$i][$iDim], $vWhat2Find, 1) Then
							If $1stFound Then
								$arFound[0] = $i & '|' & $iDim
								Return $arFound
							Else
								ReDim $arFound[UBound($arFound) + 1]
								$arFound[UBound($arFound) - 1] = $i & '|' & $iDim
								$arFound[0] += 1
							EndIf
						EndIf
				EndSelect
			EndIf
		Next
	EndIf
	Return $arFound
EndFunc   ;==>_Array2DSearch
#EndRegion _Array2DSearch.au3 from BugFix