Что нового

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

Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Yashied
У меня одного отображаетса так в Input-е или это так задуманно?
C:\Директория\Директория\Директория\Фаил.???\Фаил.???
C:\Директория\Директория\Директория\КонечнаяДиректория\КонечнаяДиректория


Убрал в конце из
$sText = $aParam[2147483647 - Abs(_GUICtrlTreeView_GetItemParam($hTV, $hItem))] & '\' & _GUICtrlTreeView_GetText($hTV, $hItem)
Вот такое написание
& '\' & _GUICtrlTreeView_GetText($hTV, $hItem) теперь отображает так.

Теперь отображает как и должно отображатса
C:\Директория\Директория\Директория\Фаил.???
C:\Директория\Директория\Директория\КонечнаяДиректория

Пс! Помогите кто понимает. Укажите куда прописать код для контекстного меню на пункты. - на сам TreeVie это не проблема я уже зделал.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вот окончательный вариант. Увеличена скорость и добавлена проверка существования папок и файлов "на лету", т.е., если файл или папка была удалена, то в TreeView она исчезнет при ее выделении или развериовании/свертовании втки. А также, я избавился от массива $aParam.

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

Opt('MustDeclareVars', 1)

Global $hForm, $hTreeView, $hImageList, $hItem, $hNext, $hSelect = 0, $hInput, $Input, $Dummy
Global $sPath, $sRoot = @HomeDrive

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

If _WinAPI_GetVersion() >= '6.0' Then
	_WinAPI_SetWindowTheme($hTreeView, 'Explorer')
EndIf

$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($sRoot, '\\+\Z', '')
$sPath = StringRegExpReplace($sRoot, '^.*\\', '')
If StringInStr($sPath, ':') Then
	$sRoot &= '\'
	$sPath &= '\'
EndIf

;_GUICtrlTreeView_BeginUpdate($hTreeView)
_TVUpdate($hTreeView, _GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, 0, 0))
;_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
			GUISetCursor(1, 1)
			$hItem = _GUICtrlTreeView_GetFirstChild($hTreeView, GUICtrlRead($Dummy))
			If $hItem Then
				While $hItem
					$hNext = _GUICtrlTreeView_GetNextSibling($hTreeView, $hItem)
					If Not _TVUpdate($hTreeView, $hItem) Then
						_GUICtrlTreeView_Delete($hTreeView, $hItem)
					EndIf
					$hItem = $hNext
				WEnd
				_WinAPI_RedrawWindow($hTreeView)
			EndIf
			GUISetCursor(2, 0)
	EndSwitch
WEnd

Func _TVGetPath($hTV, $hItem, $sRoot)

	Local $Path = StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $hItem), '([|]+)|(\\[|])', '\\')

	If Not $Path Then
		Return ''
	EndIf
	If Not StringInStr($Path, ':') Then
		Return StringRegExpReplace($sRoot, '(\\[^\\]*(\\|)+)\Z', '\\') & $Path
	EndIf
	Return $Path
EndFunc   ;==>_TVGetPath

Func _TVSetPath($hTV, $hItem, $sRoot)
	GUICtrlSetData($Input, _WinAPI_PathCompactPath($hInput, _TVGetPath($hTV, $hItem, $sRoot), 554))
EndFunc   ;==>_TVSetPath

Func _TVUpdate($hTV, $hItem)

	Local $hImageList = _SendMessage($hTV, $TVM_GETIMAGELIST)
	Local $Path = StringRegExpReplace(_TVGetPath($hTV, $hItem, $sRoot), '\\+\Z', '')
	Local $hSearch, $hIcon, $Index, $File

	$hSearch = FileFindFirstFile($Path & '\*')
	If $hSearch = -1 Then
		If Not @error Then
			If FileExists($Path) Then
;				If _WinAPI_PathIsDirectory($Path) Then
;					; Access denied
;				EndIf
			Else
				Return 0
			EndIf
		EndIf
	Else
		While 1
			$File = FileFindNextFile($hSearch)
			If @error Then
				ExitLoop
			EndIf
			If @extended Then
				_GUICtrlTreeView_AddChild($hTV, $hItem, $File, 0, 0)
			EndIf
		WEnd
		FileClose($hSearch)
	EndIf
	$hSearch = FileFindFirstFile($Path & '\*')
	If $hSearch = -1 Then

	Else
		While 1
			$File = FileFindNextFile($hSearch)
			If @error Then
				ExitLoop
			EndIf
			If Not @extended Then
				$hIcon = _WinAPI_ShellExtractAssociatedIcon($Path & '\' & $File, 1)
				$Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
				_GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
				_WinAPI_DestroyIcon($hIcon)
			EndIf
		WEnd
		FileClose($hSearch)
	EndIf
	Return 1
EndFunc   ;==>_TVUpdate

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')

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDW
					If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
						_GUICtrlTreeView_Delete($hTV, $hItem)
						If BitAND($iState, $TVIS_SELECTED) Then
							$hSelect = _GUICtrlTreeView_GetSelection($hTV)
							_TVSetPath($hTV, $hSelect, $sRoot)
						EndIf
					Else
						If Not BitAND($iState, $TVIS_EXPANDED) Then
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 0)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 0)
						Else
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 1)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 1)
							If Not _GUICtrlTreeView_GetItemParam($hTV, $hItem) Then
								_GUICtrlTreeView_SetItemParam($hTV, $hItem, 0x7FFFFFFF)
								GUICtrlSendToDummy($Dummy, $hItem)
							EndIf
						EndIf
					EndIf
				Case $TVN_SELCHANGEDW
					If BitAND($iState, $TVIS_SELECTED) Then
						If $hItem <> $hSelect Then
							If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
								_GUICtrlTreeView_Delete($hTV, $hItem)
								$hSelect = _GUICtrlTreeView_GetSelection($hTV)
							Else
								$hSelect = $hItem
							EndIf
							_TVSetPath($hTV, $hSelect, $sRoot)
						EndIf
					EndIf
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Я наверное зделаю так, что пропишу в Func WM_NOTIFY
Case $отслеживать правый клик
If если это фаил то тогда контекстное меню такое-то.....
это наверное самый оптимальный вариант так я считаю.

А также поэксперементирую с параметрами -
$hTV
$ID
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Yashied [?]
добавлена проверка существования папок и файлов "на лету"

Нужная фича. Еще бы добавить возможность занесения появившейся новой папки\файла .
 

Yashied

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

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

Opt('MustDeclareVars', 1)

Global $hForm, $hTreeView, $hImageList, $hItem, $hNext, $hSelect = 0, $hInput, $Input, $Dummy1, $Dummy2
Global $X, $Y, $sPath, $sRoot = @HomeDrive

