;-- TIME_STAMP   2018-10-08 17:52:09   v 1.0

Opt('MustDeclareVars', 1)

#Region    ;************ Includes ************
#include-once
#include <WindowsConstants.au3>
#include <Date.au3>
#include <GuiComboBoxEx.au3>
#include <GuiListBox.au3>
#include <GuiListView.au3>
#include <WinAPIProc.au3>
#include <WinAPILocale.au3>
#include <WinAPISysWin.au3>
#EndRegion ;************ Includes ************

Global Enum $WGC_SHOWALL, $WGC_SHOWVISIBLE, $WGC_SHOWHIDDEN

Global $sHeader_ProcessInfo = 'iCount|iPID|sProcessName|sCommandLine|sUser|bWow64|sWorkingDir|sRunTime|iPIDParentProcess|sParentProcessName|aParentProcessWindows|aProcessList'
Global $sHeader_Controls = 'HWND|CLASS|NN|ID|AU3|Visible|xPos|yPos|width|hight|Title|Text'
Global Enum $eHWND, $eCLASS, $eNN, $eID, $eAU3, $eVisible, $exPos, $eyPos, $ewidth, $ehight, $eTitle, $eText
Global Enum $eName, $eErw, $eSize, $eDatum, $eAttr
Global Enum $eHeader_ProcessInfo, $eHeader_Controls, $eHeader_Both

Func _WinGetHeader($iHeader = 1)
	Local $vReturn
	Switch $iHeader
		Case $eHeader_ProcessInfo
			$vReturn = $sHeader_ProcessInfo
		Case $eHeader_Controls
			$vReturn = $sHeader_Controls
		Case $eHeader_Both
			Dim $vReturn[2] = [$sHeader_ProcessInfo, $sHeader_Controls]
		Case Else
			Return SetError(1, 0, False)
	EndSwitch
	Return
EndFunc


