Что нового

Как получить список всех элементов TreeView (с дочками-внуками)?

sss

Продвинутый
Сообщения
332
Репутация
96
Всем доброго времени суток! Созрела очередная проблема, с виду простая, но повергшая меня в ступор. Есть TreeView с элементами - есть с дочерними элементами, есть без. Максимальная глубина - 2 (то есть элемент в элементе, не глубже). Примерный вид набросал в Koda:
Код:
#include <GUIConstantsEx.au3>
#include <TreeViewConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 217, 257)
$TreeView1 = GUICtrlCreateTreeView(8, 8, 201, 169)
$TreeView1_0 = GUICtrlCreateTreeViewItem("Item1", $TreeView1)
$TreeView1_1 = GUICtrlCreateTreeViewItem("Child1", $TreeView1_0)
$TreeView1_2 = GUICtrlCreateTreeViewItem("Child2", $TreeView1_0)
$TreeView1_3 = GUICtrlCreateTreeViewItem("Child3", $TreeView1_0)
$TreeView1_4 = GUICtrlCreateTreeViewItem("Item2", $TreeView1)
$TreeView1_5 = GUICtrlCreateTreeViewItem("Child1", $TreeView1_4)
$TreeView1_6 = GUICtrlCreateTreeViewItem("Item3", $TreeView1)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
Надо создать массив, в котором будут указаны все эти элементы - корневые с префиксом "/++\", дочерние с "/XX\". То есть, для кода в примере должен получиться такой массив:
$array[0]=7 (кол-во элементов)
$array[1]=/++\Item1
$array[2]=/XX\Child1
$array[3]=/XX\Child2
$array[4]=/XX\Child3
$array[5]=/++\Item2
$array[6]=/XX\Child1
$array[7]=/++\Item3

Как это реализовать? Заранее спасибо.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Sky-WaLkeR,
Может так?
Код:
#include <GUIConstantsEx.au3>
#include <Array.au3>

#cs
	$aTreeView[0][0] - кол-во TreeViewItem (задается сразу)
	$aTreeView[0][1] - размеры TreeView
	$aTreeView[0][2] - ID TreeView
	$aTreeView[0][3] = Handle TreeView
	-----
	n = $aTreeView[0][0]
	$aTreeView[1- n][0] - текст TreeViewItem (задается сразу)
	$aTreeView[1- n][1] - индекс строки колонки 2 с родителем TreeViewItem (задается сразу)
	$aTreeView[1- n][2] - ID TreeViewItem
	$aTreeView[1- n][3] - Handle TreeViewItem
	$aTreeView[1- n][4] - текст TreeViewItem c префиксом
#ce
$sParent = '/++\'
$sChild = '/XX\'
Dim $aTreeView[8][5] = [[7, '8|8|201|169'],['Item1', 0],['Child1', 1],['Child2', 1],['Child3', 1], _
		['Item2', 0],['Child1', 5],['Item3', 0]]
$aPosTV = StringSplit($aTreeView[0][1], '|')
$hGui = GUICreate('Test', 217, 231)
$aTreeView[0][2] = GUICtrlCreateTreeView($aPosTV[1], $aPosTV[2], $aPosTV[3], $aPosTV[4])
$aTreeView[0][3] = GUICtrlGetHandle($aTreeView[0][2])
$aTreeView[0][4] = 'Мама :)'
For $i = 1 To $aTreeView[0][0]
	$aTreeView[$i][2] = GUICtrlCreateTreeViewItem($aTreeView[$i][0], $aTreeView[$aTreeView[$i][1]][2])
	$aTreeView[$i][3] = GUICtrlGetHandle($aTreeView[$i][2])
	If $aTreeView[$i][1] Then
		$aTreeView[$i][4] = $sChild & $aTreeView[$i][0]
	Else
		$aTreeView[$i][4] = $sParent & $aTreeView[$i][0]
	EndIf
Next
$nButton = GUICtrlCreateButton('Show', 75, 190, 67, 30)
GUISetState()

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

CreatoR

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

Код:
#include <GUIConstantsEx.au3>
#include <Array.au3>

;Нужно ли?
Global $sPrnt_Prfx = '/++\'
Global $sChld_Prfx = '/XX\'

Global $aTV_Data[4][2] = [[3], ['Item1', 'Child1|Child2|Child3'], ['Item2', 'Child1'], ['Item3']]
Global $aTV_IDs[1][2]