$hForm = GUICreate('MyGUI', 600, 600)
$Input = GUICtrlCreateInput('', 20, 20, 560, 19)
$hInput = GUICtrlGetHandle(-1)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlCreateTreeView(20, 50, 560, 530, -1, $WS_EX_CLIENTEDGE)
$hTreeView = GUICtrlGetHandle(-1)
$Dummy1 = GUICtrlCreateDummy()
$Dummy2 = GUICtrlCreateDummy()

If _WinAPI_GetVersion() >= '6.0' Then
	_WinAPI_SetWindowTheme($hTreeView, 'Explorer')
EndIf

$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($sRoot, '\\+\Z', '')
$sPath = StringRegExpReplace($sRoot, '^.*\\', '')
If StringInStr($sPath, ':') Then
	$sRoot &= '\'
	$sPath &= '\'
EndIf

;_GUICtrlTreeView_BeginUpdate($hTreeView)
_TVUpdate($hTreeView, _GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, 0, 0))
;_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 $Dummy1 ; Update
			GUISetCursor(1, 1)
			$hItem = _GUICtrlTreeView_GetFirstChild($hTreeView, GUICtrlRead($Dummy1))
			If $hItem Then
				While $hItem
					$hNext = _GUICtrlTreeView_GetNextSibling($hTreeView, $hItem)
					If Not _TVUpdate($hTreeView, $hItem) Then
						_GUICtrlTreeView_Delete($hTreeView, $hItem)
					EndIf
					$hItem = $hNext
				WEnd
				_WinAPI_RedrawWindow($hTreeView)
			EndIf
			GUISetCursor(2, 0)
		Case $Dummy2 ; Menu
			$hItem = GUICtrlRead($Dummy2)
			$sPath = _TVGetPath($hTreeView, $hItem, $sRoot)

			ConsoleWrite('-------------------------------' & @CR)
			ConsoleWrite('Handle: ' & $hItem & @CR)
			ConsoleWrite('Path:   ' & $sPath & @CR)
			If _WinAPI_PathIsDirectory($sPath) Then
				ConsoleWrite('Type:   ' & 'Directory' & @CR)
			Else
				ConsoleWrite('Type:   ' & 'File' & @CR)
			EndIf
			ConsoleWrite('X:      ' & MouseGetPos(0) & @CR)
			ConsoleWrite('Y:      ' & MouseGetPos(1) & @CR)
			ConsoleWrite('-------------------------------' & @CR)

	EndSwitch
WEnd

Func _TVGetPath($hTV, $hItem, $sRoot)

	Local $Path = StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $hItem), '([|]+)|(\\[|])', '\\')

	If Not $Path Then
		Return ''
	EndIf
	If Not StringInStr($Path, ':') Then
		Return StringRegExpReplace($sRoot, '(\\[^\\]*(\\|)+)\Z', '\\') & $Path
	EndIf
	Return $Path
EndFunc   ;==>_TVGetPath

Func _TVSetPath($hTV, $hItem, $sRoot)
	GUICtrlSetData($Input, _WinAPI_PathCompactPath($hInput, _TVGetPath($hTV, $hItem, $sRoot), 554))
	$hSelect = $hItem
EndFunc   ;==>_TVSetPath

Func _TVUpdate($hTV, $hItem)

	Local $hImageList = _SendMessage($hTV, $TVM_GETIMAGELIST)
	Local $Path = StringRegExpReplace(_TVGetPath($hTV, $hItem, $sRoot), '\\+\Z', '')
	Local $hSearch, $hIcon, $Index, $File

	$hSearch = FileFindFirstFile($Path & '\*')
	If $hSearch = -1 Then
		If Not @error Then
			If FileExists($Path) Then
;				If _WinAPI_PathIsDirectory($Path) Then
;					; Access denied
;				EndIf
			Else
				Return 0
			EndIf
		EndIf
	Else
		While 1
			$File = FileFindNextFile($hSearch)
			If @error Then
				ExitLoop
			EndIf
			If @extended Then
				_GUICtrlTreeView_AddChild($hTV, $hItem, $File, 0, 0)
			EndIf
		WEnd
		FileClose($hSearch)
	EndIf
	$hSearch = FileFindFirstFile($Path & '\*')
	If $hSearch = -1 Then

	Else
		While 1
			$File = FileFindNextFile($hSearch)
			If @error Then
				ExitLoop
			EndIf
			If Not @extended Then
				$hIcon = _WinAPI_ShellExtractAssociatedIcon($Path & '\' & $File, 1)
				$Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
				_GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
				_WinAPI_DestroyIcon($hIcon)
			EndIf
		WEnd
		FileClose($hSearch)
	EndIf
	Return 1
EndFunc   ;==>_TVUpdate

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 $tTVHTI, $tPoint

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDW
					If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
						_GUICtrlTreeView_Delete($hTV, $hItem)
						If BitAND($iState, $TVIS_SELECTED) Then
							_TVSetPath($hTV, _GUICtrlTreeView_GetSelection($hTV), $sRoot)
						EndIf
					Else
						If Not BitAND($iState, $TVIS_EXPANDED) Then
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 0)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 0)
						Else
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 1)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 1)
							If Not _GUICtrlTreeView_GetItemParam($hTV, $hItem) Then
								_GUICtrlTreeView_SetItemParam($hTV, $hItem, 0x80000000)
								GUICtrlSendToDummy($Dummy1, $hItem)
							EndIf
						EndIf
					EndIf
				Case $TVN_SELCHANGEDW
					If BitAND($iState, $TVIS_SELECTED) Then
						If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
							_GUICtrlTreeView_Delete($hTV, $hItem)
							$hItem = _GUICtrlTreeView_GetSelection($hTV)
						EndIf
						If $hItem <> $hSelect Then
							_TVSetPath($hTV, $hItem, $sRoot)
						EndIf
					EndIf
				Case $NM_RCLICK
						$tPoint = _WinAPI_GetMousePos(1, $hTV)
						$tTVHTI = _GUICtrlTreeView_HitTestEx($hTV, DllStructGetData($tPoint, 1), DllStructGetData($tPoint, 2))
						$hItem = DllStructGetData($tTVHTI, 'Item')
						If BitAND(DllStructGetData($tTVHTI, 'Flags'), $TVHT_ONITEM) Then
							_GUICtrlTreeView_SelectItem($hTreeView, $hItem)
							If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
								_GUICtrlTreeView_Delete($hTV, $hItem)
								$hItem = _GUICtrlTreeView_GetSelection($hTV)
							Else
								GUICtrlSendToDummy($Dummy2, $hItem)
							EndIf
							If $hItem <> $hSelect Then
								_TVSetPath($hTV, $hItem, $sRoot)
							EndIf
						EndIf
				EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY


