<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK v2: TreeView как альтернатива DirSelect]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=18129</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=18129&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK v2: TreeView как альтернатива DirSelect».]]></description>
		<lastBuildDate>Sat, 09 Aug 2025 06:03:53 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162627#p162627</link>
			<description><![CDATA[<p>Нашел. Например - добавить в строки такое:<br /></p><div class="codebox"><pre><code>...
DirID := This.TreeView.Add(DirName, , &quot;Icon1&quot;)
...
DirID := This.TreeView.Add(DirName, HigherDirPathID, &quot;Icon2&quot;)
...</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (-=Sema=-)]]></author>
			<pubDate>Sat, 09 Aug 2025 06:03:53 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162627#p162627</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162626#p162626</link>
			<description><![CDATA[<p>Добавил:<br /></p><div class="codebox"><pre><code>;==== 
ImageListID := IL_Create(11)
IL_Add(ImageListID, &quot;shell32.dll&quot; ,   4) ; 1 [Yellow Folder]
IL_Add(ImageListID, &quot;imageres.dll&quot;,  10) ; 2 [Green Folder]
IL_Add(ImageListID, &quot;imageres.dll&quot;,   9) ; 3 [Grey Folder]
IL_Add(ImageListID, &quot;imageres.dll&quot;, 174) ; 4 [Keyboard]
IL_Add(ImageListID, &quot;shell32.dll&quot; , 174) ; 5 [Клавиатурка]
IL_Add(ImageListID, &quot;shell32.dll&quot; ,  22) ; 6 [Grafic]
IL_Add(ImageListID, &quot;comres.dll&quot;  ,  11) ; 7 Red [X]
IL_Add(ImageListID, &quot;dsuiext.dll&quot; ,  36) ; 8 [Set]
; IL_Add(ImageListID, &quot;wmploc.dll&quot;  ,  18) ; 8 [Set]
IL_Add(ImageListID, &quot;imageres.dll&quot;, 228) ; 9 [Portfel]
IL_Add(ImageListID, &quot;wmploc.dll&quot;  ,  71) ; 10 [Film Hlop]
IL_Add(ImageListID, &quot;wmploc.dll&quot;  ,  18) ; 11 [Set]
; IL_Add(ImageListID, &quot;imageres.dll&quot;,   6) ; 9 [Yellow Tone Folder]
; IL_Add(ImageListID, &quot;imageres.dll&quot;, 180) ; 9 [Green Tone Folder]
;==== </code></pre></div><p>И поменял<br /></p><div class="codebox"><pre><code>Settings[&quot;TreeViewOptions&quot;] := &quot;R15 W250 X&quot; Gui1.MarginX</code></pre></div><p>На<br /></p><div class="codebox"><pre><code>Settings[&quot;TreeViewOptions&quot;] := &quot;ImageList&quot; ImageListID &quot; R15 W250 X&quot; Gui1.MarginX</code></pre></div><p>Иконки благополучно добавились. Отобразились - Icon1 (так красивей).<br />Пока не понял как сменить иконку. И если нужны разные (напр. для Root и Sub) - новый массив готовить?</p>]]></description>
			<author><![CDATA[null@example.com (-=Sema=-)]]></author>
			<pubDate>Sat, 09 Aug 2025 04:56:32 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162626#p162626</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160532#p160532</link>
			<description><![CDATA[<p>Да, теперь всё вроде в порядке.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sun, 10 Mar 2024 13:23:43 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160532#p160532</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160531#p160531</link>
			<description><![CDATA[<p><strong>teadrinker</strong><br />Подредактировал свою версию с учётом этой проблемы. У меня это практически не ощущается, по этому полноценно протестировать я не могу.<br />Вот новая версия класса:<br /></p><div class="codebox"><pre><code>#Requires AutoHotkey v2

Gui1 := Gui()
Gui1.OnEvent(&#039;Close&#039;, (*) =&gt; ExitApp())
DefaultDir := &quot;C:\Program Files&quot;
Text1 := Gui1.Add(&quot;Text&quot;, &quot;&quot;, &quot;DefaultDir:&quot;)
Edit1 := Gui1.Add(&quot;Edit&quot;, &quot;W250 X&quot; Gui1.MarginY &quot; XM&quot;, DefaultDir)
Button1 := Gui1.Add(&quot;Button&quot;, &quot;X&quot; Gui1.MarginY &quot; XM&quot;, &quot;Change&quot;)
Button1.OnEvent(&#039;Click&#039;, ChangeDefaultDir)
Text2 := Gui1.Add(&quot;Text&quot;, &quot;X&quot; Gui1.MarginY &quot; XM&quot;, &quot;Selected Item:&quot;)
Edit2 := Gui1.Add(&quot;Edit&quot;, &quot;W250 X&quot; Gui1.MarginY &quot; XM&quot;)

Settings := Map()
Settings[&quot;TreeViewOptions&quot;] := &quot;R15 W250 X&quot; Gui1.MarginX
TreeView1 := TreeViewDirSelect(Gui1, DefaultDir, Settings)
TreeView1.TreeView.OnEvent(&#039;ItemSelect&#039;, (GuiCtrlObj, Item) =&gt; ItemSelect(GuiCtrlObj, Item))
Gui1.Show()

ItemSelect(GuiCtrlObj, Item) {
	If (TreeView1.IDToPath.Has(Item))
		Edit2.Text := TreeView1.IDToPath[Item]
}

ChangeDefaultDir(Button, Info) {
	Gui1.Submit(0)
	DefaultDir := Edit1.Text
	TreeView1.TreeViewOperations(&quot;TreeViewDirSelectRecreate&quot;, Gui1, DefaultDir)
}


Class TreeViewDirSelect {
	/*
	By Bulef
	Версия 0.02
	---------------------------------------
	Тестовые настройки:
Gui1 := Gui()
TreeView1 := TreeViewDirSelect(Gui1, &quot;C:\Program Files&quot;)
Gui1.Show()
	---------------------------------------
	В первой опции (Gui) необходимо дать ссылку на ваш Gui, чтобы разместить TreeView в нём. Эта настройка обязательная.
	Вторая опция (DefaultDir) позволяет выбрать директорию по умолчанию, из которой будет происходить открытие папок. Вы можете указать эту настройку пустой (&quot;&quot;), чтобы отобразить ваши диски как изначальную директорию.
	Третья опция (Settings) позволяет внести дополнительные настройки при создании TreeView. Для этого создайте карту:
Settings := Map()
	И добавьте нужную опцию.
Settings[&quot;TreeViewOptions&quot;] := &quot;R15&quot;
	Позволит добавить опции AHK Gui при создани TreeView (Искать в руководстве AHK по Gui Object).
Settings[&quot;ShowHiddenFolders&quot;] := True
	Позволит показать скрытые папки. Принимает значение либо True, либо False.
	После чего добавьте опцию Settings при создании класса:
TreeView1 := TreeViewDirSelect(Gui1, &quot;C:\Program Files&quot;, Settings)
	---------------------------------------
	Элемент TreeView будет находиться в собственности &quot;TreeView&quot; родительского объекта (&quot;TreeView1&quot;), то есть в &quot;TreeView1.TreeView&quot; как в примере.
	---------------------------------------
	Также возможно пересоздать TreeView используя внутреннюю функцию &quot;TreeViewOperations&quot;.
	Для этого вызовите её из родительского объекта и добавьте первой опцию &quot;TreeViewDirSelectRecreate&quot;, вставив остальные опции после неё:
TreeView1.TreeViewOperations(&quot;TreeViewDirSelectRecreate&quot;, Gui1, &quot;C:\Program Files&quot;)
	Также существует такая опция:
TreeView1.TreeViewOperations(&quot;TreeViewDirSelectCreate&quot;, Gui1, &quot;C:\Program Files&quot;)
	Она создаст TreeView заново. Если не знаете точно, что это вам требуется, не используйте её.
	---------------------------------------
	Для того, чтобы получить, к примеру путь к выбранной в TreeView папке, необходимо получить ID элемента и найти его в карте TreeView1.IDToPath.
	Для этого вызываем функцию GetSelection в TreeView.
ItemID := TreeView1.TreeView.GetSelection()
	После чего ищем её в TreeView1.IDToPath
Path := TreeView1.IDToPath[ItemID]
	Также возможно найти ItemID имея путь в TreeView1.PathToID, если он уже отрисован.
ItemID := TreeView1.PathToID[Path]
	Остальные возможные варианты взаимодействия с TreeView ищите в руководстве AHK по TreeView.
	*/
	
	__New(Gui, DefaultDir := &quot;&quot;, Settings := &quot;&quot;) {
		This.TreeViewOperations(&quot;TreeViewDirSelectCreate&quot;, Gui, DefaultDir, Settings)
	}
	
	TreeViewOperations(TreeViewDirSelectOption, Gui, DefaultDir := &quot;&quot;, Settings := &quot;&quot;) {
		If (TreeViewDirSelectOption = &quot;TreeViewDirSelectCreate&quot;) {
			If (IsObject(Settings)) {
				If (Settings.Has(&quot;TreeViewOptions&quot;))
					This.TreeViewOptions := Settings[&quot;TreeViewOptions&quot;]
				Else
					This.TreeViewOptions := &quot;&quot;
				If (Settings.Has(&quot;ShowHiddenFolders&quot;))
					This.ShowHiddenFolders := Settings[&quot;ShowHiddenFolders&quot;]
				Else
					This.ShowHiddenFolders := False
			}
			Else
			If (!IsObject(Settings)) {
				This.TreeViewOptions := &quot;&quot;
				This.ShowHiddenFolders := False
			}
		}
		Else
		If (TreeViewDirSelectOption = &quot;TreeViewDirSelectRecreate&quot;) {
			If (IsObject(Settings)) {
				If (Settings.Has(&quot;TreeViewOptions&quot;))
					This.TreeViewOptions := Settings[&quot;TreeViewOptions&quot;]
				If (Settings.Has(&quot;ShowHiddenFolders&quot;))
					This.ShowHiddenFolders := Settings[&quot;ShowHiddenFolders&quot;]
			}
		}
		
		If (TreeViewDirSelectOption = &quot;TreeViewDirSelectCreate&quot;) {
			This.TreeView := Gui.Add(&quot;TreeView&quot;, This.TreeViewOptions)
			This.TreeView.OnEvent(&quot;ItemExpand&quot;, (GuiCtrlObj, Item, Expanded) =&gt; This.TreeViewItemExpand(GuiCtrlObj, Item, Expanded))
		}
		Else
		If (TreeViewDirSelectOption = &quot;TreeViewDirSelectRecreate&quot;) {
			This.TreeView.Opt(This.TreeViewOptions)
			This.TreeView.Delete()
		}
		
		This.DefaultDir := DefaultDir
		This.DrivesList := DriveGetList(&quot;FIXED&quot;)
		
		This.PathToID := Map()
		This.IDToPath := Map()
		This.IDToDefaultDir := Map()
		
		
		This.PreLoadLevels(This.DefaultDir, This.DefaultDir, 2)
		
		This.TreeView.Redraw()
	}
	
	PreLoadLevels(Path, DefaultDir, Level) {
		PathArray := []
		If (Path = &quot;&quot; AND DefaultDir = &quot;&quot;) {
			Loop Parse This.DrivesList {
				DriveName := A_LoopField &quot;:&quot;
				PathArray.Push(DriveName)
				If (!This.PathToID.Has(DriveName)) {
					DriveFullName := DriveGetLabel(DriveName) &quot; (&quot; DriveName &quot;)&quot;
					DirID := This.TreeView.Add(DriveFullName)
					This.PathToID[DriveName] := DirID
					This.IDToPath[DirID] := DriveName
					This.IDToDefaultDir[DirID] := &quot;&quot;
				}
			}
		}
		Else
			PathArray.Push(Path)
		
		If (IsInteger(Level) AND Level &gt;= 1 OR InStr(Level, &quot;=&quot;, , 1, ) = 1 AND SubStr(Level, 2, ) &gt;= 1) {
			For PathID, Path In PathArray {
				Path1 := Path
				If (IsInteger(Level) AND Level &gt;= 1 OR Level = &quot;=1&quot;)
					This.AddItem(Path1, DefaultDir)
				
				If (IsInteger(Level) AND Level &gt;= 2 OR InStr(Level, &quot;=&quot;, , 1, ) = 1 AND SubStr(Level, 2, ) &gt;= 2) {
					Loop Files Path1 &quot;\*&quot;, &quot;D&quot; {
						Path2 := A_LoopFileFullPath
						If (IsInteger(Level) AND Level &gt;= 2 OR Level = &quot;=2&quot;)
							This.AddItem(Path2, DefaultDir)
						
						If (IsInteger(Level) AND Level &gt;= 3 OR InStr(Level, &quot;=&quot;, , 1, ) = 1 AND SubStr(Level, 2, ) &gt;= 3) {
							Loop Files Path2 &quot;\*&quot;, &quot;D&quot; {
								Path3 := A_LoopFileFullPath
								If (IsInteger(Level) AND Level &gt;= 3 OR Level = &quot;=3&quot;)
									This.AddItem(Path3, DefaultDir)
							}
						}
					}
				}
			}
		}
	}
	
	AddItem(Path, DefaultDir) {
		Loop Files Path &quot;\*&quot;, &quot;D&quot; {
			If (!This.ShowHiddenFolders AND InStr(A_LoopFileAttrib, &quot;H&quot;, 0))
				Continue
			HigherDirPath := &quot;&quot;
			FullDirPath := A_LoopFileFullPath
			TrimmedPath := FullDirPath
			If (DefaultDir != &quot;&quot; AND InStr(FullDirPath, DefaultDir, 1, 1, ) = 1)
				TrimmedPath := SubStr(FullDirPath, StrLen(DefaultDir &quot;\&quot;)+1, )
			Loop Parse TrimmedPath, &quot;\&quot;, &quot;&quot; {
				DirName := A_LoopField
				If (HigherDirPath = &quot;&quot;)
					DirPath := DirName
				Else
				If (HigherDirPath != &quot;&quot;)
					DirPath := HigherDirPath &quot;\&quot; DirName
				
				If (!This.PathToID.Has(DirPath)) {
					If (HigherDirPath = &quot;&quot;)
						DirID := This.TreeView.Add(DirName)
					Else
					If (HigherDirPath != &quot;&quot;) {
						HigherDirPathID := This.PathToID[HigherDirPath]
						DirID := This.TreeView.Add(DirName, HigherDirPathID)
					}
					This.PathToID[DirPath] := DirID
					This.IDToPath[DirID] := FullDirPath
					This.IDToDefaultDir[DirID] := DefaultDir
					HigherDirPath := DirPath
				}
				Else
				If (This.PathToID.Has(DirPath))
					HigherDirPath := DirPath
			}
		}
	}
	
	TreeViewItemExpand(GuiCtrlObj, Item, Expanded) {
		If (!Expanded)
			Return
		Path := This.IDToPath[Item]
		DefaultDir := This.IDToDefaultDir[Item]
		This.PreLoadLevels(Path, DefaultDir, &quot;=3&quot;)
	}
}</code></pre></div><p>Различие между нашими вариантами только в том, что в моём можно изменить директорию по умолчанию, из которой будут открываться папки. В остальном можно использовать любой из вариантов.</p><br /><p>Обновлено:<br />Возникала ошибка если очень быстро обновлять директорию по умолчанию. Я это исправил. Возможно буду периодически ещё вносить корректировки.</p>]]></description>
			<author><![CDATA[null@example.com (Bulef)]]></author>
			<pubDate>Sun, 10 Mar 2024 11:40:51 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160531#p160531</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160529#p160529</link>
			<description><![CDATA[<p>В целом всё ок, но есть небольшой недостаток. У меня на компьютере с HDD после раскрытия узлов не всегда успевают прогружаться раскрывающиеся вложенные узлы. По идее нужно изначально загрузить несколько уровней сразу, а при раскрытии загружать уже более глубокие уровни. Как-то так:<br /></p><div class="codebox"><pre><code>#Requires AutoHotkey v2

paths := Map()
wnd := Gui(&#039;Resize&#039;)
wnd.OnEvent(&#039;Close&#039;, (*) =&gt; ExitApp())
wnd.OnEvent(&#039;Size&#039;, (g, mm, w, h) =&gt; (
    selectedPath.Move(,, w - g.MarginX * 2),
    tree.Move(,, w - g.MarginX * 2, h - g.MarginY * 3 - 20)
))
selectedPath := wnd.AddEdit(&#039;w400 h20&#039;)
tree := wnd.AddTreeView(&#039;wp h300&#039;)
tree.OnEvent(&#039;ItemExpand&#039;, OnExpand)
tree.OnEvent(&#039;ItemSelect&#039;, (ctrl, item) =&gt; selectedPath.Value := RegExReplace(paths[item], &#039;\\$&#039;))
root := tree.Add(&#039;My Computer&#039;,, &#039;Expand&#039;)
paths[root] := &#039;My Computer&#039;

; добавляем сначала только три уровня
loop parse DriveGetList(&#039;FIXED&#039;) {
    node := tree.Add(drive := A_LoopField . &#039;:&#039;, root)
    paths[node] := drive
    loop files drive . &#039;\*&#039;, &#039;D&#039; {
        childNode := tree.Add(A_LoopFileName, node)
        paths[childNode] := A_LoopFilePath
        loop files A_LoopFilePath . &#039;\*&#039;, &#039;D&#039; {
            paths[tree.Add(A_LoopFileName, childNode)] := A_LoopFilePath
        }
    }
}
wnd.Show()

; остальные уровни добавляем при раскрытии узлов дерева
OnExpand(tree, item, expanded) {
    if !expanded || paths[item] ~= &#039;\\$&#039; {
        return
    }
    ; отмечаем узел, с которым будем работать, добавляя слеш в конец пути
    ; чтобы не добавлять дочерние узлы повторно
    paths[item] .= &#039;\&#039;
    CreateSubTree(tree.GetChild(item), 0)

    CreateSubTree(item, level) {
        level++
        Loop {
            if level &lt; 3 &amp;&amp; next := tree.GetChild(item) {
                CreateSubTree(next, level)
            } else {
                loop files paths[item] . &#039;\*&#039;, &#039;D&#039; {
                    paths[tree.Add(A_LoopFileName, item)] := A_LoopFilePath
                }
            }
        } until !item := tree.GetNext(item)
    }
}</code></pre></div><p>Особо не тестировал, может, тут не всё идеально.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 09 Mar 2024 17:51:18 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160529#p160529</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160528#p160528</link>
			<description><![CDATA[<p>Вот класс:<br /></p><div class="codebox"><pre><code>#Requires AutoHotkey v2.0

Gui1 := Gui()
Settings := Map()
Settings[&quot;TreeViewOptions&quot;] := &quot;r15&quot;
TreeView1 := TreeViewDirSelect(Gui1, &quot;C:\Program Files&quot;, Settings)
Gui1.Show()
Loop {
	Sleep 5000
	ItemID := TreeView1.TreeView.GetSelection()
	Path := TreeView1.IDToPath[ItemID]
	MsgBox Path
}


Class TreeViewDirSelect {
	/*
	By Bulef
	Версия 0.01
	---------------------------------------
	Тестовые настройки:
Gui1 := Gui()
TreeView1 := TreeViewDirSelect(Gui1, &quot;C:\Program Files&quot;)
Gui1.Show()
	---------------------------------------
	В первой опции (Gui) необходимо дать ссылку на ваш Gui, чтобы разместить TreeView в нём. Эта настройка обязательная.
	Вторая опция (DefaultDir) позволяет выбрать директорию по умолчанию, из которой будет происходить открытие папок. Вы можете указать эту настройку пустой (&quot;&quot;), чтобы отобразить ваши диски как изначальную директорию.
	Третья опция (Settings) позволяет внести дополнительные настройки при создании TreeView. Для этого создайте карту:
Settings := Map()
	И добавьте нужную опцию.
Settings[&quot;TreeViewOptions&quot;] := &quot;r15&quot;
	Позволит добавить опции AHK Gui при создани TreeView (Искать в руководстве AHK по Gui Object).
Settings[&quot;ShowHiddenFolders&quot;] := True
	Позволит показать скрытые папки.
	После чего добавьте опцию Settings при создании класса:
TreeView1 := TreeViewDirSelect(Gui1, &quot;C:\Program Files&quot;, Settings)
	---------------------------------------
	Элемент TreeView будет находиться в собственности &quot;TreeView&quot; родительского объекта (&quot;TreeView1&quot;), то есть в &quot;TreeView1.TreeView&quot; как в примере.
	---------------------------------------
	Для того, чтобы получить, к примеру путь к выбранной в TreeView папке, необходимо получить ID элемента и найти его в карте TreeView1.IDToPath.
	Для этого вызываем функцию GetSelection в TreeView.
ItemID := TreeView1.TreeView.GetSelection()
	После чего ищем её в TreeView1.IDToPath
Path := TreeView1.IDToPath[ItemID]
	Также возможно найти ItemID имея путь в TreeView1.PathToID, если он уже отрисован.
ItemID := TreeView1.PathToID[Path]
	Остальные возможные варианты взаимодействия с TreeView ищите в руководстве AHK по TreeView.
	*/
	
	__New(Gui, DefaultDir := &quot;&quot;, Settings := &quot;&quot;) {
		If (IsObject(Settings)) {
			If (Settings.Has(&quot;TreeViewOptions&quot;))
				This.TreeViewOptions := Settings[&quot;TreeViewOptions&quot;]
			Else
				This.TreeViewOptions := &quot;&quot;
			If (Settings.Has(&quot;ShowHiddenFolders&quot;))
				This.ShowHiddenFolders := Settings[&quot;ShowHiddenFolders&quot;]
			Else
				This.ShowHiddenFolders := False
		}
		Else
		If (!IsObject(Settings)) {
			This.TreeViewOptions := &quot;&quot;
			This.ShowHiddenFolders := False
		}
		
		This.TreeView := Gui.Add(&quot;TreeView&quot;, This.TreeViewOptions)
		This.TreeView.OnEvent(&quot;ItemExpand&quot;, (GuiCtrlObj, Item, Expanded) =&gt; This.TreeViewItemExpand(GuiCtrlObj, Item, Expanded))
		
		This.DefaultDir := DefaultDir
		This.DrivesList := DriveGetList(&quot;FIXED&quot;)
		
		This.PathToID := Map()
		This.IDToPath := Map()
		
		If (This.DefaultDir = &quot;&quot;) {
			Loop Parse This.DrivesList
				This.AddItem(A_LoopField &quot;:&quot;)
		}
		Else
		If (This.DefaultDir != &quot;&quot;) {
			This.AddItem(This.DefaultDir)
			Loop Files This.DefaultDir &quot;\*&quot;, &quot;D&quot;
				This.AddItem(A_LoopFileFullPath)
		}
	}
	
	AddItem(Path) {
		Loop Files Path &quot;\*&quot;, &quot;D&quot; {
			If (!This.ShowHiddenFolders AND InStr(A_LoopFileAttrib, &quot;H&quot;, 0))
				Continue
			HigherDirPath := &quot;&quot;
			FullDirPath := &quot;&quot;
			TrimmedPath := This.DefaultDir
			Loop Parse A_LoopFileFullPath, &quot;\&quot;, &quot;&quot; {
				DirName := A_LoopField
				If (FullDirPath = &quot;&quot;)
					FullDirPath := DirName
				Else
				If (FullDirPath != &quot;&quot;)
					FullDirPath := FullDirPath &quot;\&quot; DirName
				If (InStr(TrimmedPath, DirName, 1, 1, ) = 1) {
					If (TrimmedPath = DirName)
						TrimmedPath := &quot;&quot;
					Else
						TrimmedPath := SubStr(TrimmedPath, StrLen(DirName &quot;\&quot;)+1, )
					Continue
				}
				If (HigherDirPath = &quot;&quot;)
					DirPath := DirName
				Else
				If (HigherDirPath != &quot;&quot;)
					DirPath := HigherDirPath &quot;\&quot; DirName
				DriveName := &quot;&quot;
				If (A_Index = 1 AND InStr(DirName, &quot;:&quot;, , -1, ))
					DriveName := DriveGetLabel(DirName) &quot; (&quot; DirName &quot;)&quot;
				
				
				If (HigherDirPath = &quot;&quot; AND !This.PathToID.Has(DirPath)) {
					If (DriveName = &quot;&quot;)
						This.PathToID[DirPath] := This.TreeView.Add(DirName)
					Else
					If (DriveName != &quot;&quot;)
						This.PathToID[DirPath] := This.TreeView.Add(DriveName)
					This.IDToPath[This.PathToID[DirPath]] := FullDirPath
					HigherDirPath := DirPath
				}
				Else
				If (HigherDirPath != &quot;&quot; AND !This.PathToID.Has(DirPath)) {
					HigherDirPathID := This.PathToID[HigherDirPath]
					This.PathToID[DirPath] := This.TreeView.Add(DirName, HigherDirPathID)
					This.IDToPath[This.PathToID[DirPath]] := FullDirPath
					HigherDirPath := DirPath
				}
				Else
				If (This.PathToID.Has(DirPath))
					HigherDirPath := DirPath
			}
		}
	}
	
	TreeViewItemExpand(GuiCtrlObj, Item, Expanded) {
		If (!Expanded)
			Return
		Path := This.IDToPath[Item]
		Loop Files Path &quot;\*&quot;, &quot;D&quot;
			This.AddItem(A_LoopFileFullPath)
	}
}</code></pre></div><p>Работает быстро. То что я и хотел. Может кому ещё пригодится.</p>]]></description>
			<author><![CDATA[null@example.com (Bulef)]]></author>
			<pubDate>Sat, 09 Mar 2024 13:09:46 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160528#p160528</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160525#p160525</link>
			<description><![CDATA[<div class="quotebox"><cite>Bulef пишет:</cite><blockquote><p>А можно ли изменить цвет фона и текста в DirSelect?</p></blockquote></div><p>Может, как-то и можно, но вряд ли просто. Это системное окно, а не окно, которое создаёт скрипт.</p><div class="quotebox"><cite>Bulef пишет:</cite><blockquote><p>прогружаться по мере разворачивания директорий</p></blockquote></div><p>Вот это верный подход.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 09 Mar 2024 08:20:03 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160525#p160525</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160517#p160517</link>
			<description><![CDATA[<p>Попробуйте вот этот вариант:<br /></p><div class="codebox"><pre><code>#Requires AutoHotkey v2.0

TreeView1 := []
TreeView1.Gui := Gui()
TreeView1.TreeView := TreeView1.Gui.Add(&quot;TreeView&quot;)
TreeView1.AttachmentsTree := Map()
DrivesList := DriveGetList(&quot;FIXED&quot;)

; Парсит все диски
;Loop Parse DrivesList {
;	Loop Files A_LoopField &quot;:\*&quot;, &quot;DR&quot; {

; Тестовый путь
{
	Loop Files &quot;C:\Program Files\*&quot;, &quot;DR&quot; { ; Впишите тестовый путь
		TreeView1.HigherAttachmentsNames := &quot;&quot;
		Loop Parse A_LoopFileFullPath, &quot;\&quot;, &quot;&quot; {
			AttachmentName := A_LoopField
			
			If (TreeView1.HigherAttachmentsNames = &quot;&quot; AND !TreeView1.AttachmentsTree.Has(AttachmentName)) {
				TreeView1.AttachmentsTree[AttachmentName] := Map()
				TreeView1.AttachmentsTree[AttachmentName].TreeViewProp := TreeView1.TreeView.Add(AttachmentName)
				TreeView1.HigherAttachmentsNames := AttachmentName
			}
			Else
			If (TreeView1.HigherAttachmentsNames = &quot;&quot; AND TreeView1.AttachmentsTree.Has(AttachmentName))
				TreeView1.HigherAttachmentsNames := AttachmentName
			Else
			If (TreeView1.HigherAttachmentsNames != &quot;&quot;) {
				AttachmentsSource := TreeView1.AttachmentsTree
				Loop Parse TreeView1.HigherAttachmentsNames, &quot;|&quot;, &quot;&quot; {
					TreeAttachmentName := A_LoopField
					AttachmentsSource := AttachmentsSource[TreeAttachmentName]
				}
				
				If (!AttachmentsSource.Has(AttachmentName)) {
					AttachmentsSource[AttachmentName] := Map()
					AttachmentsSource[AttachmentName].TreeViewProp := TreeView1.TreeView.Add(AttachmentName, AttachmentsSource.TreeViewProp)
					TreeView1.HigherAttachmentsNames := TreeView1.HigherAttachmentsNames &quot;|&quot; AttachmentName
				}
				Else
				If (AttachmentsSource.Has(AttachmentName))
					TreeView1.HigherAttachmentsNames := TreeView1.HigherAttachmentsNames &quot;|&quot; AttachmentName
			}
		}
	}
}

TreeView1.Gui.Show()</code></pre></div><p>У меня всё заработало без ошибок даже если поставить парситься все диски. Но так или иначе, это нецелесообразно, так как процесс построения контрола занимает слишком много времени. Не знаю пока что с этим сделать. Видимо придётся отказаться от идеи и использовать DirSelect.</p><p>А можно ли изменить цвет фона и текста в DirSelect? Это возможно?</p><br /><p>Обновлено:<br />Я сделал быстрый вариант TreeView. Пока черновой вариант. Итемы в TreeView будут прогружаться по мере разворачивания директорий, а не сразу всё древо, как в варианте выше. Допишу класс и выложу как сделаю.</p>]]></description>
			<author><![CDATA[null@example.com (Bulef)]]></author>
			<pubDate>Fri, 08 Mar 2024 18:37:10 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160517#p160517</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160515#p160515</link>
			<description><![CDATA[<p>Нет, у меня ошибка сразу же, сейчас не у компьютера, не могу показать скриншот.<br />Избавляться от каких-либо символов нет смысла, в качестве ключа можно использовать что угодно, даже объект.<br />Массив здесь абсолютно не подходит, как я сказал выше. Для подобных целей, когда нужно сохранять данные в виде ключ-значение, обычно используется Map().</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Fri, 08 Mar 2024 18:00:20 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160515#p160515</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160514#p160514</link>
			<description><![CDATA[<p><strong>teadrinker</strong><br />Спасибо за ответ.</p><p>У меня скрипт работает на одном диске, а на другом не хочет. Попробуйте протестировать на какой-нибудь папке содержащей внутри мало подпапок, желательно в корне диска.<br />Я самоучка, по этому делаю как научился. Честно говоря не вижу проблем в использовании массивов в качестве хранилищ собственности и вложенной собственности.</p><p>В указанной ниже части я избавляюсь от escape character`ов в названии, так как предполагал, что проблема может быть в названии папки.</p><p>По поводу ошибки. Есть предположение, что есть какой-то лимит уровня вложенной собственности и дальше него уже собственность не создаётся.</p>]]></description>
			<author><![CDATA[null@example.com (Bulef)]]></author>
			<pubDate>Fri, 08 Mar 2024 16:55:01 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160514#p160514</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160512#p160512</link>
			<description><![CDATA[<p>Как-то у вас больно мудрёно получилось, непонятно, чего хотели добиться. У меня ваш код сразу выдаёт ошибку.<br />По-моему, вы выбрали какой-то семантически неверный подход. Вы берёте массив TreeView1 := [], потом начинаете присваивать ему свойства: TreeView1.Gui := Gui(), TreeView1.%PropName% := [] ... Хотя массив и является объектом, и присваивание свойств не запрещено, он для этого совсем не предназначен. В массиве в качестве свойств должны быть только индексы.<br />Вот эта часть<br /></p><div class="codebox"><pre><code>			PropName := StrReplace(PropName, &quot; &quot;, &quot;_Space&quot;, 0)
			PropName := StrReplace(PropName, &quot;.&quot;, &quot;_Dot&quot;, 0)
			PropName := StrReplace(PropName, &quot;``&quot;, &quot;_Accent&quot;, 0)
			PropName := StrReplace(PropName, &quot;`;&quot;, &quot;_Semicolon&quot;, 0)
			PropName := StrReplace(PropName, &quot;`:&quot;, &quot;_Colon&quot;, 0)
			PropName := StrReplace(PropName, &quot;`{&quot;, &quot;_LeftCurlyBrace&quot;, 0)
			PropName := StrReplace(PropName, &quot;`&quot;&quot;, &quot;_DoubleQuoteMark&quot;, 0)
			PropName := StrReplace(PropName, &quot;`&#039;&quot;, &quot;_QuoteMark&quot;, 0)</code></pre></div><p>вообще непонятно для чего.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Fri, 08 Mar 2024 15:48:14 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160512#p160512</guid>
		</item>
		<item>
			<title><![CDATA[AHK v2: TreeView как альтернатива DirSelect]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=160506#p160506</link>
			<description><![CDATA[<p>Здравствуйте. Захотелось создать кастомное окно по типу DirSelect. Сделал вот такое решение:</p><div class="codebox"><pre><code>#Requires AutoHotkey v2.0

TreeView1 := []
TreeView1.Gui := Gui()
TreeView1.Gui.TreeView := TreeView1.Gui.Add(&quot;TreeView&quot;)
DrivesList := DriveGetList(&quot;FIXED&quot;)

; Парсит все диски
;Loop Parse DrivesList {
;	Loop Files A_LoopField &quot;:\*&quot;, &quot;DR&quot; {

; Тестовый путь
{
	Loop Files &quot;C:\Program Files\*&quot;, &quot;DR&quot; { ; Впишите тестовый путь
		TreeView1.HigherPropName := &quot;&quot;
		Loop Parse A_LoopFileFullPath, &quot;\&quot;, &quot;&quot; {
			TreeViewName := A_LoopField
			PropName := A_LoopField
			PropName := StrReplace(PropName, &quot; &quot;, &quot;_Space&quot;, 0)
			PropName := StrReplace(PropName, &quot;.&quot;, &quot;_Dot&quot;, 0)
			PropName := StrReplace(PropName, &quot;``&quot;, &quot;_Accent&quot;, 0)
			PropName := StrReplace(PropName, &quot;`;&quot;, &quot;_Semicolon&quot;, 0)
			PropName := StrReplace(PropName, &quot;`:&quot;, &quot;_Colon&quot;, 0)
			PropName := StrReplace(PropName, &quot;`{&quot;, &quot;_LeftCurlyBrace&quot;, 0)
			PropName := StrReplace(PropName, &quot;`&quot;&quot;, &quot;_DoubleQuoteMark&quot;, 0)
			PropName := StrReplace(PropName, &quot;`&#039;&quot;, &quot;_QuoteMark&quot;, 0)
			
			If (TreeView1.HigherPropName = &quot;&quot; AND !HasProp(TreeView1, PropName)) {
				TreeView1.%PropName% := []
				TreeView1.%PropName%.TreeViewProp := TreeView1.Gui.TreeView.Add(TreeViewName)
				TreeView1.HigherPropName := PropName
			}
			Else
			If (TreeView1.HigherPropName = &quot;&quot; AND HasProp(TreeView1, PropName))
				TreeView1.HigherPropName := PropName
			Else
			If (TreeView1.HigherPropName != &quot;&quot;) {
				PropSource := TreeView1
				Loop Parse TreeView1.HigherPropName, &quot;.&quot;, &quot;&quot; {
					TreePropName := A_LoopField
					PropSource := PropSource.%TreePropName%
				}
				
				If (!HasProp(PropSource, PropName)) {
					PropSource.%PropName% := []
					PropSource.%PropName%.TreeViewProp := TreeView1.Gui.TreeView.Add(TreeViewName, PropSource.TreeViewProp)
					TreeView1.HigherPropName := TreeView1.HigherPropName &quot;.&quot; PropName
				}
				Else
				If (HasProp(PropSource, PropName))
					TreeView1.HigherPropName := TreeView1.HigherPropName &quot;.&quot; PropName
			}
		}
	}
}

TreeView1.Gui.Show()</code></pre></div><p>Проблема в том, что оно оказалось очень медленным и если парсить все диски, на каком-то этапе выдаёт ошибку. Причину ошибки я не смог найти.<br />Есть ли какие-то решения для TreeView, чтобы можно было быстро отрисовать окно, и если нет, подскажите, где искать ошибку?</p>]]></description>
			<author><![CDATA[null@example.com (Bulef)]]></author>
			<pubDate>Fri, 08 Mar 2024 09:58:19 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=160506#p160506</guid>
		</item>
	</channel>
</rss>
