Что нового

[Элементы GUI] Дерево папок и файлов в TreeView напямую с диска.

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Yashied, очень много новинок.
- Наконец-то ушли назначения параметров -хорошее решение с _GUICtrlTreeView_ExpandedOnce
- Стали незаметными удаления временных элементов
- Не стал раздуваться ImageList
- Нашлось получение разнообразных иконок почти, как в Explorer'е .

Однако скорость обработки еще более снизилась.Да и код не простой.
Как мыслится использование этих наработок в своем скрипте ?
Не каждый пользователь способен разобраться в сложном коде. Ему бы "Черный ящик" с входными и выходными параметрами.
А тут еще непростая ф-ия обработки ( WM_NOTIFY ) .

Я вот попробовал в качестве "экскримента" : в скрипте со своим алгоритмом создания дерева,
использовать твою ф-ию получения иконок ( _TVAddIcon ), которую залил в виде файла : ExtractIcon_Ex.au3
В результате при более простом коде и с использованием стандартной ф-ии обработки сообщений ( WM_NOTIFY ),
получил практически все прелести ,имеющиеся в твоем коде. Причем скорость : в 1.5-2 раза выше.
Да и замеченных тобой недостатков не наблюдается
- развертывание ветки с помощью клавиатуры : поддерживается
- задержек и подвисания GUI ри быстром переключении между папками, содержащими большое количество файлов : не наблюдается

Я говорю почти, поскольку : ( WinXP SP3 )
- иконки (htm, hml ,mht )-файлов все же не находятся, в отличие от Explorer'а .
- иконки url- файлов определяются как линк текстового файла и элемент показывается соответственно без расширения .
Откуда все же Explorer да и Total Commander берет правильные иконки ?
Реестр я свой поправил : Дефолтную иконку теперь дает правильно.
Код:
#region *** INCLUDES ***
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiTreeView.au3>
#include <GuiImageList.au3>
#Include "ExtractIcon_Ex.au3"
#endregion

Global $iIndexIcon
$hForm = GUICreate('PC_TreeView', 600, 600)
GUISetBkColor(0xC0C0B0)
$Input_Time = GUICtrlCreateInput('', 260, 10, 60, 19,1);1-$ES_CENTER
$Input = GUICtrlCreateInput('', 20, 30, 560, 19)
$hTreeView=GUICtrlCreateTreeView(20, 50, 560, 530, -1, $WS_EX_CLIENTEDGE)
$hImageList = _GUIImageList_Create(_WinAPI_GetSystemMetrics($SM_CXSMICON), _WinAPI_GetSystemMetrics($SM_CYSMICON), 5, 1)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)