Само контекстное меню создается AutoIt'овскими функциями, выводиться с помощью _GUICtrlMenu_TrackPopupMenu().

gregaz сказал(а):
Еще бы добавить возможность занесения появившейся новой папки\файла.

Запоминаешь текущий путь в TreeView - Очищаешь TreeView - Перечисляешь по новой корневую папку - Открываешь сокраненную ранее ветку

:smile:
 

Yashied

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

:smile:

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

Opt('MustDeclareVars', 1)

Global $hForm, $hTreeView, $hImageList, $hItem = 0, $hSelect = 0, $hInput, $Input, $Dummy1, $Dummy2
Global $X, $Y, $sPath, $sRoot = @HomeDrive

$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)
$Dummy1 = GUICtrlCreateDummy()
$Dummy2 = GUICtrlCreateDummy()

If _WinAPI_GetVersion() >= '6.0' Then
	_WinAPI_SetWindowTheme($hTreeView, 'Explorer')
EndIf

$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', 51)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
$sRoot = StringRegExpReplace(FileGetLongName($sRoot), '\\+\Z', '')
$sPath = StringRegExpReplace($sRoot, '^.*\\', '')
If StringInStr($sPath, ':') Then
	$sRoot &= '\'
	$sPath &= '\'
EndIf

If _WinAPI_PathIsDirectory($sRoot) Then
	$hItem = _GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, 0, 0)
	If FileClose(FileFindFirstFile($sRoot & '\*')) Then
		_GUICtrlTreeView_AddChild($hTreeView, $hItem, '', 2, 2)
	EndIf
EndIf

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

If $hItem Then
	_GUICtrlTreeView_Expand($hTreeView, $hItem)
EndIf

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Dummy1 ; Update
			GUISetCursor(1, 1)
			_TVUpdate($hTreeView, GUICtrlRead($Dummy1))
			GUISetCursor(2, 0)
		Case $Dummy2 ; Menu
			$hItem = GUICtrlRead($Dummy2)
			$sPath = _TVGetPath($hTreeView, $hItem, $sRoot)

			ConsoleWrite('-------------------------------' & @CR)
			ConsoleWrite('Handle: ' & $hItem & @CR)
			ConsoleWrite('Path:   ' & $sPath & @CR)
			If _WinAPI_PathIsDirectory($sPath) Then
				ConsoleWrite('Type:   ' & 'Directory' & @CR)
			Else
				ConsoleWrite('Type:   ' & 'File' & @CR)
			EndIf
			ConsoleWrite('X:      ' & MouseGetPos(0) & @CR)
			ConsoleWrite('Y:      ' & MouseGetPos(1) & @CR)
			ConsoleWrite('-------------------------------' & @CR)

	EndSwitch
WEnd

Func _TVGetPath($hTV, $hItem, $sRoot)

	Local $Path = StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $hItem), '([|]+)|(\\[|])', '\\')

	If Not $Path Then
		Return ''
	EndIf
	If Not StringInStr($Path, ':') Then
		Return StringRegExpReplace($sRoot, '(\\[^\\]*(\\|)+)\Z', '\\') & $Path
	EndIf
	Return $Path
EndFunc   ;==>_TVGetPath

Func _TVSetPath($hTV, $hItem, $sRoot)
	GUICtrlSetData($Input, _WinAPI_PathCompactPath($hInput, _TVGetPath($hTV, $hItem, $sRoot), 554))
	$hSelect = $hItem
EndFunc   ;==>_TVSetPath

Func _TVUpdate($hTV, $hItem)

	Local $hImageList = _SendMessage($hTV, $TVM_GETIMAGELIST)
	Local $Path = StringRegExpReplace(_TVGetPath($hTV, $hItem, $sRoot), '\\+\Z', '')
	Local $hIcon, $hSearch, $hSubitem
	Local $Index, $File

	_WinAPI_LockWindowUpdate($hTV)
	_GUICtrlTreeView_Delete($hTV, _GUICtrlTreeView_GetFirstChild($hTV, $hItem))

	$hSearch = FileFindFirstFile($Path & '\*')
	If $hSearch = -1 Then
		If Not @error Then
			If FileExists($Path) Then
;				If _WinAPI_PathIsDirectory($Path) Then
;					; Access denied
;				EndIf
			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
				$hSubItem = _GUICtrlTreeView_AddChild($hTV, $hItem, $File, 0, 0)
				If FileClose(FileFindFirstFile($Path & '\' & $File & '\*')) Then
					_GUICtrlTreeView_AddChild($hTV, $hSubItem, '', 2, 2)
				EndIf
			EndIf
		WEnd
		FileClose($hSearch)
	EndIf

	$hSearch = FileFindFirstFile($Path & '\*')
	If $hSearch = -1 Then

	Else
		While 1
			$File = FileFindNextFile($hSearch)
			If @error Then
				ExitLoop
			EndIf
			If Not @extended Then
				$hIcon = _WinAPI_ShellExtractAssociatedIcon($Path & '\' & $File, 1)
				$Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
				_GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
				_WinAPI_DestroyIcon($hIcon)
			EndIf
		WEnd
		FileClose($hSearch)
	EndIf

	_GUICtrlTreeView_SetItemParam($hTV, $hItem, 0x7FFFFFFF)
	_WinAPI_LockWindowUpdate(0)

	Return 1
EndFunc   ;==>_TVUpdate

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 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 $tTVHTI, $tPoint

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDW
					If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
						_GUICtrlTreeView_Delete($hTV, $hItem)
						If BitAND($iState, $TVIS_SELECTED) Then
							_TVSetPath($hTV, _GUICtrlTreeView_GetSelection($hTV), $sRoot)
						EndIf
					Else
						If Not BitAND($iState, $TVIS_EXPANDED) Then
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 0)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 0)
						Else
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 1)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 1)
							If Not _GUICtrlTreeView_GetItemParam($hTV, $hItem) Then
								GUICtrlSendToDummy($Dummy1, $hItem)
							EndIf
						EndIf
					EndIf
				Case $TVN_SELCHANGEDW
					If BitAND($iState, $TVIS_SELECTED) Then
						If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
							_GUICtrlTreeView_Delete($hTV, $hItem)
							$hItem = _GUICtrlTreeView_GetSelection($hTV)
						EndIf
						If $hItem <> $hSelect Then
							_TVSetPath($hTV, $hItem, $sRoot)
						EndIf
					EndIf
				Case $NM_RCLICK
						$tPoint = _WinAPI_GetMousePos(1, $hTV)
						$tTVHTI = _GUICtrlTreeView_HitTestEx($hTV, DllStructGetData($tPoint, 1), DllStructGetData($tPoint, 2))
						$hItem = DllStructGetData($tTVHTI, 'Item')
						If BitAND(DllStructGetData($tTVHTI, 'Flags'), $TVHT_ONITEM) Then
							_GUICtrlTreeView_SelectItem($hTreeView, $hItem)
							If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
								_GUICtrlTreeView_Delete($hTV, $hItem)
								$hItem = _GUICtrlTreeView_GetSelection($hTV)
							Else
								GUICtrlSendToDummy($Dummy2, $hItem)
							EndIf
							If $hItem <> $hSelect Then
								_TVSetPath($hTV, $hItem, $sRoot)
							EndIf
						EndIf
				EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Yashied Спасибо.
