#include <GUIConstantsEx.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <TreeViewConstants.au3>
#include <GuiTreeView.au3>
#include <Array.au3>
#include <SQLite.au3>
;#include <SQLite.dll.au3>
If $CmdLine[0] = 0 Then
Dim $s_FileDB = FileOpenDialog('Открыть список', @ScriptDir, 'База данных (*.db)', 3)
If @error Then Exit
Else
$s_FileDB = $CmdLine[1]
EndIf
;Dim $s_FileDB = @ScriptDir & '\test.db'
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", "\")
$hImage = _GUIImageList_Create(16, 16, 5, 1) ; Создаём список иконок
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', -4)
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', -5)
_GUIImageList_AddIcon($hImage, @SystemDir & '\shell32.dll', 0)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImage)
$E = ''
$i = 1
While 1
$i += 1
$sExt = RegEnumKey("HKCR", $i)
If @error Or StringLeft($sExt, 1) <> '.' Then ExitLoop
$ico1 = _FileDefaultIcon($sExt)
If Not @error Then
Switch UBound($ico1)
Case 2
If StringInStr(';.exe;.scr;.ico;.ani;.cur;', ';' & $sExt & ';') Then
ContinueLoop
Else
_GUIImageList_AddIcon($hImage, $ico1[1], 0)
If @error Then ContinueLoop
EndIf
Case 3
_GUIImageList_AddIcon($hImage, $ico1[1], $ico1[2])
If @error Then ContinueLoop
EndSwitch
$E &= '|' & $sExt
EndIf
WEnd
$E = StringTrimLeft($E, 1)
$aE = StringSplit($E, '|') ; Создаём массив расширений, позиция которых совпадает с позицией иконок
_SQLite_Startup()
$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