; #FUNCTION# ================================================================================================================
; Name...........: _WinGetControls
; Description ...: Liefert ein 2D-Array mit den Controls eines Fensters.
; Syntax.........: _WinGetControls($hWnd [, $iVisible = $WGC_SHOWVISIBLE] [, $bProcessInfo = True] [, $bExtended = False])
; Parameters ....: $hWnd         - HWND des Fensters (z.B. Rückgabewert von GUICreate)
;                  $iVisible     - $WGC_SHOWALL (0) = alle, $WGC_SHOWVISIBLE (1) = nur sichtbare, $WGC_SHOWHIDDEN (2) = nur sichtbare Controls übergeben
;                  $bProcessInfo - wenn True, werden Informationen über den Process, dem das Window ($hWnd) gehört, in den Spalten [0][1] - [0][11] übergeben
;                  $bExtended    - wenn True, wird der Inhalt von Listboxen und ListViews als 2D-Array in der Spalte Text übergeben
; Return values .: Erfolg:       - 2D-Array mit den Controls eines Fensters.
;                                - [0][ 0]         - Anzahl der Controls
;           $bProcessInfo = True - [0][ 1-11]      - iPID|sProcessName|sCommandLine|sUser|bWow64|sWorkingDir|sRunTime|iPIDParentProcess|sParentProcessName|aParentProcessWindows|aProcessList
;                                - [n][ 0] HWND    - HWND des Controls
;                                - [n][ 1] CLASS   - Klasse des Controls
;                                - [n][ 2] NN      - ClassNN des Controls
;                                - [n][ 3] ID      - ID des Controls
;                                - [n][ 4] AU3     - AU3-Bezeichnung des Controls
;                                - [n][ 5] Visible - Sichtbar? 1 = ja, 0 = nein
;                                - [n][ 6] xPos    - Horizontale Position des Controls
;                                - [n][ 7] yPos    - Vertikale Position des Controls
;                                - [n][ 8] width   - Breite des Controls
;                                - [n][ 9] hight   - Höhe des Controls
;                                - [n][10] Title   - Titel des Windows/Controls
;                                - [n][11] Text    - Text des Controls
;                  Fehler:       - False, @error = 1
; Author ........: Großater & progandy & UEZ (www.autoit.de)
; Modified.......: Bitnugger - Position, Größe, Text des Controls und ProcessInfo hinzugefügt
; Remarks .......: ProcessInfo funktioniert mom. nur bei einem Top-Window
; Related .......:
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _WinGetControls($hWnd, $bVisible = False, $bProcessInfo = True, $bExtended = False)
	If Not IsHWnd($hWnd) Then Return SetError(1, 0, False)
	Local $hParent = _WinAPI_GetAncestor($hWnd, $GA_ROOT)
	If IsHWnd($hParent) And $hParent <> $hWnd Then
		ConsoleWrite('! $hWnd is a Child-Window! ClassName = ' & _WinAPI_GetClassName($hWnd) & @CRLF)
		$hWnd = $hParent
	EndIf

	Local Const $GWL_STYLE = 0xFFFFFFF0
	Local Const $BS_AUTOCHECKBOX = 0x0003
	Local Const $BS_CHECKBOX = 0x0002
	Local Const $BS_GROUPBOX = 0x0007
	Local Const $BS_RADIOBUTTON = 0x0004
	Local Const $BS_AUTORADIOBUTTON = 0x0009
	Local Const $ES_MULTILINE = 4
	Local Const $ES_WANTRETURN = 4096
	Local Const $SS_ICON = 0x3
	Local Const $SS_BITMAP = 0xE
	Local Const $WS_VSCROLL = 0x00200000
	Local Const $ES_EDIT = BitOR($ES_WANTRETURN, $WS_VSCROLL)
	Local $iUBoundControls = 100
	Local $iUBoundClasses = 50
	Local $aControls[$iUBoundControls + 1][12]
	Local $aClasses[$iUBoundClasses + 1][2]
	Local $aResult, $sAU3, $iClassesCount, $iControlsCount, $sClass, $bClassExist, $hControl, $iControlID, $iControlNN, $iStyles
	Local $aClassList = StringSplit(StringStripWS(WinGetClassList($hWnd), 2), @LF)
	$aControls[0][0] = 0
	$aClasses[0][0] = 0
	For $i = 1 To $aClassList[0]
		If $aClassList[$i] = '' Then ContinueLoop

		$sClass = $aClassList[$i]
		$bClassExist = False
		$iClassesCount = $aClasses[0][0]
		For $j = 1 To $iClassesCount
			If $aClasses[$j][0] = $sClass Then
				$iControlNN = $aClasses[$j][1] + 1
				$aClasses[$j][1] = $iControlNN
				$bClassExist = True
				ExitLoop
			EndIf
		Next
		If Not $bClassExist Then
			$iControlNN = 1
			$iClassesCount += 1
			If $iClassesCount > $iUBoundClasses Then
				$iUBoundClasses += 50
				ReDim $aClasses[$iUBoundClasses + 1][2]
			EndIf
			$aClasses[0][0] = $iClassesCount
			$aClasses[$iClassesCount][0] = $sClass
			$aClasses[$iClassesCount][1] = $iControlNN
		EndIf
		$hControl = ControlGetHandle($hWnd, "", $sClass & $iControlNN)
		If Not IsHWnd($hControl) Then
			ConsoleWrite('! $hControl             = ' & $hControl & @CRLF)
			ConsoleWrite('! $sClass & $iControlNN = ' & $sClass & $iControlNN & @CRLF)
			ContinueLoop
		EndIf
		$aResult = DllCall("User32.dll", "Int", "GetDlgCtrlID", "HWND", $hControl)
		If @error Or $aResult[0] = 0 Then
			$iControlID = ""
		Else
			$iControlID = $aResult[0]
		EndIf
		$iControlsCount = $aControls[0][0] + 1
		If $iControlsCount > $iUBoundControls Then
			$iUBoundControls += 100
			ReDim $aControls[$iUBoundControls + 1][12]
		EndIf

    	; Ausgeliehen aus der WinAPI.au3
    	Local $sFuncName = "GetWindowLongW"
    	If @AutoItX64 Then $sFuncName = "GetWindowLongPtrW"
    	$aResult = DllCall("User32.dll", "LONG_PTR", $sFuncName, "HWND", $hControl, "INT", $GWL_STYLE)
    	$iStyles = $aResult[0]
    	; Erweiterung nach Vorschlag von UEZ
		Local $sWinTitle = '', $sControlText = '', $sEditText = ''
    	Switch $sClass
        	Case "Button"
            	If BitAND($iStyles, $BS_GROUPBOX) = $BS_GROUPBOX Then
                	$sAU3 = "Group"
            	ElseIf BitAND($iStyles, $BS_CHECKBOX) = $BS_CHECKBOX Then
                	$sAU3 = "Checkbox"
            	ElseIf BitAND($iStyles, $BS_AUTOCHECKBOX) = $BS_AUTOCHECKBOX Then
                	$sAU3 = "Checkbox"
            	ElseIf BitAND($iStyles, $BS_RADIOBUTTON) = $BS_RADIOBUTTON Then
                	$sAU3 = "Radio"
            	ElseIf BitAND($iStyles, $BS_AUTORADIOBUTTON) = $BS_AUTORADIOBUTTON Then
                	$sAU3 = "Radio"
            	Else
                	$sAU3 = "Button"
            	EndIf
        	Case "Static"
            	If BitAND($iStyles, $SS_ICON) = $SS_ICON Then
                	$sAU3 = "Icon"
            	ElseIf BitAND($iStyles, $SS_BITMAP) = $SS_BITMAP Then
                	$sAU3 = "Pic"
            	Else
                	$sAU3 = "Label"
					If $bExtended = True Then $aControls[$iControlsCount][11] = ControlGetText($hControl, '', '')
            	EndIf
        	Case "Edit", "TPathPanel"
            	If BitAND($iStyles, $ES_EDIT) = $ES_EDIT Then
                	$sAU3 = "Edit"
            	Else
                	$sAU3 = "Input"
            	EndIf
				If $bExtended = True Then $aControls[$iControlsCount][11] = ControlGetText($hControl, '', '')
        	Case "SysAnimate32"
            	$sAU3 = "AVI"
        	Case "ComboBox", "TMyComboBox"
            	$sAU3 = "Combo"
				If $bExtended = True Then $aControls[$iControlsCount][11] = _GUICtrlComboBoxEx_GetList($hControl)
        	Case "SysDateTimePick32"
            	$sAU3 = "Date"
        	Case "ListBox", "TMyListBox"
            	$sAU3 = "List"
				If $bExtended = True Then $aControls[$iControlsCount][11] = _GetListBoxItems($hControl)
        	Case "SysListView32"
            	$sAU3 = "ListView"
				If $bExtended = True Then $aControls[$iControlsCount][11] = _GetListViewItems($hControl)
        	Case "SysMonthCal32"
            	$sAU3 = "MonthCal"
        	Case "msctls_progress32"
            	$sAU3 = "Progress"
        	Case "msctls_trackbar32"
            	$sAU3 = "Slider"
        	Case "SysTabControl32", "SciTeTabCtrl"
            	$sAU3 = "Tab"
        	Case "SysTreeView32"
            	$sAU3 = "TreeView"
        	Case "msctls_updown32"
            	$sAU3 = "UpDown"
			Case "msctls_statusbar32"
				$sAU3 = "Statusbar"
        	Case Else
            	$sAU3 = ""
		EndSwitch
		If $bVisible = True And ControlCommand($hControl, '', '', "IsVisible", "") = 0 Then ContinueLoop	; nur sichtbare Controls anzeigen?
		Local $aControlPos = ControlGetPos($hControl, '', '')
		Local $sControlText = ControlGetText($hControl, '', '')
		Local $sWinTitle = WinGetTitle($hControl)
		Local $iCR = StringInStr($sWinTitle, @CR)
		If $iCR > 1 Then
			$sWinTitle = StringMid($sWinTitle, 1, $iCR -1)
		EndIf
		Local $iLF = StringInStr($sWinTitle, @LF)
		If $iLF > 1 Then
			$sWinTitle = StringMid($sWinTitle, 1, $iLF -1)
		EndIf
		$aControls[0][0] = $iControlsCount
		$aControls[$iControlsCount][0] = $hControl
		$aControls[$iControlsCount][1] = $sClass
		$aControls[$iControlsCount][2] = $iControlNN
		$aControls[$iControlsCount][3] = $iControlID
    	$aControls[$iControlsCount][4] = $sAU3
		$aControls[$iControlsCount][5] = ControlCommand($hControl, '', '', "IsVisible", "")
		$aControls[$iControlsCount][6] = $aControlPos[0]
		$aControls[$iControlsCount][7] = $aControlPos[1]
		$aControls[$iControlsCount][8] = $aControlPos[2]
		$aControls[$iControlsCount][9] = $aControlPos[3]
		$aControls[$iControlsCount][10] = $sWinTitle
		If $aControls[$iControlsCount][11] = '' And $aControls[$iControlsCount][10] <> $sControlText Then $aControls[$iControlsCount][11] = $sControlText
	Next
	$iControlsCount = $aControls[0][0] + 1
	If $hControl = "" Then $iControlsCount -= 1
	ReDim $aControls[$iControlsCount][12]

	ConsoleWrite('UBound($aControls) = ' & UBound($aControls) & @CRLF)
	ConsoleWrite('$bProcessInfo      = ' & $bProcessInfo & @CRLF)
	If UBound($aControls) And $bProcessInfo Then
		Local $aProcessInfo = _GetProcessInfo($hWnd)