По поводу
Само контекстное меню создается AutoIt'овскими функциями, выводиться с помощью _GUICtrlMenu_TrackPopupMenu().
Это я знаю, я просто не мог правильно расположить это дело в скрипте, прмучился пол ночи.
GUIOnEventMode не подставить было и ешё куча проблем, получилось только так.
Я верю есть и попроше варианты.

Вот последний вариант от Yashied уже с контекстным меню от Меня. Кому надо!
Код:
#Include <GUIConstantsEx.au3>
#Include <GUIImageList.au3>
#Include <GUITreeView.au3>
#Include <TreeViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>
#Include <GuiMenu.au3> ;~> Include ~ Для контекстного меню и Меню.
Opt('MustDeclareVars', 1)
Global Enum $CONT_MENU_Open, $CONT_MENU_Save, $CONT_MENU_Info ;~> Enum ~ Пункты контекстного меню.

Global $hForm, $hTreeView, $hImageList, $hItem = 0, $hSelect = 0, $hInput, $Input, $Dummy1, $Dummy2
Global $X, $Y, $sPath, $sRoot = @HomeDrive

$hForm = GUICreate('MyGUI', 600, 600) ;~> Параметр '$hForm' Использует контекстное меню.
$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)
$Dummy1 = GUICtrlCreateDummy()
$Dummy2 = GUICtrlCreateDummy()

If _WinAPI_GetVersion() >= '6.0' Then
    _WinAPI_SetWindowTheme($hTreeView, 'Explorer')
EndIf

$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', 51)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
$sRoot = StringRegExpReplace(FileGetLongName($sRoot), '\\+\Z', '')
$sPath = StringRegExpReplace($sRoot, '^.*\\', '')
If StringInStr($sPath, ':') Then
    $sRoot &= '\'
    $sPath &= '\'
EndIf

If _WinAPI_PathIsDirectory($sRoot) Then
    $hItem = _GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, 0, 0)
    If FileClose(FileFindFirstFile($sRoot & '\*')) Then
        _GUICtrlTreeView_AddChild($hTreeView, $hItem, '', 2, 2)
    EndIf
EndIf

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") ;~> Отвечает за команды контекстного меню.
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

If $hItem Then
    _GUICtrlTreeView_Expand($hTreeView, $hItem)
EndIf

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Dummy1 ; Update
            GUISetCursor(1, 1)
            _TVUpdate($hTreeView, GUICtrlRead($Dummy1))
            GUISetCursor(2, 0)
        Case $Dummy2 ; Menu
            $hItem = GUICtrlRead($Dummy2)
            $sPath = _TVGetPath($hTreeView, $hItem, $sRoot)

            ConsoleWrite('-------------------------------' & @CR)
            ConsoleWrite('Handle: ' & $hItem & @CR)
            ConsoleWrite('Path:   ' & $sPath & @CR)
            If _WinAPI_PathIsDirectory($sPath) Then
                ConsoleWrite('Type:   ' & 'Directory' & @CR)
            Else
                ConsoleWrite('Type:   ' & 'File' & @CR)
            EndIf
            ConsoleWrite('X:      ' & MouseGetPos(0) & @CR)
            ConsoleWrite('Y:      ' & MouseGetPos(1) & @CR)
            ConsoleWrite('-------------------------------' & @CR)
			;... ...
			GUI_CONTEXTMENU() ;~> Контекстное меню.
    EndSwitch
WEnd

Func _TVGetPath($hTV, $hItem, $sRoot)

    Local $Path = StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $hItem), '([|]+)|(\\[|])', '\\')

    If Not $Path Then
        Return ''
    EndIf
    If Not StringInStr($Path, ':') Then
        Return StringRegExpReplace($sRoot, '(\\[^\\]*(\\|)+)\Z', '\\') & $Path
    EndIf
    Return $Path
EndFunc   ;==>_TVGetPath

Func _TVSetPath($hTV, $hItem, $sRoot)
    GUICtrlSetData($Input, _WinAPI_PathCompactPath($hInput, _TVGetPath($hTV, $hItem, $sRoot), 554))
    $hSelect = $hItem
EndFunc   ;==>_TVSetPath

Func _TVUpdate($hTV, $hItem)

    Local $hImageList = _SendMessage($hTV, $TVM_GETIMAGELIST)
    Local $Path = StringRegExpReplace(_TVGetPath($hTV, $hItem, $sRoot), '\\+\Z', '')
    Local $hIcon, $hSearch, $hSubitem
    Local $Index, $File

    _WinAPI_LockWindowUpdate($hTV)
    _GUICtrlTreeView_Delete($hTV, _GUICtrlTreeView_GetFirstChild($hTV, $hItem))

    $hSearch = FileFindFirstFile($Path & '\*')
    If $hSearch = -1 Then
        If Not @error Then
            If FileExists($Path) Then
