Доброго времени суток!
Пишу функцию для создания и изменения структуры по типу дерева.
Сейчас борюсь с перемещением элементов по дереву.
На основе примера уважаемого AZJIO >>http://autoit-script.ru/index.php/topic,12101.0.html
составил код привожу ниже.
Вопрос первый.
Я перемещаю элементы переименованием и переносом дочерних ветвей элементов.
Есть ли другой более простой, более правильный способ?
Вопрос второй.
Скрипт работает для всех элементов кроме верхнего базового и нижнего базового.
(под базовыми элементами имею ввиду элементы, у которых "родитель" =0).
Как определить самый верхний и самый нижний в дереве базовые элементы?
Для демонстрации проблемы
замените строчку
на
и закомментируйте строку
в функции _TreeViewItemMove
Код:
Пишу функцию для создания и изменения структуры по типу дерева.
Сейчас борюсь с перемещением элементов по дереву.
На основе примера уважаемого AZJIO >>http://autoit-script.ru/index.php/topic,12101.0.html
составил код привожу ниже.
Вопрос первый.
Я перемещаю элементы переименованием и переносом дочерних ветвей элементов.
Есть ли другой более простой, более правильный способ?
Вопрос второй.
Скрипт работает для всех элементов кроме верхнего базового и нижнего базового.
(под базовыми элементами имею ввиду элементы, у которых "родитель" =0).
Как определить самый верхний и самый нижний в дереве базовые элементы?
Для демонстрации проблемы
замените строчку
Код:
$FirstLevel = GUICtrlCreateTreeViewItem($LngItm & $i, $Root)
на
Код:
$FirstLevel = GUICtrlCreateTreeViewItem($LngItm & $i, $iTreeView)
и закомментируйте строку
Код:
If $hParent= 0 Then Return
в функции _TreeViewItemMove
Код:
Код:
#NoTrayIcon
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiTreeView.au3>
; En
$LngTitle = 'TreeView'
$LngPath = 'Path'
$LngInd = 'Index'
$LngDel = 'Delete'
$LngItm = 'Item'
$LngUP = 'Item Up'
$LngDown = 'Item Down'
; Ru
If @OSLang = 0419 Then
$LngTitle = 'TreeView'
$LngPath = 'Путь из имён'
$LngInd = 'Путь из индексов'
$LngDel = 'Удалить'
$LngItm = 'П.'
$LngUP = 'Вверх'
$LngDown = 'Вниз'
EndIf
$hGui = GUICreate($LngTitle, 350, 375, -1, -1, $WS_OVERLAPPEDWINDOW)
Global $iTreeView = GUICtrlCreateTreeView(1, 1, 350, 375)
GUICtrlSetFont(-1, 12, 400, 0, "Verdana")
GUICtrlSetResizing(-1, 2 +4 + 32 + 64 + 256)
Global $hTreeView = GUICtrlGetHandle(-1)
; Создаём пункты дерева
Global $Root = GUICtrlCreateTreeViewItem("\", $iTreeView)
For $i = 0 To 9
$FirstLevel = GUICtrlCreateTreeViewItem($LngItm & $i, $Root)
For $j = 0 To 3
$SndLevel = GUICtrlCreateTreeViewItem($LngItm & $i & "." & $j, $FirstLevel)
For $k = 0 To 9
GUICtrlCreateTreeViewItem($LngItm & $i & "."& $j & "." & $k, $SndLevel)
Next
Next
Next
$iDummy = GUICtrlCreateDummy()
$ContMenu = GUICtrlCreateContextMenu($iDummy)
$hMenu = GUICtrlGetHandle($ContMenu)
$iCM_Up = GUICtrlCreateMenuItem($LngUP & @TAB & 'Shift+UP', $ContMenu)
$iCM_Down = GUICtrlCreateMenuItem($LngDown& @TAB & 'Shift+Down', $ContMenu)
$iCM_Path = GUICtrlCreateMenuItem($LngPath & @TAB & 'Enter', $ContMenu)
$iCM_Ind = GUICtrlCreateMenuItem($LngInd & @TAB & 'Ctrl+Enter', $ContMenu)
$iCM_Del = GUICtrlCreateMenuItem($LngDel & @TAB & 'Ctrl+Del', $ContMenu)
; установка горячих клавиш на пункты контекстного меню
Dim $AccelKeys[5][2] = [ ["+{UP}" , $iCM_Up ], _
["+{DOWN}" , $iCM_Down ], _
["{Enter}" , $iDummy ], _
["^{DEL}" , $iCM_Del ], _
["^{Enter}" , $iCM_Ind ] ]
GUISetAccelerators($AccelKeys)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()
GUICtrlSetState($Root, $GUI_EXPAND)
While 1
Switch GUIGetMsg()
Case $iCM_Up
_TreeViewItemMove($hTreeView,1)
Case $iCM_Down
_TreeViewItemMove($hTreeView,-1)
Case $iCM_Path
_OpenExplorer()
Case $iCM_Del
$hItem = _GUICtrlTreeView_GetSelection($hTreeView)
_GUICtrlTreeView_Delete($hTreeView, $hItem)
Case $iCM_Ind
MsgBox(0, 'Сообщение', ControlTreeView($hGui, '', 'SysTreeView321', 'GetSelected', 1), 0, $hGui)
Case $iDummy ; Событие по кнопке Enter, и действие взависимости от того, какой элемент в фокусе
MsgBox(0, 'Сообщение', ControlTreeView($hGui, '', 'SysTreeView321', 'GetSelected'), 0, $hGui)
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
Exit ;==>MainProgram
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $hWndFrom
Case $hTreeView
Switch $iCode
Case $NM_RCLICK ; Вызов контекстного меню правой кнопкой мыши
Local $tMPos = _WinAPI_GetMousePos(True, $hWndFrom) ; координаты относительно элемента
Local $hItem = _GUICtrlTreeView_HitTestItem($hWndFrom, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2)) ; получаем дескриптор пункта
If $hItem > 0 Then ; проверка, чтобы вызов был на пункте
$x = MouseGetPos(0)
$y = MouseGetPos(1)
_GUICtrlTreeView_SelectItem($hTreeView, $hItem)
; заставляет появится меню в указанных координатах
DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hGui, "ptr", 0)
EndIf
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY
Func _TreeViewItemMove($hWnd,$way)
; "двигаем" выделенный элемент TreeView вверх ($way =1) или вниз($way= -1)
$hItem = _GUICtrlTreeView_GetSelection($hWnd) ; получаем выделенный элемент
$sItem = _GUICtrlTreeView_GetText($hWnd ,$hItem)
$hParent =_GUICtrlTreeView_GetParentHandle($hWnd ,$hItem)
If $hParent= 0 Then Return
If $way > 0 Then
; направление вверх
If $hItem = _GUICtrlTreeView_GetFirstChild($hWnd, $hParent) Then Return ; если первый ребенок
$hItemBro= _GUICtrlTreeView_GetPrev($hWnd, $hItem)
While $hParent <> _GUICtrlTreeView_GetParentHandle($hWnd, $hItemBro); ищу старшего брата по общему предку
$hItemBro= _GUICtrlTreeView_GetPrev($hWnd, $hItemBro)
WEnd
Else
; направление вниз
If $hItem = _GUICtrlTreeView_GetLastChild($hWnd, $hParent) Then Return ; если последний ребенок
$hItemBro = _GUICtrlTreeView_GetNext($hWnd, $hItem)
While $hParent <> _GUICtrlTreeView_GetParentHandle($hWnd, $hItemBro); ищу младшего брата по общему предку
$hItemBro = _GUICtrlTreeView_GetNext($hWnd, $hItemBro)
WEnd
EndIf
$sItemBro = _GUICtrlTreeView_GetText($hWnd ,$hItemBro) ; имя брата
_GUICtrlTreeView_SetText($hWnd ,$hItemBro, $sItem ) ; становлюсь на место брата
_GUICtrlTreeView_SetText($hWnd ,$hItem, $sItemBro)
; обмен детьми
$nChildrenItemBro = _GUICtrlTreeView_GetChildCount($hWnd, $sItemBro)
If $nChildrenItemBro Then
$hTMP = _GUICtrlTreeView_AddChild($hWnd, $hParent, "") ; времянка для детей брата
_MoveTreeChildern($hWnd, $hItemBro, $hTMP)
EndIf
If _GUICtrlTreeView_GetChildCount($hWnd, $hItem) Then
_MoveTreeChildern($hWnd, $hItem , $hItemBro)
EndIf
If $nChildrenItemBro Then
_MoveTreeChildern($hWnd, $hTMP , $hItem)
_GUICtrlTreeView_Delete($hWnd, $hTMP)
EndIf
;перемещаю выделение
_GUICtrlTreeView_SetState($hWnd, $hItem , $TVIS_SELECTED,0)
_GUICtrlTreeView_SetState($hWnd, $hItemBro , $TVIS_SELECTED,1)
_GUICtrlTreeView_ClickItem($hWnd, $hItemBro)
EndFunc ;==>_TreeViewItemMove
Func _MoveTreeChildern($hWnd, $hItemA , $hItemB)
; переносим дерево с дочерними элементами из $hItemA в $hItemB
If _GUICtrlTreeView_GetChildCount($hWnd, $hItemA) Then
For $i = 1 To _GUICtrlTreeView_GetChildCount($hWnd, $hItemA)
$hChildItem = _GUICtrlTreeView_GetLastChild($hWnd, $hItemA)
$hChildMove = _GUICtrlTreeView_AddChildFirst($hWnd, $hItemB, _GUICtrlTreeView_GetText($hWnd ,$hChildItem))
_MoveTreeChildern($hWnd,$hChildItem,$hChildMove)
_GUICtrlTreeView_Delete($hWnd , $hChildItem)
Next
Else
_GUICtrlTreeView_AddChildFirst($hWnd, $hItemB, _GUICtrlTreeView_GetText($hWnd ,$hItemA))
_GUICtrlTreeView_Delete($hWnd, $hItemA)
EndIf
EndFunc ;==>_MoveTreeChildern