$aDisk=DriveGetDrive("ALL")
$begin=TimerInit()
$iIndexIcon = _TVAddIcon($hTreeView, $aDisk[1]&'\')
For $i=1 To UBound($aDisk)-1
   $aDisk[$i]=StringUpper ( $aDisk[$i] )
   $hItem= _GUICtrlTreeView_Add($hTreeView, 0, $aDisk[$i],$iIndexIcon,$iIndexIcon)
   If  FileFindFirstFile($aDisk[$i] & '\*')<> -1 Then _GUICtrlTreeView_SetChildren($hTreeView,  $hItem)
Next
GUICtrlSetData($Input_Time,StringFormat("%.2f",TimerDiff($begin)))

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY_1')
GUISetState()
Do
Until GUIGetMsg()= -3

Func TreeView_UpDate_Ex($hTV,$hItem)
   If $hItem=0 Then Return -1
   If Not IsHWnd($hTV) Then $hTV=GUICtrlGetHandle($hTV)
   $sPath=StringReplace(_GUICtrlTreeView_GetTree($hTV, $hItem) ,'|','\')
   If Not FileExists($sPath) Then Return SetError(1, 1, 0)
   GUICtrlSetData($Input,StringRegExpReplace ( $sPath ,'(.:)$','\1\\' ,1))
   If  _GUICtrlTreeView_ExpandedOnce($hTV, $hItem) Then Return  -1
   Local $hSearch = FileFindFirstFile($sPath & '\*')
   Local $hFolder
   While 1
	  $sFile = FileFindNextFile($hSearch)
	  If @error Then ExitLoop
	  $iIndexIcon = _TVAddIcon($hTV, $sPath & '\' & $sFile); *** 1-й вариант поиска Иконок ***
	  If StringInStr(FileGetAttrib($sPath & '\' & $sFile), 'D')  Then
		 $hFolder= _GUICtrlTreeView_InsertItem($hTV, $sFile,$hItem,$hFolder,$iIndexIcon,$iIndexIcon)
		 If FileFindFirstFile($sPath & '\' & $sFile & '\*')<> -1 Then _GUICtrlTreeView_SetChildren($hTV,  $hFolder)
	  Else
		 $hChild= _GUICtrlTreeView_AddChild($hTV,$hItem,$sFile,$iIndexIcon,$iIndexIcon)
	  EndIf
   WEnd
   Return 1
EndFunc ;==> TreeView_UpDate_Ex

Func WM_NOTIFY_1($hWnd, $iMsg, $iwParam, $ilParam)
   #forceref $hWnd, $iMsg, $iwParam
   Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeview
   $hWndTreeview = $hTreeView
   If Not IsHWnd($hTreeView) Then $hWndTreeview = GUICtrlGetHandle($hTreeView)
   $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
   $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
   $iCode = DllStructGetData($tNMHDR, "Code")
   Switch $hWndFrom
	  Case $hWndTreeview
		 Switch $iCode
			Case  $NM_CLICK 
			   $hClickedItemTV=ScreenToClient($hWndTreeview); ===>
			   $begin=TimerInit()
			   If Not TreeView_UpDate_Ex($hTreeView, $hClickedItemTV) Then _GUICtrlTreeView_Delete($hTreeView, $hClickedItemTV); ===>
			   GUICtrlSetData($Input_Time,StringFormat("%.2f",TimerDiff($begin)))
		EndSwitch
   EndSwitch
   Return $GUI_RUNDEFMSG
EndFunc   ;==> WM_NOTIFY

Func ScreenToClient($hWnd)
   Local $tPOINT = DllStructCreate("int X;int Y"),$hPointed
   DllStructSetData($tPOINT, "X", MouseGetPos(0))
   DllStructSetData($tPOINT, "Y", MouseGetPos(1))
   DllCall("user32.dll", "int", "ScreenToClient", "hwnd", $hWnd, "ptr", DllStructGetPtr($tPOINT)) 
   Local $iX = DllStructGetData($tPOINT, "X"),$iY = DllStructGetData($tPOINT, "Y")
   $hPointed = _GUICtrlTreeView_HitTestItem($hWnd, $iX, $iY)
   Return $hPointed
EndFunc ;==> ScreenToClient
Скачать : ExtractIcon_Ex.au3 (6.89 kb)


Добавлено:
Сообщение автоматически объединено:

Только сейчас подумал :
Если я нарушил нереднамеренно авторские права, просьба удалить файл.
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
HukpoFuJl сказал(а):
пользовательское контекстное меню
Ближе к началу этой темы уже был приведён пример как это зделать. Вот тут для тебя выложил с последним примером
Код:
; 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>
#Include <GuiMenu.au3>

Opt('MustDeclareVars', 1)
Opt("GUICoordMode", 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]]

Global $Dummy2, $TVMenu[4], $TreeView
$hForm = GUICreate('MyGUI', 600, 600, Default, Default)
$Input = GUICtrlCreateInput('', 20, 20, 560, 19)
$hInput = GUICtrlGetHandle(-1)
GUICtrlSetState(-1, $GUI_DISABLE)
; Контекст меню для вложений TreeView ...
$Dummy2 = GUICtrlCreateDummy() ;~> Событие 3, Для меню на адресной строки.
$TVMenu[0] = GUICtrlCreateContextMenu($Dummy2) ; GUICtrlCreateMenuItem('', $TVMenu[0]) ;Разделитель [Separator]...
$TVMenu[1] = GUICtrlCreateMenuItem('Open', $TVMenu[0])
$TVMenu[2] = GUICtrlCreateMenuItem('Save', $TVMenu[0])
$TVMenu[3] = GUICtrlCreateMenuItem('Info', $TVMenu[0])
$TVMenu[0] = GUICtrlGetHandle($TVMenu[0])
;~$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)
$TreeView = 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)
        Case $Dummy2 ;~> Контекст меню при правом клике на вложении TreeView.
			_GUICtrlMenu_TrackPopupMenu($TVMenu[0], $hForm)
		; Параметры/Действия контекстного меню TreeView.
        Case $TVMenu[1] ; "Open"
            MsgBox(64, _GUICtrlTreeView_GetText($hTreeView, $hSelect), '"Open" item was chosen.', 0, $hForm)
        Case $TVMenu[2] ; "Save"
            MsgBox(64, _GUICtrlTreeView_GetText($hTreeView, $hSelect), '"Save" item was chosen.', 0, $hForm)
        Case $TVMenu[3] ; "Info"
            MsgBox(64, _GUICtrlTreeView_GetText($hTreeView, $hSelect), '"Info" item was chosen.', 0, $hForm)
    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
    Local $tTVHTI, $tPoint
    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
                Case $NM_RCLICK
					GUICtrlSendToDummy($Dummy2, $hItem)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

#EndRegion Windows Message Functions

Yashied
И ешё вот это последний пример у меня отрабатывает так что аш "монитор" Desktop тресётса когда открываеш много содержашую папку, ну картинка прыгает. Я аш испугался первый раз. и смотрел что процессор делает скачёк до 30%. Такое наблюдалось и в пред последнем варианте.

У каво ешё такое наблюдаетса? или только у меня одного.
Комп XP SP 3 > DualCoore 2.50G > 3.25 Raam > видео 9800Gt

gregaz
Посмотрите пожалуйсто что получилось с запуском вашего варианта. Фаил прикреплён
:wacko: :'(
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
У каво ешё такое наблюдаетса? или только у меня одного.
У меня все нормально хотя тоже XP SP 3

dronet [?]
Посмотрите пожалуйсто что получилось с запуском вашего варианта. Фаил прикреплён
Скачал. Проверил . Все нормально
Файл ExtractIcon_Ex.au3 установлен в папке со скриптом ?
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
gregaz
У меня вот такое вот сообшение выдаёт, не знаю почему
"Устройство не готово..." У меня бод "I" CD-Room
Да без него вообше бы не запустился
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Попробуй заменить строку 18 :
Код:
$aDisk=DriveGetDrive("ALL")

на
Код:
$aDisk=DriveGetDrive("FIXED")

(без CD_ROOM'а)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
dronet сказал(а):
У меня вот такое вот сообшение выдаёт, не знаю почему
"Устройство не готово..."

Поставь где-нибудь в начале скрипта следующую строчку:

Код:
_WinAPI_SetErrorMode($SEM_FAILCRITICALERRORS)
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Всё нормально, я разобрался -
_WinAPI_SetErrorMode($SEM_FAILCRITICALERRORS) работает.
$aDisk=DriveGetDrive("FIXED") тоже работает .
И с прыганием картинки разобрался, - настройки моего компа :whistle:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
gregaz

Я долго думал над тем, почему мой алгоритм уступает по скорости твоему решению. И оказалось, что все дело в паре функций _GUICtrlTreeView_BeginUpdate() и _GUICtrlTreeView_EndUpdate(). Даже несмотря на то, что я заменил их _WinAPI_LockWindowUpdate(), скорость очень сильно падает. Более того, если использовать первые две функции, то через некоторое время (после открытия папок с большим количеством файлов (мне хватало Windows + System32 + еще что-нибудь), TreeView начинает глючить так, что даже открытие папки с одним лишь файлом занимает столько времени, как будто там их несколько сотен. Вообщем, пришлось переписать алгоритм без использования этих функций, и скорость стала сравнима с твоим алгоритмом. А насчет сложности кода, то ведь никто не обещал, что будет все легко... В любом случае, специально для этого я написал UDF, в котором, плюс ко всему, есть еще несколько плюшек. Протестируй пожалуйста, если не сложно.

:smile:
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Yashied [?]
Протестируй пожалуйста, если не сложно.
Первые впечатления : (навскидку)
Значительно удобнее стало.
Скорость все же увеличилась незначительно :
Сравнивал на папке System32
Была : 2.8 сек
Стала : 2.7 сек
Против 1.9 сек на моем варианте с твоей ф-ией определения иконок.
Я думаю для других папках это не будет заметно , и может считаться приемлемым.
Все же видимо время уходит на создание временных элементов дерева.(При большом кол-ве файлов это сильно сказывается)
И еще одной возможной причиной может быть
Отсутствие у меня ф-ии : _GUICtrlTreeView_Expand($TV) (наверняка при большом кол-ве файлов съедает приличное время).
Кстати из-за необходимости ее вводить я не смог прикрутить обработку через Dammy.

Элементы дерева теперь не имеют расширений,(кроме ".dll") , как в системном Explorer"е - это хорошо, но вместе с тем и неудобно.
В системном ведь все файлы имеют иконки и имеется ToolTip.
Здесь же достаточное кол-во файлов неизвестного расширения.
Может имеет смысл оставить для файлов с неопределенной иконкой расширения.
И добавить ToolTip.

Еще одну вещь заметил :
Пожоже контороль за начилием иконок в ImageList начинается не сначала , а после второго клика.
Попробуй файл -"1.au3" добавить в корень диска и в дочернюю папку. Он дважды занесется в лист. Хотя это может и не так важно.
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Yashied я в своём коде вообше убрал эту функцию НА старте! потому-что всё равно ошипку рапартавала. А далее в работе всё ок было .
Вот этом куске кода я убрал.
Код:
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

Я обычно подписываю в функциях вывод в консоль рапорты, чтоб знать где ошипки и почему
Выглядет так
Код:
Func _WinAPI_LockWindowUpdate($hWnd)
    Local $Ret = DllCall('user32.dll', 'int', 'LockWindowUpdate', 'hwnd', $hWnd)
    If (@error) Or (Not $Ret[0]) Then
		WRITE_ERROR_LOOG('Error!', '', @ScriptLineNumber, @error, @extended)
        Return SetError(1, 0, 0)
    EndIf
    Return 1
EndFunc   ;==>_WinAPI_LockWindowUpdate


Func WRITE_ERROR_LOOG($TITLE, $TEXT, $LINE, $ERROR, $EXTENDED)
	ConsoleWrite( _
			"===================================================================================="&@CRLF& _
			"~~> "&$TITLE&@CRLF& _
			"~~> "&$TEXT&@CRLF& _
			"~~> ERROR CODE: "&$ERROR&@CRLF& _
			"~~> LINE NUMBER: "&$LINE&@CRLF& _
			"~~> EXTENDED: "&$EXTENDED&@CRLF& _
			"===================================================================================="&@CRLF)
EndFunc   ;==>GUI_SEND_MESSAGE
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724

AZJIO

Меценат
Меценат
Сообщения
2,894
Репутация
1,196
Мой первый вариант

Код:
#include <GUIConstantsEx.au3>
#include <GuiTreeView.au3>
#include <WindowsConstants.au3>
#include <GuiImageList.au3>
#include <File.au3>
#include <GuiListView.au3>

Opt("GUIOnEventMode", 1)

Global $PathCur

GUICreate('My Program', 640, 560)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
$StatusBar = GUICtrlCreateLabel('', 5, 560 - 18, 640 - 10, 17)

$restart = GUICtrlCreateButton("R", 640 - 20, 2, 18, 20)
GUICtrlSetOnEvent(-1, "_restart")

$TreeView = GUICtrlCreateTreeView(0, 35, 216, 500)
$hTreeView = GUICtrlGetHandle($TreeView)

$hImage = _GUIImageList_Create(16, 16, 5, 1)
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', -4)
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', -5)
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', 0)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImage)

$E=''
$i=1
While 1
	$i+=1
	$sExt = RegEnumKey("HKCR", $i)
    If @error Or StringLeft($sExt, 1)<>'.' then ExitLoop
	$ico1=_FileDefaultIcon($sExt)
	If Not @error Then
		Switch UBound($ico1)
			Case 2
				If StringInStr(';.exe;.scr;.ico;.ani;.cur;', ';'&$sExt&';') Then
					ContinueLoop
				Else
					_GUIImageList_AddIcon($hImage, $ico1[1], 0)
					If @error Then ContinueLoop
				EndIf
			Case 3
				_GUIImageList_AddIcon($hImage, $ico1[1], $ico1[2])
				If @error Then ContinueLoop
		EndSwitch
		$E&='|'&$sExt
	EndIf
WEnd
$E=StringTrimLeft($E, 1)
$aE=StringSplit($E, '|')

$DrivesArr = DriveGetDrive("all")
For $i = 1 To $DrivesArr[0]
	If $DrivesArr[$i] = 'a:' Or DriveGetType($DrivesArr[$i] & '\') = 'CDROM' Then ContinueLoop
	$hTmp = _GUICtrlTreeView_Add($hTreeView, 0, $DrivesArr[$i], 0, 0)
	$tmp = _FileListToArray($DrivesArr[$i], "*", 2)
	For $j = 1 To $tmp[0]
		_GUICtrlTreeView_AddChild($hTreeView, $hTmp, $tmp[$j], 0, 0)
	Next
Next

; перейти к нужной папке
; $StartPath='C:\AutoIt3\Notepad++'

$ListView = GUICtrlCreateListView(' ', 220, 35, 420, 500, $LVS_NOCOLUMNHEADER + $LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED)
GUICtrlSetBkColor(-1, 0xf0f0f0)
$hListView = GUICtrlGetHandle($ListView)
_GUICtrlListView_SetColumnWidth($ListView, 0, 390)
_GUICtrlListView_SetImageList($hListView, $hImage, 1)

GUISetState()
GUIRegisterMsg(0x004E, 'WM_NOTIFY')

While 1
	Sleep(100000)
WEnd

Func _Exit()
	Exit
EndFunc   ;==>_Exit

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
	Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tmp

	$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
	$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
	$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
	$iCode = DllStructGetData($tNMHDR, "Code")
	Switch $hWndFrom
		Case $hTreeView
			Switch $iCode
				Case $NM_CLICK
					Local $tMPos = _WinAPI_GetMousePos(True, $hWndFrom), $tHit = _GUICtrlTreeView_HitTestEx($hWndFrom, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
					Local $hItem = DllStructGetData($tHit, "Item")
					If $hItem <> -1 And $hItem <> 0x0 Then
						$tmp = _GetPathItem($hWndFrom, $hItem)
						If $PathCur = $tmp Then
							Return
						Else
							$PathCur = $tmp
						EndIf
						GUICtrlSetData($StatusBar, $PathCur)

						_GUICtrlListView_BeginUpdate($hListView)
						_GUICtrlListView_DeleteAllItems($hListView)
						$tmp = _FileListToArray($PathCur, "*", 2)
						If Not @error Then
							For $i = 1 To $tmp[0]
								_GUICtrlListView_AddItem($hListView, $tmp[$i], 0)
							Next
						EndIf
						$tmp=_FileListToArray($PathCur, "*", 1)
						If Not @error Then
							For $i = 1 to $tmp[0]
								$tmp3=StringRegExpReplace($tmp[$i], '.*(\.\S+)', '\1')
								$ind=_ArraySearch($aE, $tmp3)
								If @error Then $ind=0
								_GUICtrlListView_AddItem($hListView, $tmp[$i], $ind+2)
							Next
						EndIf
						_GUICtrlListView_EndUpdate($hListView)

						$KolChild = _GUICtrlTreeView_GetChildCount($hWndFrom, $hItem)
						If $KolChild <= 0 Then Return

						$h = _GUICtrlTreeView_GetFirstChild($hWndFrom, $hItem)
						$KolH = _GUICtrlTreeView_GetChildCount($hWndFrom, $h)
						If $KolH > 0 Then Return
						_CreateItem($hWndFrom, $h, $PathCur)

						For $i = 1 To $KolChild - 1
							$h = _GUICtrlTreeView_GetNextChild($hWndFrom, $h)
							$KolH = _GUICtrlTreeView_GetChildCount($hWndFrom, $h)
							If $KolH > 0 Then Return
							_CreateItem($hWndFrom, $h, $PathCur)
						Next
					Else
						Return
					EndIf
			EndSwitch
		Case $hListView
			Switch $iCode
				Case $NM_DBLCLK
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    $iItem = DllStructGetData($tInfo, 'Index')
					If $iItem > -1 Then
						$tmp = $PathCur&'\'&_GUICtrlListView_GetItemText($hListView, $iItem)
						If FileExists($tmp) Then ShellExecute('"'&$tmp&'"')
					EndIf
			EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _CreateItem($hWndFrom, $h, $Path)
	$text = _GUICtrlTreeView_GetText($hWndFrom, $h)
	$tmp = _FileListToArray($Path & '\' & $text, "*", 2)
	If @error Then Return
	For $i = 1 To $tmp[0]
		_GUICtrlTreeView_AddChild($hTreeView, $h, $tmp[$i], 0, 0)
	Next
EndFunc   ;==>_CreateItem

Func _GetPathItem($hWndFrom, $hItem)
	Local $Path = _GUICtrlTreeView_GetText($hWndFrom, $hItem), $text, $Path
	While 1
		$hItem = _GUICtrlTreeView_GetParentHandle($hWndFrom, $hItem)
		If $hItem = 0 Then ExitLoop
		$text = _GUICtrlTreeView_GetText($hWndFrom, $hItem)
		$Path = $text & '\' & $Path
	WEnd
	Return $Path
EndFunc   ;==>_GetPathItem

Func _restart()
	Local $sAutoIt_File = @TempDir & "\~Au3_ScriptRestart_TempFile.au3"
	Local $sRunLine, $sScript_Content, $hFile

	$sRunLine = @ScriptFullPath
	If Not @Compiled Then $sRunLine = @AutoItExe & ' /AutoIt3ExecuteScript ""' & $sRunLine & '""'
	If $CmdLine[0] > 0 Then $sRunLine &= ' ' & $CmdLineRaw

	$sScript_Content &= '#NoTrayIcon' & @CRLF & _
			'While ProcessExists(' & @AutoItPID & ')' & @CRLF & _
			'   Sleep(10)' & @CRLF & _
			'WEnd' & @CRLF & _
			'Run("' & $sRunLine & '")' & @CRLF & _
			'FileDelete(@ScriptFullPath)' & @CRLF

	$hFile = FileOpen($sAutoIt_File, 2)
	FileWrite($hFile, $sScript_Content)
	FileClose($hFile)

	Run(@AutoItExe & ' /AutoIt3ExecuteScript "' & $sAutoIt_File & '"', @ScriptDir, @SW_HIDE)
	Sleep(1000)
	Exit
EndFunc   ;==>_restart

Func _FileDefaultIcon($sExt)
	If $sExt = '' Or StringInStr($sExt, ':') Then Return SetError(1)

    Local $aCall = DllCall("shlwapi.dll", "int", "AssocQueryStringW", _
            "dword", 0x00000040, _ ;$ASSOCF_VERIFY
            "dword", 15, _ ;$ASSOCSTR_DEFAULTICON 
            "wstr", $sExt, _
            "ptr", 0, _
            "wstr", "", _
            "dword*", 65536)

    If @error Then Return SetError(1, 0, "")

    If Not $aCall[0] Then
		$sExt=StringReplace($aCall[5], '"', '')
		$sExt=StringSplit($sExt, ',')
		Opt('ExpandEnvStrings', 1)
		$sExt[1]=$sExt[1]
		Opt('ExpandEnvStrings', 0)
        Return SetError(0, 0, $sExt)
    ElseIf $aCall[0] = 0x80070002 Then
        Return SetError(1, 0, "{unknown}")
    ElseIf $aCall[0] = 0x80004005 Then
        Return SetError(1, 0, "{fail}")
    Else
        Return SetError(2, $aCall[0], "")
    EndIf

EndFunc  ;==>_FileAssociation

Попробовал скрестить оболочку с FTP, юзание папок работает, скачивание двойным кликом тоже. На юкоз не получилось зайти. В строке 64 указать сервер FTP.

Код:
#include <GUIConstantsEx.au3>
#include <GuiTreeView.au3>
#include <WindowsConstants.au3>
#include <GuiImageList.au3>
#Include <File.au3>
#include <GuiListView.au3>
#Include <Array.au3> ; тест
#include <FTPEx.au3>

Opt("GUIOnEventMode", 1)

Global $PathCur, $TrWM_NOTIFY=0, $OpenFTPCon, $FileGet
Global $Address0, $server, $username, $pass


; установка входящих параметров
; !i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i
$Gui1 = GUICreate('', 120, 200)
GUISetOnEvent(-3, "_Exit1")
Global $inpSet[5]

GUICtrlCreateLabel('сервер', 10, 13, 300, 17)
$inpSet[0]=GUICtrlCreateCombo('', 10, 30, 100, 23)
GUICtrlSetData(-1,'192.168.45.38|192.168.48.36', '192.168.45.38')

GUICtrlCreateLabel('Пользователь', 10, 63, 300, 17)
$inpSet[1]=GUICtrlCreateInput('anonymous', 10, 80, 100, 20)

GUICtrlCreateLabel('Пароль', 10, 113, 300, 17)
$inpSet[2]=GUICtrlCreateInput('[email protected]', 10, 130, 100, 20)

GUICtrlCreateButton('OK', 25, 160, 70, 25)
GUICtrlSetOnEvent(-1, "_OK")

GUISetState(@SW_SHOW, $Gui1)

$ex = 0
While 1
	Sleep(100)
	If $ex = 1 Then
		GUIDelete($Gui1)
		ExitLoop
	EndIf
WEnd

Func _OK()
	$Address0 =GUICtrlRead($inpSet[0]) 
	$server = $Address0
	$username =GUICtrlRead($inpSet[1]) 
	$pass =GUICtrlRead($inpSet[2]) 
	$ex =1
EndFunc

Func _Exit1()
	Exit
EndFunc
; !i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i!i



$Gui=GUICreate('Файловый менеджер', 640, 560)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
$StatusBar = GUICtrlCreateLabel('', 5, 560-18, 640-10, 17)

$restart = GUICtrlCreateButton("R", 640-20, 2, 18, 20)
; GUICtrlSetResizing(-1, 512 + 256 + 32 + 4)
GUICtrlSetOnEvent(-1, "_restart")

$TreeView = GUICtrlCreateTreeView(0, 35, 216, 500)
; GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
$hTreeView = GUICtrlGetHandle($TreeView)


$hImage = _GUIImageList_Create(16, 16, 5, 1)
_GUIImageList_AddIcon($hImage, @SystemDir&'\shell32.dll', -4)
_GUIImageList_AddIcon($hImage, @SystemDir&'\shell32.dll', -5)
_GUIImageList_AddIcon($hImage, @SystemDir&'\shell32.dll', 0)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImage)


$E=''
$i=1
While 1
	$i+=1
	$sExt = RegEnumKey("HKCR", $i)
    If @error Or StringLeft($sExt, 1)<>'.' then ExitLoop
	$ico1=_FileDefaultIcon($sExt)
	If Not @error Then
		Switch UBound($ico1)
			Case 2
				If StringInStr(';.exe;.scr;.ico;.ani;.cur;', ';'&$sExt&';') Then
					ContinueLoop
				Else
					_GUIImageList_AddIcon($hImage, $ico1[1], 0)
					If @error Then ContinueLoop
				EndIf
			Case 3
				_GUIImageList_AddIcon($hImage, $ico1[1], $ico1[2])
				If @error Then ContinueLoop
		EndSwitch
		$E&='|'&$sExt
	EndIf
WEnd
$E=StringTrimLeft($E, 1)
$aE=StringSplit($E, '|')


$OpenFTPCon = _FTP_Open('MyFTP_Connect')
If @error Then
	MsgBox(0, 'Ошибка', 'Ошибка сессии')
	Exit
EndIf
$Conn = _FTP_Connect($OpenFTPCon, $server, $username, $pass)
If @error Then
	MsgBox(0, 'Ошибка', 'Ошибка подключения')
	Exit
EndIf

$FolderArr =_FTP_ListToArray($Conn, 1)
 If Not IsArray($FolderArr) Or $FolderArr[0] = 0 Or ($FolderArr[0] = 2 And $FolderArr[1] = "." And $FolderArr[2] = "..") Then
	MsgBox(0, 'Ошибка', 'Отсутствуют каталоги')
	Exit
EndIf
For $i = 1 to $FolderArr[0]
    If StringInStr("..", $FolderArr[$i]) Then ContinueLoop
	$hTmp = _GUICtrlTreeView_Add($hTreeView, 0, $FolderArr[$i], 0, 0)
	_FTP_DirSetCurrent($Conn, "/"& $FolderArr[$i] & "/")
	$tmp=_FTP_ListToArray($Conn, 1)
    If Not IsArray($tmp) Or $tmp[0] = 0 Or ($tmp[0] = 2 And $tmp[1] = "." And $tmp[2] = "..") Then ContinueLoop
	For $j = 1 to $tmp[0]
		If StringInStr("..", $tmp[$j]) Then ContinueLoop
		_GUICtrlTreeView_AddChild($hTreeView, $hTmp, $tmp[$j], 0, 0)
	Next
Next


$ListView = GUICtrlCreateListView(' ', 220, 35, 420, 500, $LVS_NOCOLUMNHEADER +$LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED)
GUICtrlSendMsg($ListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_FULLROWSELECT, $LVS_EX_FULLROWSELECT)
GUICtrlSendMsg($ListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_TRACKSELECT, $LVS_EX_TRACKSELECT)
GUICtrlSetBkColor(-1, 0xf0f0f0) ; 0xE0DFE3
$hListView = GUICtrlGetHandle($ListView)
_GUICtrlListView_SetColumnWidth($ListView, 0, 390)
_GUICtrlListView_SetImageList($hListView, $hImage, 1)
GUISetState ()
GUIRegisterMsg(0x004E, 'WM_NOTIFY')

; создаём список в ListView корневого каталога
_GUICtrlListView_BeginUpdate($hListView)
_GUICtrlListView_DeleteAllItems($hListView)
For $i = 1 to $FolderArr[0]
	If StringInStr("..", $FolderArr[$i]) Then ContinueLoop
	_GUICtrlListView_AddItem($hListView, $FolderArr[$i], 0)
Next
$tmp=_FTP_ListToArray($Conn, 2) ; файлы
If Not @error And IsArray($tmp) Then
	For $i = 1 to $tmp[0]
		$tmp3=StringRegExpReplace($tmp[$i], '.*(\.\S+)', '\1')
		$ind=_ArraySearch($aE, $tmp3)
		If @error Then $ind=0
		_GUICtrlListView_AddItem($hListView, $tmp[$i], $ind+2)
	Next
EndIf
_GUICtrlListView_EndUpdate($hListView)



While 1
	Sleep(100000)
WEnd

Func _Exit()
	$Ftpc = _FTP_Close($OpenFTPCon)
	Exit
EndFunc

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tmp, $TrWM_NOTIFY=1

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hTreeView
            Switch $iCode
                Case $NM_CLICK
					; получение хэндла кликнутого пункта и поиск его в массиве
					Local $tMPos = _WinAPI_GetMousePos(True, $hWndFrom), $tHit = _GUICtrlTreeView_HitTestEx($hWndFrom, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
					Local $hItem = DllStructGetData($tHit, "Item")
					If $hItem <> -1 And $hItem<>0x0 Then
						$tmp=_GetPathItem($hWndFrom, $hItem)
						If $PathCur=$tmp Then
							Return
						Else
							$PathCur=$tmp
						EndIf
						GUICtrlSetData($StatusBar, $PathCur)
						; GUICtrlSetData($Address, $PathCur)
						
						_GUICtrlListView_BeginUpdate($hListView)
						_GUICtrlListView_DeleteAllItems($hListView)
						
						 _FTP_DirSetCurrent($Conn, "/"& $PathCur & "/")
						$tmp=_FTP_ListToArray($Conn, 1) ; папки
						If Not @error And IsArray($tmp) Then
							For $i = 1 to $tmp[0]
								If StringInStr("..", $tmp[$i]) Then ContinueLoop
								_GUICtrlListView_AddItem($hListView, $tmp[$i], 0)
							Next
						EndIf
						$tmp=_FTP_ListToArray($Conn, 2) ; файлы
						If Not @error And IsArray($tmp) Then
							For $i = 1 to $tmp[0]
								$tmp3=StringRegExpReplace($tmp[$i], '.*(\.\S+)', '\1')
								$ind=_ArraySearch($aE, $tmp3)
								If @error Then $ind=0
								_GUICtrlListView_AddItem($hListView, $tmp[$i], $ind+2)
							Next
						EndIf
						_GUICtrlListView_EndUpdate($hListView)
						
						$KolChild=_GUICtrlTreeView_GetChildCount($hWndFrom, $hItem)
						If $KolChild<=0 Then Return
						
						$h=_GUICtrlTreeView_GetFirstChild($hWndFrom, $hItem)
						$KolH=_GUICtrlTreeView_GetChildCount($hWndFrom, $h)
						If $KolH>0 Then Return
						_CreateItem($hWndFrom, $h, $PathCur)
						
						For $i = 1 to $KolChild-1
							$h=_GUICtrlTreeView_GetNextChild($hWndFrom, $h)
							$KolH=_GUICtrlTreeView_GetChildCount($hWndFrom, $h)
							If $KolH>0 Then Return
							_CreateItem($hWndFrom, $h, $PathCur)
						Next
					Else
						Return
					EndIf
                Case $NM_RCLICK
					Local $tMPos = _WinAPI_GetMousePos(True, $hWndFrom), $tHit = _GUICtrlTreeView_HitTestEx($hWndFrom, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
					Local $hItem = DllStructGetData($tHit, "Item")
					If $hItem <> -1 And $hItem<>0x0 Then
					Else
						Return
					EndIf
            EndSwitch
		Case $hListView
			Switch $iCode
				Case $NM_DBLCLK
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    $iItem = DllStructGetData($tInfo, 'Index')
					If $iItem > -1 Then
						$FileGet = $PathCur&'/'&_GUICtrlListView_GetItemText($hListView, $iItem)
						AdlibRegister('_FileGet', 40)
					EndIf
			EndSwitch
    EndSwitch
	$TrWM_NOTIFY=0
    Return $GUI_RUNDEFMSG
EndFunc


Func _FileGet()
	AdlibUnRegister('_FileGet')
	$SaveFile = FileSaveDialog('Сохранить как ...', @DesktopDir , 'Все (*.*)', 18, StringRegExpReplace($FileGet, '(^.*)/(.*)$', '\2'), $Gui)
	If @error Then Return
	If _FTP_FileGet($Conn, "/"& $FileGet, $SaveFile) Then
		MsgBox(0, 'Message', 'Готово')
	Else
		MsgBox(0, 'Ошибка', 'Скачивайте файл а не каталог')
	EndIf
EndFunc

Func _CreateItem($hWndFrom, $h, $Path)
	Local $text=_GUICtrlTreeView_GetText($hWndFrom, $h)
	_FTP_DirSetCurrent($Conn, "/"& $Path &'/'& $text & "/")
	Local $tmp=_FTP_ListToArray($Conn, 1)
	If @error Or Not IsArray($tmp) Then Return
	For $i = 1 to $tmp[0]
		If $tmp[$i] = "." Or $tmp[$i] = ".." Then ContinueLoop
		_GUICtrlTreeView_AddChild($hTreeView, $h, $tmp[$i], 0, 0)
	Next
EndFunc

Func _GetPathItem($hWndFrom, $hItem)
	Local $Path=_GUICtrlTreeView_GetText($hWndFrom, $hItem), $text, $Path
	While 1
		$hItem=_GUICtrlTreeView_GetParentHandle($hWndFrom, $hItem)
		If $hItem = 0 Then ExitLoop
		$text=_GUICtrlTreeView_GetText($hWndFrom, $hItem)
		$Path=$text &'/'& $Path
	WEnd
	Return $Path
EndFunc

Func _restart()
	$Ftpc = _FTP_Close($OpenFTPCon)
	Local $sAutoIt_File = @TempDir & "\~Au3_ScriptRestart_TempFile.au3"
	Local $sRunLine, $sScript_Content, $hFile

	$sRunLine = @ScriptFullPath
	If Not @Compiled Then $sRunLine = @AutoItExe & ' /AutoIt3ExecuteScript ""' & $sRunLine & '""'
	If $CmdLine[0] > 0 Then $sRunLine &= ' ' & $CmdLineRaw

	$sScript_Content &= '#NoTrayIcon' & @CRLF & _
			'While ProcessExists(' & @AutoItPID & ')' & @CRLF & _
			'   Sleep(10)' & @CRLF & _
			'WEnd' & @CRLF & _
			'Run("' & $sRunLine & '")' & @CRLF & _
			'FileDelete(@ScriptFullPath)' & @CRLF

	$hFile = FileOpen($sAutoIt_File, 2)
	FileWrite($hFile, $sScript_Content)
	FileClose($hFile)

	Run(@AutoItExe & ' /AutoIt3ExecuteScript "' & $sAutoIt_File & '"', @ScriptDir, @SW_HIDE)
	Sleep(1000)
	Exit
EndFunc   ;==>_restart

Func _FileDefaultIcon($sExt)
	If $sExt = '' Or StringInStr($sExt, ':') Then Return SetError(1)

    Local $aCall = DllCall("shlwapi.dll", "int", "AssocQueryStringW", _
            "dword", 0x00000040, _ ;$ASSOCF_VERIFY
            "dword", 15, _ ;$ASSOCSTR_DEFAULTICON 
            "wstr", $sExt, _
            "ptr", 0, _
            "wstr", "", _
            "dword*", 65536)

    If @error Then Return SetError(1, 0, "")

    If Not $aCall[0] Then
		$sExt=StringReplace($aCall[5], '"', '')
		$sExt=StringSplit($sExt, ',')
		Opt('ExpandEnvStrings', 1)
		$sExt[1]=$sExt[1]
		Opt('ExpandEnvStrings', 0)
        Return SetError(0, 0, $sExt)
    ElseIf $aCall[0] = 0x80070002 Then
        Return SetError(1, 0, "{unknown}")
    ElseIf $aCall[0] = 0x80004005 Then
        Return SetError(1, 0, "{fail}")
    Else
        Return SetError(2, $aCall[0], "")
    EndIf

EndFunc  ;==>_FileAssociation


Добавлено:
Сообщение автоматически объединено:

Посмотрел тему, не нашёл ссылок на варианты с офсайта
ShellTristateTreeView - KaFu объединил наработки Rasim и Holger
Tristate GUI TreeView - Holger
ShellTreeView - Rasim
эксплорер от OldCoder

Так как мне пришлось немного модернизировать старые скрипты (кроме варианта KaFu), чтоб они запускались без ошибок, то выкладываю модернизированные, четыре варианта в одном архиве.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
AZJIO

Я так понимаю, что TVExplorer UDF не подходит тебе из принципа.

:smile:
 

AZJIO

Меценат
Меценат
Сообщения
2,894
Репутация
1,196
Файловый менеджер
Аналогичный алгоритм менеджера реестра

Обновил алгоритм немного:
1. Вместо добавления пустышки использовал _GUICtrlTreeView_SetChildren
2. Вместо самодельной функции _GetPathItem использовал _GUICtrlTreeView_GetTree
3. Удалось сделать прыжок к папке/разделу из адресной строки

Заметил у некоторых аналогичных окон более упрощённый алгоритм: плюсики для разворачивания изначально добавляются всем папкам, а уже при клике, если папка не содержит вложенных папок то плюсик убирается. Немного снижение информативности в счёт увеличения скорости, особенно это актуально для FTP-менеджера.
 
Верх