;               If _WinAPI_PathIsDirectory($Path) Then
;                   ; Access denied
;               EndIf
            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
                $hSubItem = _GUICtrlTreeView_AddChild($hTV, $hItem, $File, 0, 0)
                If FileClose(FileFindFirstFile($Path & '\' & $File & '\*')) Then
                    _GUICtrlTreeView_AddChild($hTV, $hSubItem, '', 2, 2)
                EndIf
            EndIf
        WEnd
        FileClose($hSearch)
    EndIf

    $hSearch = FileFindFirstFile($Path & '\*')
    If $hSearch = -1 Then

    Else
        While 1
            $File = FileFindNextFile($hSearch)
            If @error Then
                ExitLoop
            EndIf
            If Not @extended Then
                $hIcon = _WinAPI_ShellExtractAssociatedIcon($Path & '\' & $File, 1)
                $Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
                _GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
                _WinAPI_DestroyIcon($hIcon)
            EndIf
        WEnd
        FileClose($hSearch)
    EndIf

    _GUICtrlTreeView_SetItemParam($hTV, $hItem, 0x80000000)
    _WinAPI_LockWindowUpdate(0)

    Return 1
EndFunc   ;==>_TVUpdate

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 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 $tTVHTI, $tPoint

    Switch $hTV
        Case $hTreeView
            Switch $ID
                Case $TVN_ITEMEXPANDEDW
                    If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
                        _GUICtrlTreeView_Delete($hTV, $hItem)
                        If BitAND($iState, $TVIS_SELECTED) Then
                            _TVSetPath($hTV, _GUICtrlTreeView_GetSelection($hTV), $sRoot)
                        EndIf
                    Else
                        If Not BitAND($iState, $TVIS_EXPANDED) Then
                            _GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 0)
                            _GUICtrlTreeView_SetImageIndex($hTV, $hItem, 0)
                        Else
                            _GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 1)
                            _GUICtrlTreeView_SetImageIndex($hTV, $hItem, 1)
                            If Not _GUICtrlTreeView_GetItemParam($hTV, $hItem) Then
                                GUICtrlSendToDummy($Dummy1, $hItem)
                            EndIf
                        EndIf
                    EndIf
                Case $TVN_SELCHANGEDW
                    If BitAND($iState, $TVIS_SELECTED) Then
                        If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
                            _GUICtrlTreeView_Delete($hTV, $hItem)
                            $hItem = _GUICtrlTreeView_GetSelection($hTV)
                        EndIf
                        If $hItem <> $hSelect Then
                            _TVSetPath($hTV, $hItem, $sRoot)
                        EndIf
                    EndIf
                Case $NM_RCLICK
                        $tPoint = _WinAPI_GetMousePos(1, $hTV)
                        $tTVHTI = _GUICtrlTreeView_HitTestEx($hTV, DllStructGetData($tPoint, 1), DllStructGetData($tPoint, 2))
                        $hItem = DllStructGetData($tTVHTI, 'Item')
                        If BitAND(DllStructGetData($tTVHTI, 'Flags'), $TVHT_ONITEM) Then
                            _GUICtrlTreeView_SelectItem($hTreeView, $hItem)
                            If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
                                _GUICtrlTreeView_Delete($hTV, $hItem)
                                $hItem = _GUICtrlTreeView_GetSelection($hTV)
                            Else
                                GUICtrlSendToDummy($Dummy2, $hItem)
                            EndIf
                            If $hItem <> $hSelect Then
                                _TVSetPath($hTV, $hItem, $sRoot)
                            EndIf
                        EndIf
                EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

; Функция .........................: GUI_CONTEXTMENU ~ Создание контекст меню для вложений.
Func GUI_CONTEXTMENU()
    Local $hC_Menu
    $hC_Menu = _GUICtrlMenu_CreatePopup ()
    _GUICtrlMenu_InsertMenuItem ($hC_Menu, 0, "Open", $CONT_MENU_Open)
    _GUICtrlMenu_InsertMenuItem ($hC_Menu, 1, "Save", $CONT_MENU_Save)
    _GUICtrlMenu_InsertMenuItem ($hC_Menu, 3, "", 0)
    _GUICtrlMenu_InsertMenuItem ($hC_Menu, 4, "Info", $CONT_MENU_Info)
;~     _GUICtrlMenu_TrackPopupMenu ($hC_Menu, $iw_Param)
	_GUICtrlMenu_TrackPopupMenu ($hC_Menu, $hForm) ;~> !.!.!
    _GUICtrlMenu_DestroyMenu ($hC_Menu)
    Return True
EndFunc   ;==>GUI_CONTEXTMENU()

; Функция .........................: WM_COMMAND ~ Параметры/Действия контекстного меню.
Func WM_COMMAND($h_Wnd, $i_Msg, $iw_Param, $il_Param)
	Switch ($iw_Param)
		Case $CONT_MENU_Open
			;......
            GUI_SEND_MESSAGE('Тест!', 'Был нажат пункт - Open'&@CR& $sPath, 0)
        Case $CONT_MENU_Save
			;......
            GUI_SEND_MESSAGE('Тест!', 'Был нажат пункт - Save'&@CR& $sPath, 0)
        Case $CONT_MENU_Info
			;......
            GUI_SEND_MESSAGE('Тест!', 'Был нажат пункт - Info'&@CR& $sPath, 0)
	EndSwitch
	Return True
EndFunc   ;==>WM_COMMAND

; Функция .........................: GUI_SEND_MESSAGE ~ Мессага.
Func GUI_SEND_MESSAGE($MESSAGE_TITLE, $MESSAGE_TEXT, $FLAGS)
	BlockInput(0)
    MsgBox($FLAGS, $MESSAGE_TITLE, $MESSAGE_TEXT&"     "&@CR)
EndFunc   ;==>MemoWrite
 

Yashied

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

Код:
; http://autoit-script.ru/index.php?topic=3725.0

#Include <GUIConstantsEx.au3>
#Include <GUIImageList.au3>
#Include <GUIMenu.au3>
#Include <GUITreeView.au3>
#Include <TreeViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $hForm, $hTreeView, $hImageList, $hItem = 0, $hSelect = 0, $hInput, $Input, $Dummy1, $Dummy2, $Menu[4]
Global $X, $Y, $sPath, $sRoot = @HomeDrive

$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)
$Dummy1 = GUICtrlCreateDummy()
$Dummy2 = GUICtrlCreateDummy()

$Menu[0] = GUICtrlCreateContextMenu($Dummy2)
$Menu[1] = GUICtrlCreateMenuItem('Open', $Menu[0])
$Menu[2] = GUICtrlCreateMenuItem('Save', $Menu[0])
GUICtrlCreateMenuItem('', $Menu[0])
$Menu[3] = GUICtrlCreateMenuItem('Info', $Menu[0])
$Menu[0] = GUICtrlGetHandle($Menu[0])

If _WinAPI_GetVersion() >= '6.0' Then
	_WinAPI_SetWindowTheme($hTreeView, 'Explorer')
EndIf

$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', 51)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)
$sRoot = StringRegExpReplace(FileGetLongName($sRoot), '\\+\Z', '')
$sPath = StringRegExpReplace($sRoot, '^.*\\', '')
If StringInStr($sPath, ':') Then
	$sRoot &= '\'
	$sPath &= '\'
EndIf

If _WinAPI_PathIsDirectory($sRoot) Then
	If Not _TVIsEmpty($sRoot) Then
		_GUICtrlTreeView_AddChild($hTreeView, _GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, 0, 0), '', 2, 2)
	Else
		Switch @error
			Case 0 ; OK
				_GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, 0, 0)
			Case 1 ; Access denied
				_GUICtrlTreeView_AddChild($hTreeView, 0, $sPath, 0, 0)
			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 $Dummy1 ; Update
			GUISetCursor(1, 1)
			_TVUpdate($hTreeView, GUICtrlRead($Dummy1))
			GUISetCursor(2, 0)
		Case $Dummy2 ; Menu
			_GUICtrlMenu_TrackPopupMenu($Menu[0], $hForm)