$hGUI = GUICreate('Test', 220, 230)
$nTreeView = GUICtrlCreateTreeView(10, 10, 200, 170)

For $i = 1 To $aTV_Data[0][0]
	$aChilds = StringSplit($aTV_Data[$i][1], "|")
	
	$aTV_IDs[0][0] += 1
	ReDim $aTV_IDs[$aTV_IDs[0][0] + 1][2]
	$aTV_IDs[$aTV_IDs[0][0]][0] = GUICtrlCreateTreeViewItem($aTV_Data[$i][0], $nTreeView)
	
	$aTV_Data[$i][0] = $sPrnt_Prfx & $aTV_Data[$i][0]
	$aTV_Data[$i][1] = ''
	
	For $j = 1 To $aChilds[0]
		If $aChilds[$j] = "" Then ContinueLoop
		$aTV_Data[$i][1] &= $sChld_Prfx & $aChilds[$j]
		$aTV_IDs[$aTV_IDs[0][0]][1] &= GUICtrlCreateTreeViewItem($aChilds[$j], $aTV_IDs[$aTV_IDs[0][0]][0])
		
		If $j < $aChilds[0] Then
			$aTV_IDs[$aTV_IDs[0][0]][1] &= "|"
			$aTV_Data[$i][1] &= "|"
		EndIf
	Next
Next

$nButton = GUICtrlCreateButton('Show', 75, 190, 70, 25)
GUISetState(@SW_SHOW, $hGUI)

While 1
	$nMsg = GUIGetMsg()
	
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButton
			_ArrayDisplay($aTV_Data)
			_ArrayDisplay($aTV_IDs)
	EndSwitch
WEnd
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR [?]
Я бы наверное сделал так:
Мне удобнее (привык) все данные хранить в одном массиве, отдельном для каждого набора элементов.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles [?]
Мне удобнее (привык) все данные хранить в одном массиве
Ну... для автора вроде как бы ID/Handle не нужны :smile:, он про них ничего не писал.
Я поправил свой пример, чтобы поддерживал префиксы.
 
Автор
sss

sss

Продвинутый
Сообщения
332
Репутация
96
madmasles
Спасибо! Очень удобная конструкция! Все данные в одном массиве, очень удобно. Буду использовать Ваш вариант.
CreatoR
Ваш скрипт тоже хорош, но Вы не совсем поняли то, что мне нужно. Мне надо чтобы все элементы были в 1 месте (размерности), поэтому потребность в префиксах. Я буду записывать построчно все элементы с префиксами в файл, а при следующем запуске читать из него и генерировать новый TreeView.
Всем спасибо, тема решена!
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Sky-WaLkeR [?]
Я буду записывать построчно все элементы с префиксами в файл, а при следующем запуске читать из него и генерировать новый TreeView.
Что мешает это делать с массивом где хранятся только записи?
Тем более что ID и Handle при восстановлений пунктов не помогут.

Для сохранения в файл я бы использовал ini, т.е имя секций это родительский элемент, а «ключ=значение» это дочерний элемент, где «ключ» это порядковый номер элемента, а «значение» собственно само название параметра, вот так примерно:

Код:
#include <GUIConstantsEx.au3>
#include <GUITreeView.au3>

Global $sTVItems_File = @ScriptDir & "\TV_Items.ini"
Global $aTV_Items = IniReadSectionNames($sTVItems_File)

$hGUI = GUICreate('Restore TV States Demo', 220, 230)
$nTreeView = GUICtrlCreateTreeView(10, 10, 200, 170)
$hTreeView = GUICtrlGetHandle($nTreeView)

For $i = 1 To UBound($aTV_Items)-1
	$nParent = GUICtrlCreateTreeViewItem($aTV_Items[$i], $nTreeView)
	
    $aTV_SubItems = IniReadSection($sTVItems_File, $aTV_Items[$i])
    
    For $j = 1 To UBound($aTV_SubItems)-1
		GUICtrlCreateTreeViewItem($aTV_SubItems[$j][1], $nParent)
    Next
Next

$nAddItem_Button = GUICtrlCreateButton('Add Item', 10, 190, 60, 25)
$nAddSubItem_Button = GUICtrlCreateButton('Add SubItem', 75, 190, 70, 25)
$nWrite_Button = GUICtrlCreateButton('Write', 160, 190, 50, 25)

GUISetState(@SW_SHOW, $hGUI)

