#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <GuiTreeView.au3>
#include <StructureConstants.au3>
#include <TreeViewConstants.au3>
#include <WindowsConstants.au3>

Opt('MustDeclareVars', 1)

Global $hGui = GUICreate('FileExplorer', 400, 400)

Global Const $Delim = '\', $Delim1 = '|'

Global $hTreeview = GUICtrlCreateTreeView(10, 10, 380, 360)
Global $hWndTreeview = GUICtrlGetHandle($hTreeview)
Global $hOk = GUICtrlCreateButton('Ok', 240, 375, 60, 22)
Global $hCancel = GUICtrlCreateButton('Cancel', 320, 375, 60, 22)

Global $hImage = _GUIImageList_Create(16, 16, 5, 1)
_GUIImageList_AddIcon($hImage, 'shell32.dll', 3) ; Verzeichnis-Icon
_GUIImageList_AddIcon($hImage, 'shell32.dll', 110) ; Verzeichnis-Icon mit Haken
_GUIImageList_AddIcon($hImage, 'shell32.dll', 1) ; Datei-Icon
_GUIImageList_AddIcon($hImage, 'shell32.dll', 5) ; Diskette
_GUIImageList_AddIcon($hImage, 'shell32.dll', 7) ; Wechseldatenträger
_GUIImageList_AddIcon($hImage, 'shell32.dll', 8) ; Festplatte
_GUIImageList_AddIcon($hImage, 'shell32.dll', 11) ; CDROM
_GUIImageList_AddIcon($hImage, 'shell32.dll', 12) ; Netzwerklaufwerk
_GUIImageList_AddIcon($hImage, 'shell32.dll', 53) ; Unbekannt
_GUICtrlTreeView_SetNormalImageList($hTreeview, $hImage)

GUISetState()
GUICtrlSetStyle($hTreeview, Default, BitOR($WS_EX_COMPOSITED, $WS_EX_CLIENTEDGE))

If ToolTip('Please wait...', Default, Default, 'Read Directory', 1) Then Local $aDrives = DriveGetDrive('ALL'), $iLWindex, $hRoot
For $i = 1 To $aDrives[0]
	$iLWindex = 0
	Switch DriveGetType($aDrives[$i])
		Case 'Fixed'
			$iLWindex = 5
		Case 'CDROM'
			$iLWindex = 6
		Case 'RAMDisk'
			$iLWindex = 7
		Case 'Removable'
			$iLWindex = 4
			If StringLeft($aDrives[$i], 2) = 'a:' Or StringLeft($aDrives[$i], 2) = 'b:' Then $iLWindex = 3
		Case Else
			$iLWindex = 8
	EndSwitch
	$hRoot = _GUICtrlTreeView_Add($hTreeview, $hTreeview, StringUpper($aDrives[$i]), $iLWindex, $iLWindex)
	If DriveStatus($aDrives[$i]) <> 'READY' Then ContinueLoop
	If _GUICtrlTreeView_BeginUpdate($hTreeview) And _GUICtrlTreeView_FileExplorer($hTreeview, $hRoot, $aDrives[$i]) Then _GUICtrlTreeView_EndUpdate($hTreeview)
Next
ToolTip('')

GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')
While True
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE, $hCancel
			Exit
		Case $hOk
			MsgBox(0, 'Selected Path/File', StringReplace(_GUICtrlTreeView_GetTree($hTreeview, _GUICtrlTreeView_GetSelection($hTreeview)), $Delim1, $Delim))
	EndSwitch
WEnd

Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
	Local $hChild, $hITEM, $tNMTREEVIEW = DllStructCreate($tagNMTREEVIEW, $ilParam)
	If DllStructGetData($tNMTREEVIEW, 'hWndFrom') = $hWndTreeview Then
		Switch DllStructGetData($tNMTREEVIEW, 'Code')
			Case $TVN_ITEMEXPANDINGA, $TVN_ITEMEXPANDINGW
				Switch DllStructGetData($tNMTREEVIEW, 'Action')
					Case $TVE_EXPAND
						If ToolTip('Please wait...', Default, Default, 'Read Directory', 1) Then $hITEM = DllStructGetData($tNMTREEVIEW, 'NewhItem')
						If _GUICtrlTreeView_GetExpanded($hTreeview, $hITEM) Then Return $GUI_RUNDEFMSG
						$hChild = _GUICtrlTreeView_GetFirstChild($hTreeview, $hITEM)
						If Not $hChild Then Return $GUI_RUNDEFMSG
						If _GUICtrlTreeView_BeginUpdate($hTreeview) Then _GUICtrlTreeView_DeleteChildren($hTreeview, $hChild)
						_GUICtrlTreeView_FileExplorer($hTreeview, $hChild, StringReplace(_GUICtrlTreeView_GetTree($hTreeview, $hChild), $Delim1, $Delim))
						Do
							$hChild = _GUICtrlTreeView_GetNextChild($hTreeview, $hChild)
							If Not $hChild Then ExitLoop
							_GUICtrlTreeView_DeleteChildren($hTreeview, $hChild)
							_GUICtrlTreeView_FileExplorer($hTreeview, $hChild, StringReplace(_GUICtrlTreeView_GetTree($hTreeview, $hChild), $Delim1, $Delim))
						Until False
						If _GUICtrlTreeView_EndUpdate($hTreeview) Then ToolTip('')
				EndSwitch
		EndSwitch
	EndIf
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_NOTIFY

Func _GUICtrlTreeView_FileExplorer($hTreeview, $hITEM, $sPath)
	Local $sFileList, $sFolderList, $aDirList, $hSearch, $sFile
	Local $iHidden = RegRead('HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced', 'Hidden') - 1
	Local $iSuperHidden = Not RegRead('HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced', 'ShowSuperHidden')
	$hSearch = FileFindFirstFile($sPath & $Delim & '*')
	If $hSearch = -1 Then Return True
	Do
		$sFile = FileFindNextFile($hSearch)
		If @error Then ExitLoop
		Switch @extended
			Case False
				If $iHidden And StringInStr(FileGetAttrib($sPath & $Delim & $sFile), 'H') Then ContinueLoop
				If $iSuperHidden And StringInStr(FileGetAttrib($sPath & $Delim & $sFile), 'S') Then ContinueLoop
				$sFileList &= $sFile & $Delim1
			Case True
				If _IsReparsePoint($sPath & $Delim & $sFile) Then ContinueLoop
				$sFolderList &= $sFile & $Delim1
		EndSwitch
	Until False
	FileClose($hSearch)
	If $sFolderList & $sFileList = '' Then Return True
	$aDirList = StringSplit(StringTrimRight($sFolderList & $sFileList, 1), $Delim1, 2)
	For $sFile In $aDirList
		If StringInStr(FileGetAttrib($sPath & $Delim & $sFile), 'D') Then
			_GUICtrlTreeView_AddChild($hTreeview, $hITEM, $sFile, 0, 1)
		Else
			_GUICtrlTreeView_AddChild($hTreeview, $hITEM, $sFile, 2, 2)
		EndIf
	Next
	Return True
EndFunc   ;==>_GUICtrlTreeView_FileExplorer

Func _IsReparsePoint($FLS) ; progandy
	Dim Static $K32 = DllOpen('kernel32.dll')
	Dim $DA = DllCall($K32, 'dword', 'GetFileAttributesW', 'wstr', $FLS)
	If @error Then Return SetError(1, @error, False)
	Return BitAND($DA[0], 1024) = 1024
EndFunc   ;==>_IsReparsePoint