#cs

			$hItem = GUICtrlRead($Dummy2)
			$sPath = _TVGetPath($hTreeView, $hItem, $sRoot)

			ConsoleWrite('-------------------------------' & @CR)
			ConsoleWrite('Handle: ' & $hItem & @CR)
			ConsoleWrite('Path:   ' & $sPath & @CR)
			If _WinAPI_PathIsDirectory($sPath) Then
				ConsoleWrite('Type:   ' & 'Directory' & @CR)
			Else
				ConsoleWrite('Type:   ' & 'File' & @CR)
			EndIf
			ConsoleWrite('X:      ' & MouseGetPos(0) & @CR)
			ConsoleWrite('Y:      ' & MouseGetPos(1) & @CR)
			ConsoleWrite('-------------------------------' & @CR)

#ce

		Case $Menu[1] ; "Open"
			MsgBox(64, _GUICtrlTreeView_GetText($hTreeView, $hSelect), '"Open" item was chosen.', 0, $hForm)
		Case $Menu[2] ; "Save"
			MsgBox(64, _GUICtrlTreeView_GetText($hTreeView, $hSelect), '"Save" item was chosen.', 0, $hForm)
		Case $Menu[3] ; "Info"
			MsgBox(64, _GUICtrlTreeView_GetText($hTreeView, $hSelect), '"Info" item was chosen.', 0, $hForm)
	EndSwitch
WEnd

Func _TVGetPath($hTV, $hItem, $sRoot)

	Local $Path = StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $hItem), '([|]+)|(\\[|])', '\\')

	If Not $Path Then
		Return ''
	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 $hImageList = _SendMessage($hTV, $TVM_GETIMAGELIST)
	Local $Path = StringRegExpReplace(_TVGetPath($hTV, $hItem, $sRoot), '\\+\Z', '')
	Local $hIcon, $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
				; Access denied
			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
				If Not _TVIsEmpty($Path & '\' & $File) Then
					_GUICtrlTreeView_AddChild($hTV, _GUICtrlTreeView_AddChild($hTV, $hItem, $File, 0, 0), '', 2, 2)
				Else
					Switch @error
						Case 0 ; OK
							_GUICtrlTreeView_AddChild($hTV, $hItem, $File, 0, 0)
						Case 1 ; Access denied
							_GUICtrlTreeView_AddChild($hTV, $hItem, $File, 0, 0)
						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
					$hIcon = _WinAPI_ShellExtractAssociatedIcon($Path & '\' & $File, 1)
					$Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)
					_GUICtrlTreeView_AddChild($hTV, $hItem, $File, $Index, $Index)
					_WinAPI_DestroyIcon($hIcon)
				EndIf
			WEnd
			FileClose($hSearch)
		EndIf
	EndIf

	_GUICtrlTreeView_SetItemParam($hTV, $hItem, 0x7FFFFFFF)
	_WinAPI_LockWindowUpdate(0)

	Return 1
EndFunc   ;==>_TVUpdate

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 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 $tTVHTI, $tPoint

	Switch $hTV
		Case $hTreeView
			Switch $ID
				Case $TVN_ITEMEXPANDEDW
					If _WinAPI_PathIsDirectory(_TVGetPath($hTV, $hItem, $sRoot)) Then
						If Not BitAND($iState, $TVIS_EXPANDED) Then
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 0)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 0)
						Else
							_GUICtrlTreeView_SetSelectedImageIndex($hTV, $hItem, 1)
							_GUICtrlTreeView_SetImageIndex($hTV, $hItem, 1)
							If Not _GUICtrlTreeView_GetItemParam($hTV, $hItem) Then
								GUICtrlSendToDummy($Dummy1, $hItem)
							EndIf
						EndIf
					Else
						_GUICtrlTreeView_Delete($hTV, $hItem)
						If BitAND($iState, $TVIS_SELECTED) Then
							_TVSetPath($hTV, _GUICtrlTreeView_GetSelection($hTV), $sRoot)
						EndIf
					EndIf
				Case $TVN_SELCHANGEDW
					If BitAND($iState, $TVIS_SELECTED) Then
						If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
							_GUICtrlTreeView_Delete($hTV, $hItem)
							$hItem = _GUICtrlTreeView_GetSelection($hTV)
						EndIf
						If $hItem <> $hSelect Then
							_TVSetPath($hTV, $hItem, $sRoot)
						EndIf
					EndIf
				Case $NM_RCLICK
						$tPoint = _WinAPI_GetMousePos(1, $hTV)
						$tTVHTI = _GUICtrlTreeView_HitTestEx($hTV, DllStructGetData($tPoint, 1), DllStructGetData($tPoint, 2))
						$hItem = DllStructGetData($tTVHTI, 'Item')
						If BitAND(DllStructGetData($tTVHTI, 'Flags'), $TVHT_ONITEM) Then
							_GUICtrlTreeView_SelectItem($hTreeView, $hItem)
							If Not FileExists(_TVGetPath($hTV, $hItem, $sRoot)) Then
								_GUICtrlTreeView_Delete($hTV, $hItem)
								$hItem = _GUICtrlTreeView_GetSelection($hTV)
							Else
								GUICtrlSendToDummy($Dummy2, $hItem)
							EndIf
							If $hItem <> $hSelect Then
								_TVSetPath($hTV, $hItem, $sRoot)
							EndIf
						EndIf
				EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
 
Автор
D

dronet

Знающий
Сообщения
46
Репутация
8
Yashied - Как всегда на высоте. :ok:
Будем тоже старатса. :laugh:
 

Yashied

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

Код:
If True Then


на

Код:
If False Then


то будут отображаться только папки. + еще несколько изменений в коде.

:smile:
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Можно рассмотреть вариант с очень простой ф- иями : TreeView_UpDate_Ex и WM_NOTIFY
Особенности :
Использование системного Image List
Скорость создания элементов получилась высокая.
Код:
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <File.au3>
#include <GuiTreeView.au3>
;#include <ExpListView.au3>
;#cs
Global $Shell32 = DllOpen('shell32.dll')
Global Const $FOLDER_ICON_INDEX = _GUIImageList_GetFileIconIndex(@SystemDir, 0, 1)
;#ce
$hGui = GUICreate("3", 650, 900)
GUISetBkColor(0xC0C0B0)

$Input = GUICtrlCreateInput('', 220, 10, 100, 19)
$hImageList=_GUIImageList_GetSystemImageList()
$hTreeView = GUICtrlCreateTreeView(10, 40, 500, 810 ,-1 , $WS_EX_CLIENTEDGE)
_GUICtrlTreeView_SetNormalImageList(-1, $hImageList)

