Что нового

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

dronet

Знающий
Сообщения
46
Репутация
8
Нужна помощь по созданию TreeView с отображением структуры определённой директории.
В этой теме обсуждалось http://autoit-script.ru/index.php?topic=2588.0 как записать структуру директории в фаил, а потом считать её в TreeView, есть-ли варианты как можно это напрямую зделать, без записи в фаил.
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Видно нет решения средствами AutoIt, данной задачи. Чтож буду искать решения из других направлений.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
dronet [?]
Видно нет решения средствами AutoIt
И этот вывод делается на основе отсутствия ответа в твоей теме в течений двух дней?
Мда... ну чтож, видимо не судьба :suicide:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#Include <File.au3>
#Include <GUIConstantsEx.au3>
#Include <GUIImageList.au3>
#Include <GUITreeView.au3>
#Include <TreeViewConstants.au3>
#Include <WindowsConstants.au3>

Global Const $sRoot = 'C:\Program Files\AutoIt3'

$hForm = GUICreate('MyGUI', 600, 600)
GUICtrlCreateTreeView(20, 20, 560, 560, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
$hTreeView = GUICtrlGetHandle(-1)

; Windows Vista/7
DllCall('uxtheme.dll', 'uint', 'SetWindowTheme', 'hwnd', $hTreeView, 'wstr', 'Explorer', 'ptr', 0)

$hImageList = _GUIImageList_Create(16, 16, 5, 1)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 3)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 4)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 0)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
_GUICtrlTreeView_BeginUpdate($hTreeView)
_EnumDir($hTreeView, $sRoot)
_GUICtrlTreeView_SetState($hTreeView, _GUICtrlTreeView_GetFirstItem($hTreeView), $TVIS_EXPANDED, 1)
_GUICtrlTreeView_EndUpdate($hTreeView)

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func _EnumDir($hWnd, $sRoot, $hItem = 0)

	Local $hSubItem, $sItem, $aList

	$sRoot = StringRegExpReplace($sRoot, '\\+\Z', '')
	$sItem = StringRegExpReplace($sRoot, '^.*\\', '')
	If StringRight($sItem, 1) = ':' Then
		$sItem &= '\'
	EndIf
	$hSubItem = _GUICtrlTreeView_AddChild($hWnd, $hItem, $sItem, 0, 1)
	$aList = _FileListToArray($sRoot, '*', 2)
	If Not @error Then
		For $i = 1 To $aList[0]
			_EnumDir($hWnd, $sRoot & '\' & $aList[$i], $hSubItem)
		Next
	EndIf

; Если нужен список файлов

;	$aList = _FileListToArray($sRoot, '*', 1)
;	If Not @error Then
;		For $i = 1 To $aList[0]
;			_GUICtrlTreeView_AddChild($hWnd, $hSubItem, $aList[$i], 2, 2)
;		Next
;	EndIf

EndFunc   ;==>_EnumDir

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

	Local $tNMTREEVIEW = DllStructCreate($tagNMTREEVIEW, $lParam)
	Local $hTV = DllStructGetData($tNMTREEVIEW, 'hWndFrom')
	Local $ID = DllStructGetData($tNMTREEVIEW, 'Code')

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDA, $TVN_ITEMEXPANDEDW
					_GUICtrlTreeView_SetImageIndex($hTreeView, DllStructGetData($tNMTREEVIEW, 'NewhItem'), BitAND(DllStructGetData($tNMTREEVIEW, 'NewState'), $TVIS_EXPANDED) = $TVIS_EXPANDED)
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Yashied.
Спасибо! Этот пример даже меньше чем с другой темы форума, и работает быстрее, а главное не надо создавать лишние файлы обмена данных. Теперь настрою иконки, и попробую присвоить к каждому элементу контекст меню.
Вопрос для того кто может ответить на него.
Я никак не могу понять для чего нужна эта функция.

Код:
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')  
-->Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
С перебором файлов и отображением иконок для них, будет значительно медленнее :(
 

Yashied

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

Отвечает за изменение иконок у папок при их раскрытии/сворачивании. В Windows XP эти иконки различаются, в Vista/7 - одинаковые (можно удалить этот кусок).
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
CreatoR сказал(а):
С перебором файлов и отображением иконок для них, будет значительно медленнее.

Для того, чтобы было быстро, нужно добвлять содержимое папок по мере их раскрытия.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
Для того, чтобы было быстро, нужно добвлять содержимое папок по мере их раскрытия.
Знаю...

Вот пока что пример с полным чтением, медленно, но работает (на XP):

Код:
#include <File.au3>
#include <GUIConstantsEx.au3>
#include <GUIImageList.au3>
#include <GUITreeView.au3>
#include <TreeViewConstants.au3>
#include <WindowsConstants.au3>

Global Const $sRoot = @DesktopDir

$hForm = GUICreate('MyGUI', 600, 600)
GUICtrlCreateTreeView(20, 20, 560, 560, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
$hTreeView = GUICtrlGetHandle(-1)

; Windows Vista/7
DllCall('uxtheme.dll', 'uint', 'SetWindowTheme', 'hwnd', $hTreeView, 'wstr', 'Explorer', 'ptr', 0)

$hImageList = _GUIImageList_Create(16, 16, 5, 1)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 3)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 4)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 0)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
_GUICtrlTreeView_BeginUpdate($hTreeView)
_GUICtrlTreeView_EnumDir($hTreeView, $sRoot)
_GUICtrlTreeView_SetState($hTreeView, _GUICtrlTreeView_GetFirstItem($hTreeView), $TVIS_EXPANDED, 1)
_GUICtrlTreeView_EndUpdate($hTreeView)

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func _FileGetIcon($sFile, $iFixIconID = 1)
	Local $iOld_Opt_EES = Opt("ExpandEnvStrings", 1)
	Local $sRegDefault = "", $sDefIcon = "", $sExecutable, $sExt, $a_LinkInfo, $s_TargetFile, $s_IconFile, $hSearch, $sIconFile
	Local $nIcon = 0, $iError = 0, $aRet[3]

	If StringInStr(FileGetAttrib($sFile & "\"), "D") Then
		$sRegDefault = RegRead("HKCR\Folder", "")

		If $sRegDefault <> "" Then
			$sDefIcon = RegRead("HKCR\Folder\DefaultIcon", "")
		EndIf
	Else
		$sExt = StringRegExpReplace($sFile, '^.*\.', '.')
		
		If $sExt = ".exe" And FileExists($sFile) Then
			Opt("ExpandEnvStrings", $iOld_Opt_EES)

			If _WinAPI_ExtractIconEx($sFile, 0, 0, 0, 1) = 0 Then
				$sFile = @SystemDir & '\shell32.dll'
				$nIcon = -3
			EndIf

			If $iFixIconID Then
				$nIcon = -($nIcon + ($nIcon > 0))
			EndIf

			Dim $aRet[3] = [2, $sFile, $nIcon]
			Return $aRet
		EndIf

		If $sExt = ".lnk" Then
			$aLinkInfo = FileGetShortcut($sFile)

			If Not @error Then
				$s_TargetFile = $aLinkInfo[0]
				$s_IconFile = $aLinkInfo[4]

				Opt("ExpandEnvStrings", $iOld_Opt_EES)

				If Not FileExists($s_IconFile) Then
					$a_LinkInfo = _FileGetIcon($s_TargetFile, 0)

					If Not @error Then
						$aLinkInfo[4] = $a_LinkInfo[1]
						$aLinkInfo[5] = $a_LinkInfo[2]
					EndIf
				EndIf

				If $iFixIconID Then
					$aLinkInfo[5] = -($aLinkInfo[5] + ($aLinkInfo[5] > 0))
				EndIf

				Dim $aRet[3] = [2, $aLinkInfo[4], $aLinkInfo[5]]
				Return $aRet
			EndIf
		EndIf

		If $sExt = $sFile Then
			$hSearch = FileFindFirstFile($sFile & ".*")
			$sExt = StringRegExpReplace(FileFindNextFile($hSearch), '^.*\.', '.')
			$sFile &= $sExt
			FileClose($hSearch)
		EndIf

		$sRegDefault = RegRead("HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" & $sExt, "ProgID")

		If $sRegDefault = "" Then
			$sRegDefault = RegRead("HKCR\" & $sExt, "")
		EndIf

		If $sRegDefault <> "" Then
			$sDefIcon = RegRead("HKCR\" & $sRegDefault & "\DefaultIcon", "")

			If $sDefIcon = "" Then
				$sDefIcon = RegRead("HKCR\" & $sExt & "\DefaultIcon", "")
			EndIf
		Else
			$sRegDefault = RegRead("HKCR\" & $sExt, "PerceivedType")

			If $sRegDefault <> "" Then
				$sRegDefault = RegRead("HKCR\SystemFileAssociations\" & $sRegDefault & "\DefaultIcon", "")
			EndIf
		EndIf
	EndIf

	If $sDefIcon = "" And $sRegDefault <> "" Then
		$sDefIcon = RegRead("HKCR\" & $sRegDefault & "\CurVer", "") ; ADOBE PERVERSION....

		If $sDefIcon Then
			$sDefIcon = RegRead("HKCR\" & $sDefIcon & "\DefaultIcon", "")
		Else
			$sDefIcon = RegRead("HKCR\" & $sRegDefault & "\shell\open\command", "")
			$sDefIcon = StringReplace($sDefIcon, ' "%1"', '')
		EndIf
	EndIf

	If $sDefIcon = "" Then
		$sIconFile = @SystemDir & "\shell32.dll"
	ElseIf Not StringRegExp($sDefIcon, '\A"*%1"*\z') Then
		If StringRegExpReplace($sFile, "^.*\\", "") = "shell32.dll" Then
			$sIconFile = $sFile
			$nIcon = 0
		Else
			Local $aDefIconSplit = StringSplit($sDefIcon, ",")

			If IsArray($aDefIconSplit) Then
				$sIconFile = $aDefIconSplit[1]

				If $aDefIconSplit[0] > 1 Then
					$nIcon = $aDefIconSplit[2]
				EndIf
			Else
				$iError = 1
			EndIf
		EndIf
	Else
		$sIconFile = -1 ;$sFile
		$nIcon = 0
	EndIf

	If Not FileExists($sIconFile) And Not FileExists(@SystemDir & "\" & $sIconFile) Then
		$sExecutable = _WinAPI_FindExecutable($sFile)

		If FileExists($sExecutable) Then
			$sIconFile = $sExecutable
		Else
			$sExecutable = _WinAPI_PathFindOnPath($sIconFile)

			If FileExists($sExecutable) Then
				$sIconFile = $sExecutable
			EndIf
		EndIf
	ElseIf FileExists(@SystemDir & "\" & $sIconFile) Then
		$sIconFile = @SystemDir & "\" & $sIconFile
	EndIf

	Opt("ExpandEnvStrings", $iOld_Opt_EES)

	If $iFixIconID Then
		$nIcon = -($nIcon + ($nIcon > 0))
	EndIf

	If Not FileExists($sIconFile) Then
		$iError = 1
	EndIf

	Dim $aRet[3] = [2, StringRegExpReplace($sIconFile, '\A"+|"+\z', ''), $nIcon]
	Return SetError($iError, 0, $aRet)
EndFunc   ;==>_FileGetIcon

Func _GUICtrlTreeView_EnumDir($hWnd, $sRoot, $hItem = 0)
	Local $hSubItem, $sItem, $aList
	$sRoot = StringRegExpReplace($sRoot, '\\+\Z', '')
	$sItem = StringRegExpReplace($sRoot, '^.*\\', '')
	If StringRight($sItem, 1) = ':' Then
		$sItem &= '\'
	EndIf
	$hSubItem = _GUICtrlTreeView_AddChild($hWnd, $hItem, $sItem, 0, 1)
	$aList = _FileListToArray($sRoot, '*', 2)
	If Not @error Then
		For $i = 1 To $aList[0]
			_GUICtrlTreeView_EnumDir($hWnd, $sRoot & '\' & $aList[$i], $hSubItem)
		Next
	EndIf

	; Если нужен список файлов
	$aList = _FileListToArray($sRoot, '*', 1)

	If Not @error Then
		For $i = 1 To $aList[0]
			$aIcon = _FileGetIcon($sRoot & '\' & $aList[$i], 0)

			If Not @error Then
				$iIcon = _GUIImageList_AddIcon($hImageList, $aIcon[1], $aIcon[2])
			Else
				$iIcon = 2
			EndIf

			_GUICtrlTreeView_AddChild($hWnd, $hSubItem, $aList[$i], $iIcon, $iIcon)
		Next
	EndIf
EndFunc   ;==>_GUICtrlTreeView_EnumDir

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
	Local $tNMTREEVIEW = DllStructCreate($tagNMTREEVIEW, $lParam)
	Local $hTV = DllStructGetData($tNMTREEVIEW, 'hWndFrom')
	Local $ID = DllStructGetData($tNMTREEVIEW, 'Code')

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDA, $TVN_ITEMEXPANDEDW
					_GUICtrlTreeView_SetImageIndex($hTreeView, _
							DllStructGetData($tNMTREEVIEW, 'NewhItem'), _
							BitAND(DllStructGetData($tNMTREEVIEW, 'NewState'), $TVIS_EXPANDED) = $TVIS_EXPANDED)
			EndSwitch
	EndSwitch

	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY


Если сможешь из этого сделать создание дерева на лету (при раскрытий), буду признателен.
 

Yashied

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

Код:
#Include <File.au3>
#Include <GUIConstantsEx.au3>
#Include <GUIImageList.au3>
#Include <GUITreeView.au3>
#Include <TreeViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>

Global Const $sPath = @DesktopDir

Dim $aParam[1001] = [0]

$hForm = GUICreate('MyGUI', 600, 600)
$Input = GUICtrlCreateInput('', 20, 20, 560, 19)
$hInput = GUICtrlGetHandle(-1)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlCreateTreeView(20, 50, 560, 530, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
$hTreeView = GUICtrlGetHandle(-1)
$Dummy = GUICtrlCreateDummy()

; Windows Vista/7
DllCall('uxtheme.dll', 'uint', 'SetWindowTheme', 'hwnd', $hTreeView, 'wstr', 'Explorer', 'ptr', 0)

$hSelect = 0

$hImageList = _GUIImageList_Create(16, 16, 5, 1)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 3)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 4)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
$sRoot = StringRegExpReplace($sPath, '\\+\Z', '')
$sItem = StringRegExpReplace($sRoot, '^.*\\', '')
If StringRight($sItem, 1) = ':' Then
	$sItem &= '\'
EndIf
;_GUICtrlTreeView_BeginUpdate($hTreeView)
_Update($hTreeView, _GUICtrlTreeView_AddChild($hTreeView, 0, $sItem, 0, 0), $sRoot)
;_GUICtrlTreeView_EndUpdate($hTreeView)

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

;_GUICtrlTreeView_Expand($hTreeView, _GUICtrlTreeView_GetFirstItem($hTreeView))

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Dummy
			GUISetState(@SW_DISABLE)
			GUISetCursor(15, 1)
			$hItem = GUICtrlRead($Dummy)
			$hSubItem = _GUICtrlTreeView_GetFirstChild($hTreeView, $hItem)
			If $hSubItem Then
				$iParam =_GUICtrlTreeView_GetItemParam($hTreeView, $hItem)
				While $hSubItem
					_Update($hTreeView, $hSubItem, $aParam[$iParam] & '\' & _GUICtrlTreeView_GetText($hTreeView, $hSubItem))
					$hSubItem = _GUICtrlTreeView_GetNextSibling($hTreeView, $hSubItem)
				WEnd
				_WinAPI_RedrawWindow($hTreeView)
			EndIf
			GUISetState(@SW_ENABLE)
			GUISetCursor(2, 0)
	EndSwitch
WEnd

Func _Update($hWnd, $hItem, $sRoot)

	Local $aList

	$aParam[0] += 1
	If $aParam[0] > UBound($aParam) - 1 Then
		ReDim $aParam[$aParam[0] + 1000]
	EndIf
	$aParam[$aParam[0]] = $sRoot
	_GUICtrlTreeView_SetItemParam($hWnd, $hItem, -$aParam[0])
	$aList = _FileListToArray($sRoot, '*', 2)
	If IsArray($aList) Then
		For $i = 1 To $aList[0]
			_GUICtrlTreeView_AddChild($hWnd, $hItem, $aList[$i], 0, 0)
		Next
	EndIf
	$aList = _FileListToArray($sRoot, '*', 1)
	If IsArray($aList) Then
		For $i = 1 To $aList[0]
			$hIcon = _WinAPI_ShellExtractAssociatedIcon($sRoot & '\' & $aList[$i], 1)
			_GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
			_WinAPI_DestroyIcon($hIcon)
			$Index = _GUIImageList_GetImageCount($hImageList) - 1
			_GUICtrlTreeView_AddChild($hWnd, $hItem, $aList[$i], $Index, $Index)
		Next
	EndIf
EndFunc   ;==>_Update

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 $iParam, $sText

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDW
					If Not BitAND($iState, $TVIS_EXPANDED) Then
						_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 0)
						_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 0)
					Else
						_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 1)
						_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 1)
						$iParam = _GUICtrlTreeView_GetItemParam($hTV, $hItem)
						If $iParam < 0 Then
							_GUICtrlTreeView_SetItemParam($hTV, $hItem, Abs($iParam))
							GUICtrlSendToDummy($Dummy, $hItem)
						EndIf
					EndIf
				Case $TVN_SELCHANGEDW
					If BitAND($iState, $TVIS_SELECTED) Then
						If $hItem <> $hSelect Then
							$sText = $aParam[Abs(_GUICtrlTreeView_GetItemParam($hTV, $hItem))] & '\' & _GUICtrlTreeView_GetText($hTV, $hItem)
							GUICtrlSetData($Input, _WinAPI_PathCompactPath($hInput, $sText, 554))
							$hSelect = $hItem
						EndIf
					EndIf
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY


WinAPEx
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied
Супер!
:ok:
 

Yashied

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

:wacko:

Баг?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Yashied
подтверждаю
 

Yashied

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

:wall_brake:

Дело в том, что AutoIt использует параметр $iParam (см. функцию _GUICtrlTreeView_SetItemParam()) в каждом элементе TreeView и ListView для хранения внутренних ID этих элементов, т.е. тех, которые возвращают GUICtrlCreateTreeViewItem() и GUICtrlCreateListViewItem() функции. А я их использовал в этом примере для хранения индексов в массиве $aParam для увеличения скорости обработки. Ну, и AutoIt впал в глубокий ступор от этого, несмотря на то, что я никаким боком не использовал функцию GUICtrlCreateTreeViewItem(). Решение: нумеровать элементы с другого конца, т.е. хранить значения индексов в $iParam в инвертированном виде (0x7FFFFFFF - индекс).

Это не баг, просто об этом нигде ничего не сказано, хотя надо бы. Из этого следует, что функции _GUICtrlListView_SetItemParam() и _GUICtrlTreeView_SetItemParam() следует использоват очень осторожно.

Код:
#Include <File.au3>
#Include <GUIConstantsEx.au3>
#Include <GUIImageList.au3>
#Include <GUITreeView.au3>
#Include <TreeViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>

Global Const $sPath = @DesktopDir

Dim $aParam[1001] = [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, 530, -1, $WS_EX_CLIENTEDGE)
$hTreeView = GUICtrlGetHandle(-1)
$Dummy = GUICtrlCreateDummy()

; Windows Vista/7
DllCall('uxtheme.dll', 'uint', 'SetWindowTheme', 'hwnd', $hTreeView, 'wstr', 'Explorer', 'ptr', 0)

$hSelect = 0

$hImageList = _GUIImageList_Create(16, 16, 5, 1)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 3)
_GUIImageList_AddIcon($hImageList, @SystemDir & '\shell32.dll', 4)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
$sRoot = StringRegExpReplace($sPath, '\\+\Z', '')
$sItem = StringRegExpReplace($sRoot, '^.*\\', '')
If StringRight($sItem, 1) = ':' Then
	$sItem &= '\'
EndIf
;_GUICtrlTreeView_BeginUpdate($hTreeView)
_Update($hTreeView, _GUICtrlTreeView_AddChild($hTreeView, 0, $sItem, 0, 0), $sRoot)
;_GUICtrlTreeView_EndUpdate($hTreeView)

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

;_GUICtrlTreeView_Expand($hTreeView, _GUICtrlTreeView_GetFirstItem($hTreeView))

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Dummy
			GUISetState(@SW_DISABLE)
			GUISetCursor(15, 1)
			$hItem = GUICtrlRead($Dummy)
			$hSubItem = _GUICtrlTreeView_GetFirstChild($hTreeView, $hItem)
			If $hSubItem Then
				$iParam = 2147483647 - _GUICtrlTreeView_GetItemParam($hTreeView, $hItem)
				While $hSubItem
					_Update($hTreeView, $hSubItem, $aParam[$iParam] & '\' & _GUICtrlTreeView_GetText($hTreeView, $hSubItem))
					$hSubItem = _GUICtrlTreeView_GetNextSibling($hTreeView, $hSubItem)
				WEnd
				_WinAPI_RedrawWindow($hTreeView)
			EndIf
			GUISetState(@SW_ENABLE)
			GUISetCursor(2, 0)
	EndSwitch
WEnd

Func _Update($hWnd, $hItem, $sRoot)

	Local $aList

	$aParam[0] += 1
	If $aParam[0] > UBound($aParam) - 1 Then
		ReDim $aParam[$aParam[0] + 1000]
	EndIf
	$aParam[$aParam[0]] = $sRoot
	_GUICtrlTreeView_SetItemParam($hWnd, $hItem, -(2147483647 - $aParam[0]))
	$aList = _FileListToArray($sRoot, '*', 2)
	If IsArray($aList) Then
		For $i = 1 To $aList[0]
			_GUICtrlTreeView_AddChild($hWnd, $hItem, $aList[$i], 0, 0)
		Next
	EndIf
	$aList = _FileListToArray($sRoot, '*', 1)
	If IsArray($aList) Then
		For $i = 1 To $aList[0]
			$hIcon = _WinAPI_ShellExtractAssociatedIcon($sRoot & '\' & $aList[$i], 1)
			_GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
			_WinAPI_DestroyIcon($hIcon)
			$Index = _GUIImageList_GetImageCount($hImageList) - 1
			_GUICtrlTreeView_AddChild($hWnd, $hItem, $aList[$i], $Index, $Index)
		Next
	EndIf
EndFunc   ;==>_Update

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 $iParam, $sText

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDW
					If Not BitAND($iState, $TVIS_EXPANDED) Then
						_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 0)
						_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 0)
					Else
						_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 1)
						_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 1)
						$iParam = _GUICtrlTreeView_GetItemParam($hTV, $hItem)
						If $iParam < 0 Then
							_GUICtrlTreeView_SetItemParam($hTV, $hItem, Abs($iParam))
							GUICtrlSendToDummy($Dummy, $hItem)
						EndIf
					EndIf
				Case $TVN_SELCHANGEDW
					If BitAND($iState, $TVIS_SELECTED) Then
						If $hItem <> $hSelect Then
							$sText = $aParam[2147483647 - Abs(_GUICtrlTreeView_GetItemParam($hTV, $hItem))] & '\' & _GUICtrlTreeView_GetText($hTV, $hItem)
							GUICtrlSetData($Input, _WinAPI_PathCompactPath($hInput, $sText, 554))
							$hSelect = $hItem
						EndIf
					EndIf
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Поскольку у меня _WinAPI_ShellExtractAssociatedIcon не находит иконку htm-файла ,
приведу вариант с ф-ией : _WinAPI_FindExecutable
благополучно находящую ее.
Код:
#region *** INCLUDES ***
#include<WindowsConstants.au3>
#include<GuiConstantsEx.au3>
#include <File.au3>
#include <GuiTreeView.au3>
#endregion

$hGui = GUICreate("Дерево папок и файлов в TreeView v2", 600, 900)
;$hTreeView = GUICtrlCreateTreeView(10, 10, 500, 850 ,BitOr($TVS_HASLINES,$TVS_HASBUTTONS,$TVS_SINGLEEXPAND) , $WS_EX_DLGMODALFRAME ) ; Одинарный клик
$hTreeView = GUICtrlCreateTreeView(10, 10, 500, 850 ,BitOr($TVS_HASLINES,$TVS_HASBUTTONS) , $WS_EX_DLGMODALFRAME )
GUISetState()

TreeView_SetDrives($hTreeView,"FIXED"); ===>

While 1
   $nMsg = GUIGetMsg()
   Switch $nMsg
	  Case $GUI_EVENT_CLOSE
		 Exit
	  Case $GUI_EVENT_PRIMARYUP; 
		 $aCursor=GUIGetCursorInfo ($hGui)
		 If $aCursor[4]=0 Then ContinueLoop
		 If $aCursor[4] = $hTreeView Then	
			$hItem=_GUICtrlTreeView_GetSelection($hTreeView)
			$sFilePath=TreeView_UpDate($hTreeView,$hItem) ; ===>
		 EndIf
   EndSwitch
WEnd

Func TreeView_UpDate($hTV,$hItem=-1,$sPattern="*.*")
   If $hItem=0 Then Return
   $sFullName=StringReplace(_GUICtrlTreeView_GetTree($hTV, $hItem) ,'|','\')
   If _GUICtrlTreeView_GetChildren($hTV, $hItem) = False Then
	  If Not StringInStr(FileGetAttrib (  $sFullName ),"D")Then Return $sFullName
	  $aFolderList = _FileListToArray($sFullName, '*', 2)
	  For $i = 1 To UBound($aFolderList) - 1
		 $hChildFolder= _GUICtrlTreeView_AddChild($hTV,$hItem,  $aFolderList[$i])
		 _GUICtrlTreeView_SetIcon($hTV,$hChildFolder, "shell32.dll",3)
	  Next
	  $aFileList = _FileListToArray($sFullName, $sPattern, 1)
	  For $i = 1 To UBound($aFileList) - 1
		 $hChild= _GUICtrlTreeView_AddChild($hTV,$hItem,  $aFileList[$i])
		 $FileFullPath= $sFullName & "\" & $aFileList[$i]
		 $aIconInfo =FileGetIcon($FileFullPath)
		 _GUICtrlTreeView_SetIcon($hTV, $hChild, $aIconInfo[1],$aIconInfo[2])
	  Next
   EndIf
;   _GUICtrlTreeView_Expand($hTV, $hItem); Одинарный клик
   Return $sFullName
 EndFunc ; ====> TreeView_UpDate
 
 Func FileGetIcon($sFile)
   Local $aRet[3]=[2,"shell32.dll",0]
   Local $iOld_Opt_EES = Opt("ExpandEnvStrings", 1)
   $sExt = StringRegExpReplace($sFile, '^.*\.', '.')
   $sDefIcon =RegRead('HKCR\' & RegRead('HKCR\' &  $sExt, '') & '\DefaultIcon', '')
   If $sDefIcon ="" Then 
	  If $sExt = ".lnk" Then
		 $aLinkInfo = FileGetShortcut($sFile)
		 If FileExists($aLinkInfo[0]) Then $aRet= FileGetIcon($aLinkInfo[0]); ====>
	  EndIf
   ElseIf StringRegExp($sDefIcon, '\A"*%1"*\z') Then
	  If  $sExt=".exe" Then
		 $aRet[1]=$sFile
	  Else
		 $sExecutable = _WinAPI_FindExecutable($sFile)
		 If $sExecutable="" Then 
			$aRet[1]=$sFile
		 Else
			$aRet[1]=$sExecutable
		 EndIf
	  EndIf
   Else
	  $aSplit=StringSplit($sDefIcon,",")
	  If Not IsArray($aSplit)  Then  
		  $aRet[1]=$sDefIcon
	  ElseIf $aSplit[0]=1 Then
		  $aRet[1]=$aSplit[1]
	  Else
		  $aRet=$aSplit
	  EndIf
   EndIf
   $aRet[1]=StringReplace($aRet[1],'"',"")
   Return $aRet
 EndFunc
 
Func TreeView_SetDrives($hTV, $sType= "ALL")
   $aDisk=DriveGetDrive($sType)
   _GUICtrlTreeView_BeginUpdate($hTV)
   _GUICtrlTreeView_DeleteAll($hTV)
   For $i=1 To UBound($aDisk)-1
	  $aDisk[$i]=StringUpper ( $aDisk[$i] )
	  $hItem= GUICtrlCreateTreeViewItem($aDisk[$i], $hTV)
	  _GUICtrlTreeView_SetIcon($hTV,$hItem, "shell32.dll",7)
   Next
   _GUICtrlTreeView_EndUpdate($hTV)	
EndFunc ; ====> TreeView_SetDrives

Кстати этот вариант работает быстрее

Вопрос к Creator'у :
В чем необходимость неоднократной установки : Opt("ExpandEnvStrings", 1) в 1-й ф-ии ?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
gregaz [?]
В чем необходимость неоднократной установки : Opt("ExpandEnvStrings", 1) в 1-й ф-ии ?
Для расширения переменных окружения (при чтений с реестра).
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
CreatoR [?]
Для расширения переменных окружения (при чтений с реестра).
Это понятно , а почему несколько раз ? Нельзя ли один раз в ф-ии ?

В твоей ф-ии иконки для TreeView не корректны (знак обратный). Они годятся для Image
Обрати внимание на .txt. , .dat , .dll .ini и некоторые др.
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Yashied
:shok: Этот пример уже на профессиональном уровне, можно уже делать свой фаил-менеджер :smile:.
Ну это ладно, это я так...
Суть в том что там так запутанно всё, что не разобратса не-как, куда записать код... :'(
Хочю чтоб контекстное меню было, для папок один пункт, для файлов другой пункт.

Попробовал от gregaz пример, тоже не плохой. только глюк есть, хотел "сложить" дерево папок, а оно опять раскладываетса, нажал на минус дерево сложилось и сразу разложилось :blink:
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
dronet [?]
только глюк есть, хотел "сложить" дерево папок, а оно опять раскладываетса, нажал на минус дерево сложилось и сразу разложилось

В общем это не совсем глюк
Сделал так,чтобы все время была открыта только одна ветка.
Ветка закрывается только при открытии другой ветки.
Можно убрать это ,убрав стиль $TVS_SINGLEEXPAND
Код:
$hTreeView = GUICtrlCreateTreeView(10, 10, 500, 850 ,BitOr($TVS_HASLINES,$TVS_HASBUTTONS) , $WS_EX_DLGMODALFRAME );,$TVS_SINGLEEXPAND

и закомментировав (или убрав) :
Код:
;_GUICtrlTreeView_Expand($hTV, $hItem)
Но работать будет только при двойном клике
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Yashied [?]
Кстати, это только у меня так: если развернуть корневую директорию и затем щелкнуть (выделить) второй элемент сверху, то GUI благополучно закрывается

Я когда-то сталкивался с подобной штукой.
Так и не поняв причины я сдвинул начальный индекс и все пошло.
Здесь пожет тоже можно задать в начале не :
Код:
Dim $aParam[1001] = [0]

а
Код:
Dim $aParam[1001] = [100]
 
Верх