AutoIt: 3.
Версия: 1.0
Категория: Элементы GUI
Описание:
Указанный ниже код добавляет содержимое текстового файла в элемент интерфейса TreeView. Пример отличается от приведенных ранее тем, что в нем осуществляется загрузка объемных текстовых файлов.
К примеру, вы хотите отобразить на экране ранее сохраненную файловую структуру вашего ПК, а именно результаты выполнения команды из консоли DIR: cmd.exe /c chcp 1251 && cmd.exe /c && dir /B /S /A:-D *.* > YourFile.txt
Пример реализован по следующему алгоритму: при чтении текстового файла осуществляется его конвертирование в БД SQLite, затем динамически подгружаемые при открытии узла данные отображаются в TreeView. Обязательно оцените скорость подгрузки данных .
Код/Пример:
Автор(ы): JSman
Версия: 1.0
Категория: Элементы GUI
Описание:
Указанный ниже код добавляет содержимое текстового файла в элемент интерфейса TreeView. Пример отличается от приведенных ранее тем, что в нем осуществляется загрузка объемных текстовых файлов.
К примеру, вы хотите отобразить на экране ранее сохраненную файловую структуру вашего ПК, а именно результаты выполнения команды из консоли DIR: cmd.exe /c chcp 1251 && cmd.exe /c && dir /B /S /A:-D *.* > YourFile.txt
Пример реализован по следующему алгоритму: при чтении текстового файла осуществляется его конвертирование в БД SQLite, затем динамически подгружаемые при открытии узла данные отображаются в TreeView. Обязательно оцените скорость подгрузки данных .
Код/Пример:
Код:
#include <GUIConstantsEx.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <TreeViewConstants.au3>
#include <GuiTreeView.au3>
#include <SQLite.au3>
;#include <SQLite.dll.au3>
AutoItSetOption("MustDeclareVars", 1)
If $CmdLine[0] = 0 Then
Dim $s_FileDB = FileOpenDialog('Открыть список', @ScriptDir, 'База данных (*.db; *.txt)', 3)
If @error Then Exit
Else
$s_FileDB = $CmdLine[1]
EndIf
_SQLite_Startup()
if StringRegExp($s_FileDB, "\.(?i)txt$") Then PreLoad($s_FileDB)
Func PreLoad($FileDB)
Dim $Index=0
Global $CacheLength = 1
Global $Cache[300][2]
Dim $ParentIndex=0
Dim $k=0
$Cache[0][0]=0
$Cache[0][1]="<ROOT>"
Dim $file, $line
$file = FileOpen($FileDB,0)
Dim $t, $f, $lastpart
Dim $timer = TimerInit()
Dim $s_FileDB = $FileDB & ".db"
Dim $h_DB = _SQLite_Open($s_FileDB)
Dim $s_Text = 'BEGIN;DROP TABLE IF EXISTS TREE;CREATE TABLE TREE ([ID] INT, [NAME] Text, [PARENT_ID] INT, [FTYPE] INT);COMMIT;'
_SQLite_Exec($h_DB, $s_Text)
Dim $i=1
$s_Text = "BEGIN;"
Dim $tmp
While 1
If (Mod($i,32768)=0) Then
$s_Text &= 'COMMIT;'
_SQLite_Exec($h_DB, $s_Text)
$s_Text="BEGIN;"
EndIf
$line = FileReadLine($file)
if $line="" Then ExitLoop
If @error = -1 Then ExitLoop
$tmp = StringRegExpReplace($line, "\\[^\\]+$", "")
; $tmp = StringLeft($line, StringInStr($line, '\', 2, -1))
$lastpart = StringReplace($line, $tmp & "\", "")
If $tmp <> $line and $CacheLength>0 and $tmp=$Cache[$CacheLength][1] Then
$Index+=1
$s_Text &= 'INSERT INTO TREE VALUES (' & $Index & ', "' & $lastpart & '", ' & $ParentIndex & ', 0);'
ContinueLoop
EndIf
$f = StringSplit($line, "\")
$t = ""
For $k=1 to $f[0]
if ($k=$f[0]) Then
$Index+=1
$s_Text &= 'INSERT INTO TREE VALUES (' & $Index & ', "' & $f[$k] & '", ' & $ParentIndex & ', 0);'
ExitLoop
EndIf
If $k<>1 Then $t&="\"
$t&=$f[$k]
If $Cache[$k][1]=$t Then
$ParentIndex = $Cache[$k][0]
ContinueLoop
EndIf
if ($k=1) Then $ParentIndex=0
$Index+=1
$Cache[$k][1]=$t
$Cache[$k][0]=$Index
$CacheLength = $k
$s_Text &= 'INSERT INTO TREE VALUES (' & $Index & ', "' & $f[$k] & '", ' & $ParentIndex & ', 1);'
$ParentIndex = $Index
Next
WEnd
ConsoleWrite("Время на создание базы данных " & Round(TimerDiff($timer) / 1000, 2) & @LF)
FileClose($file)
$s_Text &= 'COMMIT;'
_SQLite_Exec($h_DB, $s_Text)
_SQLite_Close($h_DB)
$s_Text = ""
EndFunc
;--------------------------------------------------------------------------------------------
Global $hTreeView, $fExpanded = 0
Dim $TreeNodeCollection[1000]
Dim $FolderCollection[1000]
Dim $ExpandedCollection[1000]
Dim $CollectionLength = 0
Dim $Loaded[1000]
Dim $LoadedLength = 0
Dim $hGui = GUICreate("Explorer", 540, 560, -1, -1, $WS_OVERLAPPEDWINDOW)
Dim $CountElements = 0
$hTreeView = GUICtrlCreateTreeView(0, 0, 540, 560, BitOR($TVS_DISABLEDRAGDROP, $TVS_CHECKBOXES, $GUI_SS_DEFAULT_TREEVIEW, $TVS_SHOWSELALWAYS, $TVS_HASLINES), $WS_EX_CLIENTEDGE)
Opt("GUIDataSeparatorChar", "\")
Dim $hImage = _GUIImageList_Create(16, 16, 5, 1) ; Создаём список иконок
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', -4)
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', -5)
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', 0)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImage)
Dim $E = '', $i = 1, $sExt, $ico1, $aE, $h_DB, $iMsg, $L
While 1
$i += 1
$sExt = RegEnumKey("HKCR", $i)
If @error Or StringLeft($sExt, 1) <> '.' Then ExitLoop
$ico1 = _FileDefaultIcon($sExt)
If Not @error Then
Switch UBound($ico1)
Case 2
If StringInStr(';.exe;.scr;.ico;.ani;.cur;', ';' & $sExt & ';') Then
ContinueLoop
Else
_GUIImageList_AddIcon($hImage, $ico1[1], 0)
If @error Then ContinueLoop
EndIf
Case 3
_GUIImageList_AddIcon($hImage, $ico1[1], $ico1[2])
If @error Then ContinueLoop
EndSwitch
$E &= '|' & $sExt
EndIf
WEnd
$E = StringTrimLeft($E, 1)
$aE = StringSplit($E, '|') ; Создаём массив расширений, позиция которых совпадает с позицией иконок
$h_DB = _SQLite_Open($s_FileDB)
GUISetState()
GUIRegisterMsg($WM_NOTIFY, "WM_Notify_Events")
LoadTree(0, 1, True)
;ConsoleWrite("-----------------------" & @LF)
Dim $i1=0
While 1
$iMsg = GUIGetMsg()
Select
Case $iMsg = $GUI_EVENT_CLOSE
_Exit()
Case $fExpanded = 1
; node closed so reset all nodes to current states
$L = $CollectionLength
For $i1 = 1 To $L
$ExpandedCollection[$i1] = _GUICtrlTreeView_GetExpanded($hTreeView, $TreeNodeCollection[$i1])
Next
$fExpanded = 0
Case $fExpanded = 2
; node opened so check which changed
$L = $CollectionLength
For $i1 = 1 To $L
If _GUICtrlTreeView_GetExpanded($hTreeView, $TreeNodeCollection[$i1]) <> $ExpandedCollection[$i1] Then
Dim $DB_Index = GetDBIndexByTVHandle($TreeNodeCollection[$i1])
;ConsoleWrite($i1)
$ExpandedCollection[$i1] = True
;ConsoleWrite("Expanded!" & $DB_Index & " $i=" & $i1 & " $TreeNodeCollection[$i1]=" & $TreeNodeCollection[$i1] & " " & TVGetPathByHandle($TreeNodeCollection[$i1]) & @LF)
ReLoad($DB_Index)
ExitLoop
EndIf
Next
$fExpanded = 0
EndSelect
WEnd
Func _FileDefaultIcon($sExt)
If $sExt = '' Or StringInStr($sExt, ':') Then Return SetError(1)
Local $aCall = DllCall("shlwapi.dll", "int", "AssocQueryStringW", _
"dword", 0x00000040, _ ;$ASSOCF_VERIFY
"dword", 15, _ ;$ASSOCSTR_DEFAULTICON
"wstr", $sExt, _
"ptr", 0, _
"wstr", "", _
"dword*", 65536)
If @error Then Return SetError(1, 0, "")
If Not $aCall[0] Then
$sExt = StringReplace($aCall[5], '"', '')
$sExt = StringSplit($sExt, ',')
Opt('ExpandEnvStrings', 1)
$sExt[1] = $sExt[1]
Opt('ExpandEnvStrings', 0)
Return SetError(0, 0, $sExt)
ElseIf $aCall[0] = 0x80070002 Then
Return SetError(1, 0, "{unknown}")
ElseIf $aCall[0] = 0x80004005 Then
Return SetError(1, 0, "{fail}")
Else
Return SetError(2, $aCall[0], "")
EndIf
EndFunc ;==>_FileDefaultIcon
Func __ArraySearch(ByRef $avArray, $vValue, $iStart = 0, $iEnd = 0)
If $iEnd=0 Then $iEnd=Ubound($avArray)-1
Dim $i=0, $found=false
For $i=$iStart To $iEnd
If ($avArray[$i]=$vValue) Then
$found=true
;ConsoleWrite($I & @LF)
ExitLoop
EndIf
Next
If not $Found Then
SetError(1)
Return -1
EndIf
Return $i
EndFunc
Func DBGetIndexByName($name, $parent)
Dim $hQuery, $aRow
_SQLite_Query(-1, "SELECT * FROM TREE WHERE PARENT_ID='" & $parent & "' AND NAME='" & StringReplace($name, "'", "''") & "';", $hQuery)
If _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK Then Return $aRow[0]
Return -1
EndFunc ;==>DBGetIndexByName
Func DBGetIndexPath($path)
If $path = "" Then Return 0
Dim $p = 0
Dim $parts = StringSplit($path, "\", 1)
For $i = 1 To $parts[0]
$p = DBGetIndexByName($parts[$i], $p)
Next
Return $p
EndFunc ;==>DBGetIndexPath
Func DBGetFiles($parent)
Dim $Result[1000], $ar_index = 0, $CurrentLength = 1000
Dim $hQuery, $aRow
_SQLite_Query(-1, "SELECT * FROM TREE WHERE PARENT_ID='" & $parent & "' AND FTYPE='0';", $hQuery)
While _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK
$ar_index += 1
if $ar_index >= $CurrentLength Then
$CurrentLength += 1000
ReDim $Result[$CurrentLength]
EndIf
$Result[$ar_index] = $aRow[1]
WEnd
$Result[0] = $ar_index
;Redim $Result[$ar_index+1]
Return $Result
EndFunc ;==>DBGetFiles
Func DBGetFolders($parent)
Dim $Result[1000], $ar_index = 0, $CurrentLength = 1000
Dim $hQuery, $aRow
_SQLite_Query(-1, "SELECT * FROM TREE WHERE PARENT_ID='" & $parent & "' AND FTYPE='1';", $hQuery)
While _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK
$ar_index += 1
if $ar_index >= $CurrentLength Then
$CurrentLength += 1000
ReDim $Result[$CurrentLength]
EndIf
$Result[$ar_index] = $aRow[1]
WEnd
$Result[0] = $ar_index
;Redim $Result[$ar_index+1]
Return $Result
EndFunc ;==>DBGetFolders
Func DBGetFoldersIndexes($parent)
Dim $Result[1000], $ar_index = 0, $CurrentLength = 1000
Dim $hQuery, $aRow
_SQLite_Query(-1, "SELECT * FROM TREE WHERE PARENT_ID='" & $parent & "' AND FTYPE='1';", $hQuery)
While _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK
$ar_index += 1
if $ar_index >= $CurrentLength Then
$CurrentLength += 1000
;ReDim $Result[$CurrentLength]
EndIf
$Result[$ar_index] = $aRow[0]
WEnd
$Result[0] = $ar_index
;Redim $Result[$ar_index+1]
Return $Result
EndFunc ;==>DBGetFoldersIndexes
Func DBGetByIndex($index)
Dim $hQuery, $aRow
_SQLite_Query(-1, "SELECT * FROM TREE WHERE ID='" & $index & "' ;", $hQuery)
If _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK Then Return $aRow
Return -1
EndFunc ;==>DBGetByIndex
Func DBGetParent($index)
Dim $hQuery, $aRow
$aRow = DBGetByIndex($index)
Return DBGetByIndex($aRow[2])
EndFunc ;==>DBGetParent
Func DBGetPathByIndex($index)
Dim $hQuery, $part = DBGetByIndex($index), $_index = -2, $path = "", $ar
If $part[3] = 0 Then
$path = $part[1]
EndIf
While 1
If $index = 0 Then ExitLoop
$ar = DBGetByIndex($index)
$index = $ar[2]
$path = $ar[1] & "\" & $path
WEnd
Return $path
EndFunc ;==>DBGetPathByIndex
Func TVGetHandleByPath($path)
Opt("GUIDataSeparatorChar", "\")
Return _GUICtrlTreeView_FindItemEx($hTreeView, $path, 0)
EndFunc ;==>TVGetHandleByPath
Func TVGetPathByHandle($handle)
Return _GUICtrlTreeView_GetTree($hTreeView, $handle)
EndFunc ;==>TVGetPathByHandle
Func GetDBIndexByTVHandle($index)
Dim $Result = __ArraySearch($TreeNodeCollection, $index, 0, $CollectionLength)
If $CollectionLength = 0 Or $Result = -1 Then Return 0
Return $FolderCollection[$Result]
EndFunc ;==>GetDBIndexByTVHandle
Func GetTVHandleByDBIndex($DBIndex)
Dim $Result = __ArraySearch($FolderCollection, $DBIndex, 0, $CollectionLength)
;ConsoleWrite("GetTVHandleByDBIndex " & GetDBIndexByTVHandle($Result) & " " & $DBIndex & @LF)
If $Result <> -1 Then Return $TreeNodeCollection[$Result]
Return -1
EndFunc ;==>GetTVHandleByDBIndex
Func LoadDataToTV($ParentNodeHandle = 0) ;ToDo
Dim $DB_Index = GetDBIndexByTVHandle($ParentNodeHandle)
Dim $_Folders, $_Files, $Result[1000], $i = 0, $L
Dim $ar = DBGetFoldersIndexes($DB_Index)
$_Folders = DBGetFolders($DB_Index)
Dim $Flag = False
If $ar[0] > 1 Then
If GetTVHandleByDBIndex($ar[1]) > -1 Then $Flag = True
EndIf
$L = $_Folders[0]
If $L >= 1000 Then ReDim $Result[$L]
For $i = 1 To $L
If not $Flag Then
$Result[$i] = AddFolder($_Folders[$i], $ParentNodeHandle, $ar[$i])
else
$Result[$i] = GetTVHandleByDBIndex($ar[$i])
endIf
Next
$Result[0] = $L
$LoadedLength += 1
$Loaded[$LoadedLength] = $ParentNodeHandle
$Loaded[0] = $LoadedLength
If $Flag Then
ConsoleWrite(Round(TimerDiff($timer) / 1000, 2) & @LF)
Return $Result
EndIf
$_Files = DBGetFiles($DB_Index)
$L = $_Files[0]
For $i = 1 To $L
AddFile($_Files[$i], $ParentNodeHandle)
Next
Return $Result
EndFunc ;==>LoadDataToTV
Func LoadTree($ParentNodeHandle, $lvl = 1, $force = False)
If $lvl = -1 Then Return
If Not $force Then
If __ArraySearch($Loaded, $ParentNodeHandle, 1, $LoadedLength) <> -1 Then
Return
EndIf
EndIf
_GUICtrlTreeView_Delete($hTreeView, _GUICtrlTreeView_GetFirstChild($hTreeView, $ParentNodeHandle))
Dim $Dirs = LoadDataToTV($ParentNodeHandle)
If $Dirs[0] = 0 Then Return
For $i = 1 To $Dirs[0]
LoadTree($Dirs[$i], $lvl - 1)
Next
EndFunc ;==>LoadTree
Func AddFolder($name, $ParentNodeHandle = 0, $DB_Index = -1)
Local $Result = _GUICtrlTreeView_InsertItem($hTreeView, $name, $ParentNodeHandle)
;Local $Result = _GUICtrlTreeView_AddChild($hTreeView, $ParentNodeHandle, $name)
$CountElements += 1
$CollectionLength += 1
if $CollectionLength >= Ubound($TreeNodeCollection) Then
ReDim $TreeNodeCollection[Ubound($TreeNodeCollection) + 1000]
ReDim $ExpandedCollection[Ubound($TreeNodeCollection) + 1000]
ReDim $FolderCollection[Ubound($TreeNodeCollection) + 1000]
EndIf
$TreeNodeCollection[$CollectionLength] = $Result
$ExpandedCollection[$CollectionLength] = False
$FolderCollection[$CollectionLength] = $DB_Index
;ConsoleWrite ($DB_Index & @LF)
AddFile("..", $Result)
Return $Result
EndFunc ;==>AddFolder
Func AddFile($name, $parent = 0)
Dim $tmp1 = StringRegExpReplace($name, '.*(\.\S+)', '\1') ; ищем расширение
Dim $ind = __ArraySearch($aE, $tmp1) + 2 ; ищем расширение в масиве, чтобы определить индекс
If @error Then $ind = 2 ; если нет расширения
$CountElements += 1
_GUICtrlTreeView_InsertItem($hTreeView, $name, $parent, $ind, $ind, $ind)
;_GUICtrlTreeView_AddChild($hTreeView, $parent, $name, $ind, $ind)
EndFunc ;==>AddFile
Func ReLoad($DB_Index)
Dim $timer = TimerInit()
$CountElements = 0
LoadTree(GetTVHandleByDBIndex($DB_Index), 0)
; Или так
;Dim $ar = DBGetFoldersIndexes($DB_Index)
;Dim $L = $ar[0]
;For $j = 1 To $L
; LoadTree(GetTVHandleByDBIndex($ar[$j]), 0)
; Next
ConsoleWrite("Time " & Round(TimerDiff($timer) / 1000, 2) & " Elements added " & $CountElements & @LF)
EndFunc ;==>ReLoad
Func WM_Notify_Events($hWndGUI, $iMsgID, $wParam, $lParam)
#forceref $hWndGUI, $iMsgID
Local $tagNMHDR = DllStructCreate("int;int;int;int", $lParam)
If @error Then Return
Local $iEvent = DllStructGetData($tagNMHDR, 3)
Select
Case $wParam = $hTreeView
Switch $iEvent
Case $TVN_ITEMEXPANDEDW, $TVN_ITEMEXPANDEDA
$fExpanded = DllStructGetData($tagNMHDR, 4) ; 1 = node closed, 2 = node expanded
EndSwitch
EndSelect
$tagNMHDR = 0
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_Notify_Events
Func _Exit()
_SQLite_Close($h_DB)
_SQLite_Shutdown()
Exit
EndFunc ;==>_Exit
Автор(ы): JSman