$begin=TimerInit()
$aDisk=DriveGetDrive("ALL")
For $i=1 To UBound($aDisk)-1
   $aDisk[$i]=StringUpper ( $aDisk[$i] )
   $hItem= _GUICtrlTreeView_Add($hTreeView, 0, $aDisk[$i],$FOLDER_ICON_INDEX,$FOLDER_ICON_INDEX)
   If  FileFindFirstFile($aDisk[$i] & '\*')<> -1 Then _GUICtrlTreeView_SetChildren($hTreeView,  $hItem)
Next
GUICtrlSetData($Input,TimerDiff($begin))

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

While 1
   $nMsg = GUIGetMsg()
   Switch $nMsg
	  Case $GUI_EVENT_CLOSE
		 Exit
  EndSwitch
WEnd

Func TreeView_UpDate_Ex($hTV,$hItem=-1,$sPattern="*.*")
   Local $Index
  ; If $hItem=0 Then Return
    If $hItem=0 Then Return -1; Исправлено
If Not IsHWnd($hTV) Then $hTV=GUICtrlGetHandle($hTV)
   If _GUICtrlTreeView_GetItemParam($hTV, $hItem) =True  Then Return -1
   $sPath=StringReplace(_GUICtrlTreeView_GetTree($hTV, $hItem) ,'|','\')
   If Not FileExists($sPath) Then Return SetError(1, 1, 0)
   $aFolderList = _FileListToArray($sPath, '*', 2)
   For $i = 1 To UBound($aFolderList) - 1
	  $hChildFolder=_GUICtrlTreeView_AddChild($hTV,$hItem,  $aFolderList[$i],$FOLDER_ICON_INDEX,$FOLDER_ICON_INDEX)
	  If FileFindFirstFile($sPath & "\" & $aFolderList[$i] & '\*')<> -1 Then _GUICtrlTreeView_SetChildren($hTV,  $hChildFolder)
   Next
   $aFileList = _FileListToArray($sPath, $sPattern, 1)
   For $i = 1 To UBound($aFileList) - 1
	  $Index = _GUIImageList_GetFileIconIndex($sPath & "\" & $aFileList[$i])
	  $sExt = StringRegExpReplace($aFileList[$i], '^.*\.', '.')
	  If $sExt = ".htm" Or $sExt = ".url"  Then $Index=_GUIImageList_GetFileIconIndex("C:\Program Files\Internet Explorer\IEXPLORE.exe")
	  _GUICtrlTreeView_AddChild($hTV, $hItem, $aFileList[$i], $Index, $Index)
   Next
   _GUICtrlTreeView_SetItemParam($hTV, $hItem, 0x7FFFFFFF)
   Return 1
EndFunc ;==> TreeView_UpDate_Ex

Func WM_NOTIFY($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 
			   $begin=TimerInit()
			   $hClickedItemTV=ScreenToClient($hWndTreeview)
			   If Not TreeView_UpDate_Ex($hTreeView, $hClickedItemTV) Then _GUICtrlTreeView_Delete($hTreeView, $hClickedItemTV)
			   GUICtrlSetData($Input,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

;=====================================================================================================================
;#cs
Func _GUIImageList_GetSystemImageList($bLargeIcons = False)
	Local $SHGFI_USEFILEATTRIBUTES = 0x10, $SHGFI_SYSICONINDEX = 0x4000, $SHGFI_SMALLICON = 0x1;, $SHGFI_LARGEICON = 0x0;,$FILE_ATTRIBUTE_NORMAL = 0x80
	Local $FileInfo = DllStructCreate("dword hIcon; int iIcon; DWORD dwAttributes; CHAR szDisplayName[255]; CHAR szTypeName[80];")
	Local $dwFlags = BitOR($SHGFI_USEFILEATTRIBUTES, $SHGFI_SYSICONINDEX)
	If Not ($bLargeIcons) Then $dwFlags = BitOR($dwFlags, $SHGFI_SMALLICON)
	Local $hIml = _WinAPI_SHGetFileInfo(".txt", $FILE_ATTRIBUTE_NORMAL, DllStructGetPtr($FileInfo), DllStructGetSize($FileInfo), $dwFlags)
	Return $hIml
 EndFunc   ;==>_GUIImageList_GetSystemImageList
 
 Func _WinAPI_SHGetFileInfo($pszPath, $dwFileAttributes, $psfi, $cbFileInfo, $uFlags)
	Local $return = DllCall($Shell32, "DWORD*", "SHGetFileInfo", "str", $pszPath, "DWORD", $dwFileAttributes, "ptr", $psfi, "UINT", $cbFileInfo, "UINT", $uFlags)
	If @error Then Return SetError(@error, 0, 0)
	Return $return[0]
 EndFunc   ;==>_WinAPI_SHGetFileInfo
 
 Func _GUIImageList_GetFileIconIndex($sFileSpec, $bLargeIcons = False, $bForceLoadFromDisk = False);modified
	Static $FileInfo = DllStructCreate("dword hIcon; int iIcon; DWORD dwAttributes; CHAR szDisplayName[255]; CHAR szTypeName[80];")
	Local $dwFlags = BitOR(0x4000, 0x1)
	If Not $bForceLoadFromDisk Then $dwFlags = BitOR($dwFlags, 0x10)
	DllCall($Shell32, "DWORD*", "SHGetFileInfo", "str", $sFileSpec, "DWORD", $FILE_ATTRIBUTE_NORMAL, "ptr", DllStructGetPtr($FileInfo), "UINT", DllStructGetSize($FileInfo), "UINT", $dwFlags)
	If @error Then Return SetError(1, 0, -1)
	Return DllStructGetData($FileInfo, "iIcon")
EndFunc   ;==>_GUIImageList_GetFileIconIndex
;#ce

Использовались ф-ии назначения иконок из неплохой библиотеки :
Explorer ListView UDF (от Beege)
При желании можно использовать эту библиотеку ,
закомментировав в скрипте использоанные 3 ф-ии.
и объявленные :
Код:
;#cs
Global $Shell32 = DllOpen('shell32.dll')
Global Const $FOLDER_ICON_INDEX = _GUIImageList_GetFileIconIndex(@SystemDir, 0, 1)
;#ce

Для этого надо в библиотеке : Explorer ListView.au3 в ф-ии : EXPLORER_WM_NOTIFY запретить использование сообщений от TreeView, добавив 1 строчку:
Код:
Func EXPLORER_WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
;............................
$iArrayIndex = _GetIndex($hWndFrom)
If $iArrayIndex =-1 Then Return; Добавленная строка
;..............................




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

И еще более упростилась сама ф-я :
Код:
Func TreeView_UpDate_Ex($hTV,$hItem,$sPattern="*.*")
   If $hItem=0 Then Return -1
   If Not IsHWnd($hTV) Then $hTV=GUICtrlGetHandle($hTV)
   If _GUICtrlTreeView_GetItemParam($hTV, $hItem) =True  Then Return -1
   $sPath=StringReplace(_GUICtrlTreeView_GetTree($hTV, $hItem) ,'|','\')
   If Not FileExists($sPath) Then Return SetError(1, 1, 0)
   Local $hSearch = FileFindFirstFile($sPath & '\*')
   Local $hFolder
   
   While 1
	  $sFile = FileFindNextFile($hSearch)
	  If @error Then ExitLoop
	  If StringInStr(FileGetAttrib($sPath & '\' & $sFile), 'D')  Then
		 $hFolder= _GUICtrlTreeView_InsertItem($hTV, $sFile,$hItem,$hFolder,$FOLDER_ICON_INDEX,$FOLDER_ICON_INDEX)
		 If FileFindFirstFile($sPath & '\' & $sFile & '\*')<> -1 Then _GUICtrlTreeView_SetChildren($hTV,  $hFolder)
	  Else
		 $iIndexIcon=_GUIImageList_GetFileIconIndex($sPath & "\" & $sFile)
		 $hChild= _GUICtrlTreeView_AddChild($hTV,$hItem,$sFile,$iIndexIcon,$iIndexIcon)
	  EndIf
   WEnd
   _GUICtrlTreeView_SetItemParam($hTV, $hItem, 0x7FFFFFFF)
   Return 1
EndFunc ;==> TreeView_UpDate_Ex
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Хорошее решение, но у системного списка есть ряд недостатков, например, он не содержит иконок с оверлеем. В частности, для .lnk файлов не будет отображаться "стрелочка". Кроме того, обработка по NM_CLICK не предусматривает развертывание ветки с помощью клавиатуры (стрелка вправо). При быстром переключении между папками, содержащими большое количество файлов, будут неприятные задержки и подвисания GUI, т.к. TreeView_UpDate_Ex() вызывается непосредственно из обработчика. Это больше раздражает даже не при развертывании ветки, а при простом выделении папки. И еще, в .url файлах может быть прописана собственная иконка, не обязательно "IEXPLORE.exe".
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
b]Yashied[/b] [?]
у системного списка есть ряд недостатков, например, он не содержит иконок с оверлеем. В частности, для .lnk файлов не будет отображаться "стрелочка"
И еще, в .url файлах может быть прописана собственная иконка, не обязательно "IEXPLORE.exe".
Действительно, это так. Однако его использование имеет одно преимущество : В ImageList Treeview не создается большого кол-ва одинаковых иконок ,
в отличие от варианта с занесением в лист Handle иконок. Отсюда и выигрыщ в скорости, наверное.
Кстати вопрос нахождения иконок - это отдельный вопрос, на который я так и не нашел корректного решения.

обработка по NM_CLICK не предусматривает развертывание ветки с помощью клавиатуры (стрелка вправо)
И этот есть недостаток.И тут же несомненное его достоинство :
Во время двойного клика при первом клике - создаются дочерние элементы , при втором - раскрывается ветка.Все происходит "за один присест" .Это наглядно видно если закомментировать строку:
Код:
If FileFindFirstFile($sPath & '\' & $sFile & '\*')<> -1 Then _GUICtrlTreeView_SetChildren($hTV,  $hFolder)
.

При быстром переключении между папками, содержащими большое количество файлов, будут неприятные задержки и подвисания GUI, т.к. TreeView_UpDate_Ex() вызывается непосредственно из обработчика. Это больше раздражает даже не при развертывании ветки, а при простом выделении папки.
Так вот в чем причина использования тобой элемента Dummy.
Хотя что-то я ничего не замечаю даже при раскрытии или выделении наиболее заполненной папки "WINDOWS". Можно взять на вооружение.
В то же время на ней сильно заметны операции создания-удаления временного элемента TreeView. Хотя это твое решение интересно и оригинально.

Все же как интересно и просто получается, если сравнить с вариантами из начала темы .
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
gregaz
В твоём примере есть небольшой баг. Если нажать в “пустом месте” то выделенный элемент удаляется.
Исправляется кажется заменой:
Код:
If TreeView_UpDate_Ex($hTreeView, $hClickedItemTV) Then _GUICtrlTreeView_Delete($hTreeView, $hClickedItemTV)

на
Код:
If $hClickedItemTV And Not TreeView_UpDate_Ex($hTreeView, $hClickedItemTV) Then _GUICtrlTreeView_Delete($hTreeView, $hClickedItemTV)
 

madmasles

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

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
CreatoR [?]
твоём примере есть небольшой баг. Если нажать в “пустом месте” то выделенный элемент удаляется.

В последней редакции уже ведь вроде исправлено :
В начале ф-ии просто замена Return на Return -1 :
Код:
If $hItem=0 Then Return -1
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
gregaz [?]
В последней редакции уже ведь вроде исправлено
Ты имеешь в виду в функций? желательно обновить и сам пример.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Продолжаем разговор... Вот мой окончательный вариант. Да, скорость конечно немного ниже, чем по методу gregaz'а, но я пошел по другому пути. Здесь все иконки отображаются так, как в Explorer'е (включая папки) + присутствуют "стрелочки" на иконках для линков (при этом само расширение файла не отображается) + присутствуют "замочки" на иконках для недоступных папок (только в Vista/7) + иконки для скрытых файлов и папок отображаются на 50% бледнее обычных + если файл или папка будут удалены или переименованы в процессе навигации, то эти элементы исчезнут из списка при их выделении и т.д. Да, чуть не забыл, все иконки теперь кэшируются и не плодятся в ImageList как кролики.

:smile:

Код:
; 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


P.S

В коде присутствуют несколько _WinAPI_* функций, которых нет в текущей версии библиотеки WinAPIEx.au3 (3.1), но будут, начиная с версии 3.2.
 

HukpoFuJl

AццkuЙ HukpoFuJl
Сообщения
98
Репутация
38
Отличную тему вы завели :smile: Своё дерево каталогов (и файлов) - штука крайне нужная :smile: Последний пример Yashied'a работает великолепно, осталось в него пользовательское контекстное меню ;)
Кстати интересно бы было реализовать контекстное меню, чтоб была строка меню с выпадающим подменю explorer'a... ну т.е. в контекстном меню что был пункт из которого выпадает стандартное контекстное меню файла/папки. Возможно такое реализовать?
 

Yashied

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

В AutoIt это будет проблематично, т.к. реализация через ООП.
 
Верх