While 1
    $nMsg = GUIGetMsg()
    
    Switch $nMsg
		Case $GUI_EVENT_CLOSE, $nWrite_Button
			$sTVItems_Data = ""
			$hItem = _GUICtrlTreeView_GetFirstItem($nTreeView)
			
			While 1
				If _GUICtrlTreeView_GetChildren($nTreeView, $hItem) Then
					$sTVItems_Data &= "[" & _GUICtrlTreeView_GetText($nTreeView, $hItem) & "]" & @CRLF
					
					For $i = 0 To _GUICtrlTreeView_GetChildCount($nTreeView, $hItem) - 1
						$hItem = _GUICtrlTreeView_GetNext($nTreeView, $hItem)
						$sTVItems_Data &= $i + 1 & "=" & _GUICtrlTreeView_GetText($nTreeView, $hItem) & @CRLF
					Next
				Else
					$sTVItems_Data &= "[" & _GUICtrlTreeView_GetText($nTreeView, $hItem) & "]" & @CRLF
				EndIf
				
				$hItem = _GUICtrlTreeView_GetNext($nTreeView, $hItem)
				If $hItem = 0 Then ExitLoop
			WEnd
			
			$hFile = FileOpen($sTVItems_File, 2)
			FileWrite($hFile, $sTVItems_Data)
			FileClose($hFile)
			
			If $nMsg = $GUI_EVENT_CLOSE Then Exit
		Case $nAddItem_Button
			While 1
				$sItemText = InputBox("Item name", "Enter item name:", Eval("sItem"), "", Default, Default, Default, Default, 0, $hGUI)
				
				If @error Or $sItemText = "" Then
					ContinueLoop 2
				EndIf
				
				$iParentFound = 0
				$hItem = _GUICtrlTreeView_GetFirstItem($nTreeView)
				
				For $i = 0 To _GUICtrlTreeView_GetCount($nTreeView) - 1
					If Not StringInStr(_GUICtrlTreeView_GetTree($nTreeView, $hItem), "|") Then
						If _GUICtrlTreeView_GetText($nTreeView, $hItem) = $sItemText Then
							$iParentFound = 1
							ExitLoop
						EndIf
					EndIf
					
					$hItem = _GUICtrlTreeView_GetNext($nTreeView, $hItem)
				Next
				
				If Not $iParentFound Then
					$sItem = $sItemText
					ExitLoop
				EndIf
				
				MsgBox(48, 'Attention', 'Already exists.', 0, $hGUI)
			WEnd
			
			$hItem = GUICtrlCreateTreeViewItem($sItem, $nTreeView)
			_GUICtrlTreeView_SelectItem($nTreeView, $hItem, $TVGN_CARET)
			GUICtrlSetState($nTreeView, $GUI_FOCUS)
		Case $nAddSubItem_Button
			$sItemText = InputBox("Item name", "Enter item name:", Eval("sItem"), "", Default, Default, Default, Default, 0, $hGUI)
			
			If Not @error Then
				$sItem = $sItemText
				$hItem = _GUICtrlTreeView_GetSelection($nTreeView)
				
				If StringInStr(_GUICtrlTreeView_GetTree($nTreeView, $hItem), "|") Then
					$hItem = _GUICtrlTreeView_GetParentHandle($nTreeView, $hItem)
				EndIf
				
				If $hItem Then _GUICtrlTreeView_Expand($nTreeView, $hItem)
				$hItem = _GUICtrlTreeView_AddChild($nTreeView, $hItem, $sItem)
				_GUICtrlTreeView_SelectItem($nTreeView, $hItem, $TVGN_CARET)
				GUICtrlSetState($nTreeView, $GUI_FOCUS)
			EndIf
    EndSwitch
WEnd


Забыл про TV_Items.ini:
INI:
[Item1]
1=Child1
2=Child2
3=Child3
[Item2]
1=Child1
[Item3]

P.S
Вопрос судя по всему поставлен неправильно, нужно было начинать не из получения массива, а из полной задачи, описанной в последнем посте (о записи и чтение из файла).
 
Автор
sss

sss

Продвинутый
Сообщения
332
Репутация
96
CreatoR
Большое спасибо за пост! Да, наверное, Вы правы - я думал, что чтение-запись не проблема, поэтому и писал только о получении. Ваш скрипт - то, что надо! Я как-то даже и не подумал о возможности использования ini-файла для этого.
 
Верх