;~ 		_ArrayDisplay($aProcessInfo, '$aProcessInfo')
		For $p = 1 To UBound($aControls, 2) -1 Step 1
;~ 			_ArrayDisplay($aControls, '$aControls', '', 0, Default, $sHeader_Controls)
			$aControls[0][$p] = $aProcessInfo[$p -1]
		Next
	EndIf

	Return $aControls
EndFunc   ;==>_WinGetControls
; ===============================================================================================================================

Func _GetProcessInfo($hWnd)
	Local $iPID = WinGetProcess($hWnd)
	Local $sProcessName = _WinAPI_GetProcessName($iPID)
	Local $sProcessCommandLine = _WinAPI_GetProcessCommandLine($iPID)
	Local $aProcessUser = _WinAPI_GetProcessUser($iPID)
	Local $bIsWow64Process = _WinAPI_IsWow64Process($iPID)
	Local $sProcessWorkingDirectory = _WinAPI_GetProcessWorkingDirectory($iPID)
	Local $aFT = _WinAPI_GetProcessTimes($iPID)
	Local $tFT = _Date_Time_FileTimeToLocalFileTime($aFT[0])
	Local $tST = _Date_Time_FileTimeToSystemTime($tFT)
	Local $sProcessRunTime = _WinAPI_GetTimeFormat(0, $tST)
	Local $iPIDParentProcess = _WinAPI_GetParentProcess($iPID)
	Local $sParentProcessName = _WinAPI_GetProcessName($iPIDParentProcess)
	Local $aParentProcessWindows = _WinAPI_EnumProcessWindows($iPIDParentProcess, True)
	Local $aProcessList = ProcessList($sParentProcessName)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 0   var: $hWnd                     --> " & $hWnd & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 1   var: $iPID                     --> " & $iPID & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 2   var: $sProcessName             --> " & $sProcessName & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 3   var: $sProcessCommandLine      --> " & $sProcessCommandLine & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 4   var: $aProcessUser             --> " & _ArrayToString($aProcessUser, '@') & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 5   var: $bIsWow64Process          --> " & $bIsWow64Process & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 6   var: $sProcessWorkingDirectory --> " & $sProcessWorkingDirectory & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 7   var: $sProcessRunTime          --> " & $sProcessRunTime & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 8   var: $iPIDParentProcess          --> " & $iPIDParentProcess & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & " 9   var: $sParentProcessName         --> " & $sParentProcessName & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & "10   var: $aParentProcessWindows      --> " & _ArrayToString($aParentProcessWindows, ', ') & @CRLF)
