; http://autoit-script.ru/index.php?topic=3725.0
#Include <GUIConstantsEx.au3>
#Include <GUIImageList.au3>
#Include <GUITreeView.au3>
#Include <TreeViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>
Opt('MustDeclareVars', 1)
Global $hForm, $hImageList, $hTreeView, $hIcon, $hSelect = 0, $hInput, $Input, $Dummy
Global $tSHSII, $Index, $Stock[3], $Count = 0, $sPath, $sRoot = @HomeDrive
Global $Cache[101][3] = [[0]], $Link[101][2] = [[0]]
$hForm = GUICreate('MyGUI', 600, 600)
$Input = GUICtrlCreateInput('', 20, 20, 560, 19)
$hInput = GUICtrlGetHandle(-1)
GUICtrlSetState(-1, $GUI_DISABLE)
;~$hTreeView = _GUICtrlTreeView_Create($hForm, 20, 50, 560, 530, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
;~_GUICtrlTreeView_SetHeight($hTreeView, 18)
GUICtrlCreateTreeView(20, 50, 560, 526, -1, $WS_EX_CLIENTEDGE)
$hTreeView = GUICtrlGetHandle(-1)
$Dummy = GUICtrlCreateDummy()
$hImageList = _GUIImageList_Create(_WinAPI_GetSystemMetrics($SM_CXSMICON), _WinAPI_GetSystemMetrics($SM_CYSMICON), 5, 1)
If _WinAPI_GetVersion() >= '6.0' Then
_WinAPI_SetWindowTheme($hTreeView, 'Explorer')
$Stock[0] = $SIID_DOCNOASSOC
$Stock[1] = $SIID_FOLDER
$Stock[2] = $SIID_FOLDEROPEN
For $i = 0 To 2
$tSHSII = _WinAPI_ShellGetStockIconInfo($Stock[$i], BitOR($SHGSI_ICON, $SHGSI_SMALLICON))
$hIcon = DllStructGetData($tSHSII, 'hIcon')
_GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
_WinAPI_DestroyIcon($hIcon)
Next
Else
$Stock[0] = 0
$Stock[1] = 3
$Stock[2] = 4
For $i = 0 To 2
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', $Stock[$i])
Next
EndIf
If _WinAPI_GetVersion() >= '6.1' Then
Dim $hIcon[3]
$hIcon[0] = _GUIImageList_GetIcon($hImageList, 1)
$hIcon[1] = _WinAPI_ExtractIcon(@SystemDir & '\ntshrui.dll', 3, 1)
$hIcon[2] = _WinAPI_AddIconOverlay($hIcon[0], $hIcon[1])
_GUIImageList_ReplaceIcon($hImageList, -1, $hIcon[2])
$hIcon[2] = _WinAPI_AddIconTransparency($hIcon[2], 50, 1)
_GUIImageList_ReplaceIcon($hImageList, -1, $hIcon[2])
For $i = 0 To 2
_WinAPI_DestroyIcon($hIcon[$i])
Next
Else
$hIcon = _GUIImageList_GetIcon($hImageList, 1)
_GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
$hIcon = _WinAPI_AddIconTransparency($hIcon, 50, 1)
_GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
_WinAPI_DestroyIcon($hIcon)
EndIf
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
_GUICtrlTreeView_SetUnicodeFormat($hTreeView)
$sRoot = StringRegExpReplace(FileGetLongName($sRoot), '\\+\Z', '')
$sPath = StringRegExpReplace($sRoot, '^.*\\', '')
If StringInStr($sPath, ':') Then
$sRoot &= '\'
$sPath &= '\'
EndIf
If _WinAPI_PathIsDirectory($sRoot) Then
$Index = _TVAddIcon($hTreeView, $sRoot)
If Not _TVIsEmpty($sRoot) Then
_GUICtrlTreeView_AddChild($hTreeView, _GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, $Index, $Index), '', 0, 0)
Else
Switch @error
Case 0 ; OK
_GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, $Index, $Index)
Case 1 ; Access denied
If StringInStr(FileGetAttrib($sRoot), 'H') Then
$Index = 4
Else
$Index = 3
EndIf
_GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, $Index, $Index)
Case Else
EndSwitch
EndIf
EndIf
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()
_GUICtrlTreeView_Expand($hTreeView, _GUICtrlTreeView_GetFirstItem($hTreeView))
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
Case $Dummy
GUISetCursor(1, 1)
_TVUpdate($hTreeView, GUICtrlRead($Dummy))
GUISetCursor(2, 0)
EndSwitch
WEnd
Func _TVAddIcon($hTV, $sPath, $fOpen = 0)
Local $hIL, $hIcon = 0, $Hidden, $ID, $Index, $Item = 0
Local $hImageList = _GUICtrlTreeView_GetNormalImageList($hTV)
Local $Flags = BitOR($SHGFI_SMALLICON, $SHGFI_SYSICONINDEX)
Local $tSHFI = DllStructCreate($tagSHFILEINFO)
Local $Attrib = FileGetAttrib($sPath)
If $fOpen Then
$Flags = BitOR($SHGFI_OPENICON, $Flags)
EndIf
If StringInStr($Attrib, 'D') Then
$hIL = _WinAPI_ShellGetFileInfo($sPath, $Flags, 0, $tSHFI)
If Not $hIL Then
If $fOpen Then
Return 2
Else
Return 1
EndIf
EndIf
Else
$hIL = _WinAPI_ShellGetFileInfo($sPath, BitOR($SHGFI_ICON, $SHGFI_OVERLAYINDEX, $SHGFI_USEFILEATTRIBUTES, $Flags), 0, $tSHFI)
If $hIL Then
$hIcon = DllStructGetData($tSHFI, 'hIcon')
ELse
Return 0
EndIf
EndIf
$Index = DllStructGetData($tSHFI, 'iIcon')
If (Not _WinAPI_PathIsRoot($sPath)) And (StringInStr($Attrib, 'H')) Then
$Hidden = 1
$ID = 2
Else
$Hidden = 0
$ID = 1
EndIf
For $i = 1 To $Cache[0][0]
If $Cache[$i][0] = $Index Then
$Item = $i
ExitLoop
EndIf
Next
If $Item Then
If $Cache[$Item][$ID] <> -1 Then
If $hIcon Then
_WinAPI_DestroyIcon($hIcon)
EndIf
Return $Cache[$Item][$ID]
EndIf
Else
$Cache[0][0] += 1
If $Cache[0][0] > UBound($Cache) - 1 Then
ReDim $Cache[$Cache[0][0] + 100][3]
EndIf
$Cache[$Cache[0][0]][0] = $Index
$Cache[$Cache[0][0]][1] = -1
$Cache[$Cache[0][0]][2] = -1
$Item = $Cache[0][0]
EndIf
If Not $hIcon Then
$hIcon = DllCall('comctl32.dll', 'handle', 'ImageList_GetIcon', 'handle', $hIL, 'int', _WinAPI_LoWord($Index), 'uint', _WinAPI_HiWord($Index))
If (Not @error) And ($hIcon[0]) Then
$hIcon = $hIcon[0]
Else
Return 0
EndIf
EndIf
If $Hidden Then
$hIcon = _WinAPI_AddIconTransparency($hIcon, 50, 1)
If Not $hIcon Then
Return 0
EndIf
EndIf
$Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
_WinAPI_DestroyIcon($hIcon)
If $Index = -1 Then
Return 0
EndIf
$Cache[$Item][$ID] = $Index
Return $Index
EndFunc ;==>_TVAddIcon
Func _TVGetPath($hTV, $hItem, $sRoot)
Local $Path = ''
For $i = 1 To $Link[0][0]
If $Link[$i][0] = $hItem Then
$Path = $Link[$i][1]
ExitLoop
EndIf
Next
If Not $Path Then
$Path = StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $hItem), '([|]+)|(\\[|])', '\\')
If Not $Path Then
Return ''
EndIf
EndIf
If Not StringInStr($Path, ':') Then
Return StringRegExpReplace($sRoot, '(\\[^\\]*(\\|)+)\Z', '\\') & $Path
EndIf
Return $Path
EndFunc ;==>_TVGetPath
Func _TVIsEmpty($sPath)
Local $hSearch, $Result = 1
$hSearch = FileFindFirstFile($sPath & '\*')
If $hSearch = -1 Then
If @error Then
Return 1
Else
If _WinAPI_PathIsDirectory($sPath) Then
Return SetError(1, 0, 1)
Else
Return SetError(2, 0, 1)
EndIf
EndIf
Else
If True Then
$Result = 0
Else
While 1
FileFindNextFile($hSearch)
If @error Then
ExitLoop
EndIf
If @extended Then
$Result = 0
ExitLoop
EndIf
WEnd
EndIf
EndIf
FileClose($hSearch)
Return $Result
EndFunc ;==>_TVIsEmpty
Func _TVSetPath($hTV, $hItem, $sRoot)
GUICtrlSetData($Input, _WinAPI_PathCompactPath($hInput, _TVGetPath($hTV, $hItem, $sRoot), 554))
$hSelect = $hItem
EndFunc ;==>_TVSetPath
Func _TVUpdate($hTV, $hItem)
Local $Path = StringRegExpReplace(_TVGetPath($hTV, $hItem, $sRoot), '\\+\Z', '')
Local $hSearch, $File, $Index
;~ _WinAPI_LockWindowUpdate($hTV)
_GUICtrlTreeView_Delete($hTV, _GUICtrlTreeView_GetFirstChild($hTV, $hItem))
$hSearch = FileFindFirstFile($Path & '\*')
If $hSearch = -1 Then
If @error Then
Else
If _WinAPI_PathIsDirectory($Path) Then
If StringInStr(FileGetAttrib($Path), 'H') Then
$Index = 4
Else
$Index = 3
EndIf
_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, $Index)
_GUICtrlTreeView_SetImageIndex($hTV, $hItem, $Index)
Else
_GUICtrlTreeView_Delete($hTV, $hItem)
; _WinAPI_LockWindowUpdate(0)
Return 0
EndIf
EndIf
Else
While 1
$File = FileFindNextFile($hSearch)
If @error Then
ExitLoop
EndIf
If @extended Then
$Index = _TVAddIcon($hTV, $Path & '\' & $File)
If Not _TVIsEmpty($Path & '\' & $File) Then
_GUICtrlTreeView_AddChild($hTV, _GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index), '', 0, 0)
Else
Switch @error
Case 0 ; OK
_GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
Case 1 ; Access denied
If StringInStr(FileGetAttrib($Path & '\' & $File), 'H') Then
$Index = 4
Else
$Index = 3
EndIf
_GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
Case Else
EndSwitch
EndIf
EndIf
WEnd
FileClose($hSearch)
EndIf
If True Then
$hSearch = FileFindFirstFile($Path & '\*')
If $hSearch = -1 Then
Else
While 1
$File = FileFindNextFile($hSearch)
If @error Then
ExitLoop
EndIf
If Not @extended Then
$Index = _TVAddIcon($hTV, $Path & '\' & $File)
Switch StringRegExpReplace($File, '^.*\.', '')
Case 'pif', 'lnk', 'url'
$Link[0][0] += 1
If $Link[0][0] > UBound($Link) - 1 Then
ReDim $Link[$Link[0][0] + 100][2]
EndIf
$Link[$Link[0][0]][0] = _GUICtrlTreeView_AddChild($hTV, $hItem, StringRegExpReplace($File, '\.[^.]*\Z', ''), $Index, $Index)
$Link[$Link[0][0]][1] = $Path & '\' & $File
Case Else
_GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
EndSwitch
EndIf
WEnd
FileClose($hSearch)
EndIf
EndIf
_GUICtrlTreeView_EnsureVisible($hTV, _GUICtrlTreeView_GetLastChild($hTV, $hItem))
_GUICtrlTreeView_EnsureVisible($hTV, $hItem)
_WinAPI_LockWindowUpdate(0)
Return 1
EndFunc ;==>_TVUpdate
#Region API Functions
Func _WinAPI_AddIconOverlay($hIcon, $hOverlay)
Local $tSIZE, $Ret, $hIL, $hResult = 0
$tSIZE = _WinAPI_GetIconDimension($hIcon)
If @error Then
Return SetError(1, 0, 0)
EndIf
$hIL = DllCall('comctl32.dll', 'ptr', 'ImageList_Create', 'int', DllStructGetData($tSIZE, 1), 'int', DllStructGetData($tSIZE, 1), 'uint', 0x0021, 'int', 2, 'int', 2)
If (@error) Or (Not $hIL[0]) Then
Return SetError(2, 0, 0)
EndIf
Do
$Ret = DllCall('comctl32.dll', 'int', 'ImageList_ReplaceIcon', 'ptr', $hIL[0], 'int', -1, 'ptr', $hIcon)
If (@error) Or ($Ret[0] = -1) Then
ExitLoop
EndIf
$Ret = DllCall('comctl32.dll', 'int', 'ImageList_ReplaceIcon', 'ptr', $hIL[0], 'int', -1, 'ptr', $hOverlay)
If (@error) Or ($Ret[0] = -1) Then
ExitLoop
EndIf
$Ret = DllCall('comctl32.dll', 'int', 'ImageList_SetOverlayImage', 'ptr', $hIL[0], 'int', 1, 'int', 1)
If (@error) Or (Not $Ret[0]) Then
ExitLoop
EndIf
$Ret = DllCall('comctl32.dll', 'ptr', 'ImageList_GetIcon', 'ptr', $hIL[0], 'int', 0, 'uint', 0x00000100)
If (@error) Or (Not $Ret[0]) Then
ExitLoop
EndIf
$hResult = $Ret[0]
Until 1
DllCall('comctl32.dll', 'int', 'ImageList_Destroy', 'ptr', $hIL[0])
If Not $hResult Then
Return SetError(3, 0, 0)
EndIf
Return $hResult
EndFunc ;==>_WinAPI_AddIconOverlay
Func _WinAPI_AddIconTransparency($hIcon, $iPercent = 50, $fDelete = 0)
Local $tICONINFO, $tBITMAP, $W, $H, $Ret, $iByte, $tBits, $pBits, $hBitmap[2], $hResult = 0
$tICONINFO = DllStructCreate($tagICONINFO)
$Ret = DllCall('user32.dll', 'int', 'GetIconInfo', 'ptr', $hIcon, 'ptr', DllStructGetPtr($tICONINFO))
If (@error) Or (Not $Ret[0]) Then
Return SetError(1, 0, 0)
EndIf
For $i = 0 To 1
$hBitmap[$i] = DllStructGetData($tICONINFO, $i + 4)
Next
Do
$tBITMAP = DllStructCreate($tagBITMAP)
If Not _WinAPI_GetObject($hBitmap[1], DllStructGetSize($tBITMAP), DllStructGetPtr($tBITMAP)) Then
ExitLoop
EndIf
$W = DllStructGetData($tBITMAP, 'bmWidth')
$H = DllStructGetData($tBITMAP, 'bmHeight')
$iByte = $W * $H * 4
$tBits = DllStructCreate('byte[' & $iByte & ']')
$pBits = DllStructGetPtr($tBits)
If _WinAPI_GetBitmapBits($hBitmap[1], $iByte, $pBits) <> $iByte Then
ExitLoop
EndIf
For $i = 1 To $iByte Step 4
DllStructSetData($tBits, 1, DllStructGetData($tBits, 1, $i + 3) * $iPercent / 100, $i + 3)
Next
_WinAPI_DeleteObject($hBitmap[1])
$hBitmap[1] = _WinAPI_CreateBitmap($W, $H, 1, 32, $pBits)
If $hBitmap[1] Then
$hResult = _WinAPI_CreateIconIndirect($hBitmap[1], $hBitmap[0])
EndIf
Until 1
For $i = 0 To 1
If $hBitmap[$i] Then
_WinAPI_DeleteObject($hBitmap[$i])
EndIf
Next
If Not $hResult Then
Return SetError(1, 0, 0)
EndIf
If $fDelete Then
_WinAPI_DestroyIcon($hIcon)
EndIf
Return $hResult
EndFunc ;==>_WinAPI_AddIconTransparency
Func _WinAPI_ExtractIcon($sIcon, $iIndex, $fSmall = 0)
Local $pLarge, $pSmall, $tPtr = DllStructCreate('ptr')
If $fSmall Then
$pLarge = 0
$pSmall = DllStructGetPtr($tPtr)
Else
$pLarge = DllStructGetPtr($tPtr)
$pSmall = 0
Endif
Local $Ret = DllCall('shell32.dll', 'uint', 'ExtractIconExW', 'wstr', $sIcon, 'int', $iIndex, 'ptr', $pLarge, 'ptr', $pSmall, 'uint', 1)
If (@error) Or (Not $Ret[0]) Then
Return SetError(1, 0, 0)
EndIf
Return DllStructGetData($tPtr, 1)
EndFunc ;==>_WinAPI_ExtractIcon
Func _WinAPI_LockWindowUpdate($hWnd)
Local $Ret = DllCall('user32.dll', 'int', 'LockWindowUpdate', 'hwnd', $hWnd)
If (@error) Or (Not $Ret[0]) Then
Return SetError(1, 0, 0)
EndIf
Return 1
EndFunc ;==>_WinAPI_LockWindowUpdate
Func _WinAPI_PathIsRoot($sPath)
Local $Ret = DllCall('shlwapi.dll', 'int', 'PathIsRootW', 'wstr', $sPath)
If @error Then
Return SetError(1, 0, 0)
EndIf
Return $Ret[0]
EndFunc ;==>_WinAPI_PathIsRoot
#EndRegion API Functions
#Region Windows Message Functions
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
Local $tNMTREEVIEW = DllStructCreate($tagNMTREEVIEW, $lParam)
Local $hItem = DllStructGetData($tNMTREEVIEW, 'NewhItem')
Local $iState = DllStructGetData($tNMTREEVIEW, 'NewState')
Local $hTV = DllStructGetData($tNMTREEVIEW, 'hWndFrom')
Local $ID = DllStructGetData($tNMTREEVIEW, 'Code')
Local $Index, $Path
Switch $hTV
Case $hTreeView
Switch $ID
Case $TVN_ITEMEXPANDINGW
If (Not BitAND($iState, $TVIS_EXPANDED)) And (Not _GUICtrlTreeView_ExpandedOnce($hTV, $hItem)) Then
_WinAPI_LockWindowUpdate($hTV)
$Count += 1
EndIf
Case $TVN_ITEMEXPANDEDW
$Path = _TVGetPath($hTV, $hItem, $sRoot)
If _WinAPI_PathIsDirectory($Path) Then
If Not BitAND($iState, $TVIS_EXPANDED) Then
$Index = _TVAddIcon($hTV, $Path)
Else
$Index = _TVAddIcon($hTV, $Path, 1)
If Not _GUICtrlTreeView_ExpandedOnce($hTV, $hItem) Then
GUICtrlSendToDummy($Dummy, $hItem)
$Count -=1
EndIf
EndIf
_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, $Index)
_GUICtrlTreeView_SetImageIndex($hTV, $hItem, $Index)
Else
_GUICtrlTreeView_Delete($hTV, $hItem)
If BitAND($iState, $TVIS_SELECTED) Then
_TVSetPath($hTV, _GUICtrlTreeView_GetSelection($hTV), $sRoot)
EndIf
EndIf
If $Count Then
_WinAPI_LockWindowUpdate(0)
$Count -= 1
EndIf
Case $TVN_SELCHANGEDW
If BitAND($iState, $TVIS_SELECTED) Then
If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
_GUICtrlTreeView_Delete($hTV, $hItem)
For $i = 1 To $Link[0][0]
If $Link[$i][0] = $hItem Then
For $j = $i To $Link[0][0] - 1
For $k = 0 To 1
$Link[$j][$k] = $Link[$j + 1][$k]
Next
Next
ReDim $Link[$Link[0][0]][2]
$Link[0][0] -= 1
ExitLoop
EndIf
Next
$hItem = _GUICtrlTreeView_GetSelection($hTV)
EndIf
If $hItem <> $hSelect Then
_TVSetPath($hTV, $hItem, $sRoot)
EndIf
EndIf
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY
#EndRegion Windows Message Functions