;~ 	ConsoleWrite("@@ Debug line" & @TAB & @ScriptLineNumber & "11   var: $aProcessList               --> " & _ArrayToString($aProcessList, ', ') & @CRLF & @CRLF & @CRLF)

	Local $aProcessInfo = [$iPID, $sProcessName, $sProcessCommandLine, _ArrayToString($aProcessUser, '@'), $bIsWow64Process, $sProcessWorkingDirectory, $sProcessRunTime, $iPIDParentProcess, $sParentProcessName, $aParentProcessWindows, $aProcessList]
	Return $aProcessInfo
EndFunc

Func _GetListViewItems($hWnd)
	Local $aListViewItem, $iItemCount = _GUICtrlListView_GetItemCount($hWnd), $iColumnCount = _GUICtrlListView_GetColumnCount($hWnd), $aItem, $aListViewItems[$iItemCount][$iColumnCount]
	If $iItemCount > 0 Then
		For $i = 0 To $iItemCount -1 Step 1
			$aItem = _GUICtrlListView_GetItemTextArray($hWnd, $i)
			For $j = 0 To $iColumnCount -1 Step 1
				ConsoleWrite(StringFormat('$i = %i, $j = %i\r', $i, $j))
				$aListViewItems[$i][$j] = $aItem[$j]
			Next
		Next
		Return $aListViewItems
	EndIf
EndFunc

Func _GetListBoxItems($hWnd)
	Local $iListBoxItemsCount = _GUICtrlListBox_GetCount($hWnd), $aListBoxItems[$iListBoxItemsCount]
	If $iListBoxItemsCount <> -1 Then
		For $i = 0 To $iListBoxItemsCount -1 Step 1
			$aListBoxItems[$i] = _GUICtrlListBox_GetText($hWnd, $i)
		Next
;~ 		_ArrayDisplay($aListBoxItems, '$aListBoxItems')
		Return $aListBoxItems
	EndIf
EndFunc
