Что нового

Глюки при использовании _GUICtrlTreeView_DeleteAll()

Vitorrio

Новичок
Сообщения
8
Репутация
0
Приветствую всех!
Ребята такая проблемка:

Создаю TreeView который заполняется списком оборудования,
при выборе устройства, в ListView показываются его свойства.
Есть кнопка "Обновить" при нажатии на которую, происходит:
Очиска ListView
Очиска TreeView
Повторное заполнение списка устройств.

проблема в том, что:
если выделена любая (кроме последней) позиция в TreeView, после нажатия на кнопку
"Обновить" текст из ListView остаётся, точнее сказать он появляется опять.
Выглядит так, как будто, после очистки TreeView происходит автовыделение первой позиции в этом списке и срабатывает функция которая опять заполняет ListView.
Последующие нажатия на эту кнопку очищают список...
Не могу понять в чём проблема: глюки функции UDF или я где накосячил...
Help Please!

Код:
Код:
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <TreeViewConstants.au3>
#include <GuiTreeView.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <WINAPI.au3>

Opt("GUIOnEventMode", 1)

Global $MainForm_1 = GUICreate("USB Info", 628, 261, -1, -1)
Global $btn_exit = GUICtrlCreateButton("Exit", 550, 230, 76, 26, $WS_GROUP)
GUICtrlSetOnEvent(-1, "btn_exitClick")
Global $btn_refresh = GUICtrlCreateButton("Refresh", 290, 230, 75, 26, $WS_GROUP)
GUICtrlSetOnEvent(-1, "btn_refreshClick")
Global $dev_tree = GUICtrlCreateTreeView(5, 5, 281, 251, BitOR($TVS_HASLINES,$TVS_LINESATROOT,$TVS_SHOWSELALWAYS,$WS_GROUP,$WS_TABSTOP,$WS_VSCROLL,$WS_BORDER))
Global $lst_info = GUICtrlCreateListView("Param|Value", 290, 40, 336, 186, BitOR($LVS_REPORT,$LVS_SINGLESEL,$LVS_SHOWSELALWAYS,$LVS_AUTOARRANGE,$WS_VSCROLL,$WS_BORDER), BitOR($WS_EX_CLIENTEDGE,$LVS_EX_GRIDLINES,$LVS_EX_FULLROWSELECT))
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 75)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 250)
GUISetState(@SW_SHOW)

$lst_info = GUICtrlGetHandle($lst_info);

Global $dev_tree_item[128];
Global $lst_info_[1024];
Global $lst_infoItem[1024];
Global	$dev_name[25];
Global	$dev_caption[25];
Global	$dev_description[25];


Main()

Func Main()
_get_devices()
While 1
	Sleep(100)
WEnd
EndFunc
Func _get_devices()
	Local $USB_ObjCol;
	Local $USB_ColItems;
	; Clear device list.
	_GUICtrlTreeView_DeleteAll($dev_tree);
	_clear_info();
	
	$USB_ObjCol = ObjGet("winmgmts:")
	$USB_ColItems = $USB_ObjCol.instancesof("CIM_USBDevice");
	if @error Then
		Msgbox (0,"","Error at getting object. Error code: " & @error)
		Return
	EndIf
	$i=0
	for $USB_objItem in $USB_ColItems
			$dev_tree_item[$i] = GUICtrlCreateTreeViewItem($USB_objItem.Caption, $dev_tree);
			GUICtrlSetOnEvent($dev_tree_item[$i], 'dev_tree_itemClick');
			$dev_name[$i] = $USB_objItem.Name
			$dev_caption[$i] = $USB_objItem.Caption
			$dev_description[$i] = $USB_objItem.Description
			$i+=1
	Next
EndFunc
Func _select_device()
	_clear_info();
	$cur_item = _GUICtrlTreeView_GetSelection($dev_tree)
	$cur_dev_index = _GUICtrlTreeView_Index($dev_tree, $cur_item)
	_GUICtrlListView_AddItem($lst_info, 'Device name:',0)
	_GUICtrlListView_AddSubItem($lst_info, 0,$dev_name[$cur_dev_index],1);
	_GUICtrlListView_AddItem($lst_info, 'Caption:',0)
	_GUICtrlListView_AddSubItem($lst_info, 1,$dev_caption[$cur_dev_index],1);
	_GUICtrlListView_AddItem($lst_info, 'Description:',0)
	_GUICtrlListView_AddSubItem($lst_info, 2,$dev_description[$cur_dev_index],1);
	; 	Autosize column width.
	_GUICtrlListView_SetColumnWidth($lst_info,0,$LVSCW_AUTOSIZE);
	_GUICtrlListView_SetColumnWidth($lst_info,1,$LVSCW_AUTOSIZE);
	_GUICtrlListView_EndUpdate($lst_info);
EndFunc
Func _clear_info()
	; Delete all items fron info list.
	_GUICtrlListView_DeleteAllItems($lst_info);
EndFunc
Func btn_exitClick()
_exit()
EndFunc
Func btn_refreshClick()
	$a = _GUICtrlTreeView_SetState($dev_tree,_GUICtrlTreeView_GetSelection($dev_tree),$TVIS_SELECTED,TRUE)
	ConsoleWrite($a  & ':::' & _GUICtrlTreeView_GetSelection($dev_tree) & @crlf)
	_get_devices();
	_clear_info();
EndFunc
Func dev_tree_itemClick()
	ConsoleWrite("Item click! Selected:" & _GUICtrlTreeView_Index($dev_tree, _GUICtrlTreeView_GetSelection($dev_tree)) & @CRLF)
	_select_device()
EndFunc
Func MainFormClose()
_exit()
EndFunc
Func _exit()
	Exit
EndFunc
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
622

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,320
Vitorrio
Попробуйте использовать в UDF функциях (_GUICtrlTreeView_***, _GUICtrlListView_***) не ID, а Handle элементов (GUICtrlGetHandle()). Я в Вашем скрипте поменял ID на Handle, вроде без ошибок работает.
Код:
;...
Local $hTV = GUICtrlGetHandle($dev_tree)
ConsoleWrite('Del_TV: ' & _GUICtrlTreeView_DeleteAll($hTV) & @CR)
;...
;...
Local $hLV = GUICtrlGetHandle($lst_info)
ConsoleWrite('Del_LV: ' & _GUICtrlListView_DeleteAllItems($hLV) & @CR)
;...
 
Автор
V

Vitorrio

Новичок
Сообщения
8
Репутация
0
А где именно заменили?
Я пробую, результат тот же.
Если только в _GUICtrlTreeView_DeleteAll(),
то это мало что даёт, про баг в ListView знаю, поэтом у сразу юзал по Handle.
_GUICtrlTreeView_DeleteAll судя по всему срабатывает нормально,
такое впечатление, как будто после очистки и заполнения TreeView вызыватся событие Click на каждой созданной TreeView_Item ... :wacko:
Это хорошо видно в окне консоли...

Функция GUICtrlCreateTreeViewItem работает только по ID,
пробовал аналогичные из UDF - вообще не срабатывает GUICtrlSetOnEvent
:(

А можно попросить ваш вариант кода полностью?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,320
Vitorrio
Я же написал:
в UDF функциях (_GUICtrlTreeView_***, _GUICtrlListView_***)
Примерно так:
Код:
#include <GUIConstantsEx.au3>
;#include <ListViewConstants.au3>
;#include <TreeViewConstants.au3>
#include <GuiTreeView.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
;#include <WINAPI.au3>

Opt("GUIOnEventMode", 1)

Global $MainForm_1 = GUICreate("USB Info", 628, 261, -1, -1)
Global $btn_exit = GUICtrlCreateButton("Exit", 550, 230, 76, 26, $WS_GROUP)
GUICtrlSetOnEvent(-1, "btn_exitClick")
Global $btn_refresh = GUICtrlCreateButton("Refresh", 290, 230, 75, 26, $WS_GROUP)
GUICtrlSetOnEvent(-1, "btn_refreshClick")
Global $dev_tree = GUICtrlCreateTreeView(5, 5, 281, 251, BitOR($TVS_HASLINES, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS, $WS_GROUP, $WS_TABSTOP, $WS_VSCROLL, $WS_BORDER))
Global $lst_info = GUICtrlCreateListView("Param|Value", 290, 40, 336, 186, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_AUTOARRANGE, $WS_VSCROLL, $WS_BORDER), BitOR($WS_EX_CLIENTEDGE, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 75)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 250)
GUISetState()

Global $dev_tree_item[128];
Global $lst_info_[1024];
Global $lst_infoItem[1024];
Global $dev_name[25];
Global $dev_caption[25];
Global $dev_description[25];


Main()

Func Main()
	_get_devices()
	While 1
		Sleep(100)
	WEnd
EndFunc   ;==>Main
Func _get_devices()
	Local $USB_ObjCol;
	Local $USB_ColItems;
	; Clear device list.
	Local $hTV = GUICtrlGetHandle($dev_tree)
	ConsoleWrite('Del_TV: ' & _GUICtrlTreeView_DeleteAll($hTV) & @CR)
	_clear_info();

	$USB_ObjCol = ObjGet("winmgmts:")
	$USB_ColItems = $USB_ObjCol.instancesof("CIM_USBDevice");
	If @error Then
		MsgBox(0, "", "Error at getting object. Error code: " & @error)
		Return
	EndIf
	$i = 0
	For $USB_objItem In $USB_ColItems
		$dev_tree_item[$i] = GUICtrlCreateTreeViewItem($USB_objItem.Caption, $dev_tree);
		GUICtrlSetOnEvent($dev_tree_item[$i], 'dev_tree_itemClick');
		$dev_name[$i] = $USB_objItem.Name
		$dev_caption[$i] = $USB_objItem.Caption
		$dev_description[$i] = $USB_objItem.Description
		$i += 1
	Next
EndFunc   ;==>_get_devices
Func _select_device()
	_clear_info();
	Local $hTV = GUICtrlGetHandle($dev_tree)
	Local $hLV = GUICtrlGetHandle($lst_info)
	$cur_item = _GUICtrlTreeView_GetSelection($hTV)
	$cur_dev_index = _GUICtrlTreeView_Index($hTV, $cur_item)
	_GUICtrlListView_AddItem($hLV, 'Device name:', 0)
	_GUICtrlListView_AddSubItem($hLV, 0, $dev_name[$cur_dev_index], 1);
	_GUICtrlListView_AddItem($hLV, 'Caption:', 0)
	_GUICtrlListView_AddSubItem($hLV, 1, $dev_caption[$cur_dev_index], 1);
	_GUICtrlListView_AddItem($hLV, 'Description:', 0)
	_GUICtrlListView_AddSubItem($hLV, 2, $dev_description[$cur_dev_index], 1);
	;   Autosize column width.
	_GUICtrlListView_SetColumnWidth($hLV, 0, $LVSCW_AUTOSIZE);
	_GUICtrlListView_SetColumnWidth($hLV, 1, $LVSCW_AUTOSIZE);
	_GUICtrlListView_EndUpdate($hLV);
EndFunc   ;==>_select_device
Func _clear_info()
	; Delete all items fron info list.
	Local $hLV = GUICtrlGetHandle($lst_info)
	ConsoleWrite('Del_LV: ' & _GUICtrlListView_DeleteAllItems($hLV) & @CR)
EndFunc   ;==>_clear_info
Func btn_exitClick()
	_exit()
EndFunc   ;==>btn_exitClick
Func btn_refreshClick()
	Local $hTV = GUICtrlGetHandle($dev_tree)
	$a = _GUICtrlTreeView_SetState($hTV, _GUICtrlTreeView_GetSelection($hTV), $TVIS_SELECTED, True)
	ConsoleWrite($a & ':::' & _GUICtrlTreeView_GetSelection($hTV) & @CRLF)
	_get_devices();
	_clear_info();
EndFunc   ;==>btn_refreshClick
Func dev_tree_itemClick()
	Local $hTV = GUICtrlGetHandle($dev_tree)
	ConsoleWrite("Item click! Selected:" & _GUICtrlTreeView_Index($hTV, _GUICtrlTreeView_GetSelection($hTV)) & @CRLF)
	_select_device()
EndFunc   ;==>dev_tree_itemClick
Func MainFormClose()
	_exit()
EndFunc   ;==>MainFormClose
Func _exit()
	Exit
EndFunc   ;==>_exit
 
Автор
V

Vitorrio

Новичок
Сообщения
8
Репутация
0
madmasles

Странно, но у меня этот код не работает, точнее сказать работает точно так же как и мой вариант.
Тобишь ListView очищается только после второго нажатия...
Причём, если выделить последнюю позицию в TreeView то всё ok...
:wacko:

Добавьте
Код:
ConsoleWrite('Device selected.' & @CR)
в функцию _select_device(),
в окне консли это будет видно, после нажатия на кнопку "Обновить" эта функция вызывается n количестко раз. Вопрос почему это происходит... :scratch:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
Потому что с ListView лучше работать через WM_NOTIFY. Вот пример.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,665
Репутация
2,463
Проблема действительно есть, вот упростил немного(?):

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

Global $dev_tree_item[6] = [5], $lv_item = 0

$MainForm_1 = GUICreate("USB Info", 628, 261)
$btn_exit = GUICtrlCreateButton("Exit", 550, 230, 76, 26)
$btn_refresh = GUICtrlCreateButton("Refresh", 290, 230, 75, 26)
$dev_tree = GUICtrlCreateTreeView(5, 5, 281, 251)
$lst_info = GUICtrlCreateListView("Param|Value", 290, 40, 336, 186)

GUISetState(@SW_SHOW)
_get_devices()

While 1
	$nMsg = GUIGetMsg()
	
	Switch $nMsg
		Case 0
			ContinueLoop
		Case $GUI_EVENT_CLOSE, $btn_exit
			Exit
		Case $btn_refresh
			_get_devices()
			MsgBox(0, 'Test', '_get_devices done...')
		Case $dev_tree_item[1] To $dev_tree_item[$dev_tree_item[0]]
			MsgBox(0, 'Test', GUICtrlRead($nMsg, 1))
			_select_device()
	EndSwitch
WEnd

Func _get_devices()
	; Clear device list.
	For $i = 1 To 5
		GUICtrlDelete($dev_tree_item[$i])
	Next
	
	; Delete all items fron info list.
	GUICtrlDelete($lv_item)
	
	For $i = 1 To 5
		$dev_tree_item[$i] = GUICtrlCreateTreeViewItem("Device #" & $i, $dev_tree)
	Next
EndFunc

Func _select_device()
	GUICtrlDelete($lv_item)
	$lv_item = GUICtrlCreateListViewItem("Some device", $lst_info)
EndFunc


После создания последнего элемента, почему то срабатывает событие созданных элементов.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,320
Странно, но у меня код из моего поста работает нормально и на XP 32, и на 7 32. Добавил в функцию _select_device()
Код:
ConsoleWrite('Device selected.' & @CR)
Она отрабатывает у меня один раз. :wacko:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
Это легко исправить.

Код:
Func _get_devices()
    ; Clear device list.
    For $i = 1 To 5
        GUICtrlDelete($dev_tree_item[$i])
    Next

    ; Delete all items fron info list.
    GUICtrlDelete($lv_item)

    For $i = 1 To 5
        $dev_tree_item[$i] = GUICtrlCreateTreeViewItem("Device #" & $i, $dev_tree)
    Next

	Do
	Until Not GUIGetMsg()

EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,665
Репутация
2,463
Yashied [?]
Потому что с ListView лучше работать через WM_NOTIFY
Только здесь работа с TreeView...
Действительно через WM_NOTIFY проблема не наблюдается:

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

Global $dev_tree_item[6] = [5], $lv_item = 0

$MainForm_1 = GUICreate("USB Info", 628, 261)
$btn_exit = GUICtrlCreateButton("Exit", 550, 230, 76, 26)
$btn_refresh = GUICtrlCreateButton("Refresh", 290, 230, 75, 26)
$dev_tree = GUICtrlCreateTreeView(5, 5, 281, 251)
$lst_info = GUICtrlCreateListView("Param|Value", 290, 40, 336, 186)

$nDummy = GUICtrlCreateDummy()

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)
_get_devices()

While 1
	$nMsg = GUIGetMsg()
	
	Switch $nMsg
		Case 0
			ContinueLoop
		Case $GUI_EVENT_CLOSE, $btn_exit
			Exit
		Case $btn_refresh
			_get_devices()
			MsgBox(0, 'Test', '_get_devices done...')
		Case $nDummy
			_select_device()
			MsgBox(0, 'Test', GUICtrlRead($dev_tree, 1) & " clicked...")
	EndSwitch
WEnd

Func _get_devices()
	; Clear device list.
	For $i = 1 To 5
		GUICtrlDelete($dev_tree_item[$i])
	Next
	
	; Delete all items fron info list.
	GUICtrlDelete($lv_item)
	
	For $i = 1 To 5
		$dev_tree_item[$i] = GUICtrlCreateTreeViewItem("Device #" & $i, $dev_tree)
	Next
EndFunc

Func _select_device()
	GUICtrlDelete($lv_item)
	$lv_item = GUICtrlCreateListViewItem("Some device", $lst_info)
EndFunc

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeview
    $hWndTreeview = $dev_tree
    If Not IsHWnd($dev_tree) Then $hWndTreeview = GUICtrlGetHandle($dev_tree)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
	
    Switch $hWndFrom
        Case $hWndTreeview
            Switch $iCode
				Case $NM_CLICK, $TVN_KEYDOWN ;, $TVN_SELCHANGEDA, $TVN_SELCHANGEDW
					GUICtrlSendToDummy($nDummy)
            EndSwitch
    EndSwitch
    
	Return $GUI_RUNDEFMSG
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,665
Репутация
2,463
Yashied [?]
Это легко исправить.
Да, но этого быть не должно, я не помню чтобы встречал подобные проблемы, мне никогда не приходилось так обходить подобные события :-\.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
Я работаю с ListView и TreeView только через WM_NOTIFY, поэтому тоже не сталкивался.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,716
CreatoR сказал(а):
Да, но этого быть не должно...

Активируются элементы от выделенного и до конца. Почему? Когда ты удаляешь выделенный элемент, выделение автоматически "перескакивает" на следующий элемент и т.д. И как следствие, все они активируются. Решение: удалять выделенный элемент в последнюю очередь. Как-то так:

Код:
Func _get_devices()
	Local $Sel = GUICtrlRead($dev_tree)
	For $i = 1 To 5
		If $dev_tree_item[$i] <> $Sel Then
			GUICtrlDelete($dev_tree_item[$i])
		EndIf
	Next
	If $Sel Then
		GUICtrlDelete($Sel)
	EndIf
    GUICtrlDelete($lv_item)
    For $i = 1 To 5
        $dev_tree_item[$i] = GUICtrlCreateTreeViewItem("Device #" & $i, $dev_tree)
    Next
EndFunc
 
Автор
V

Vitorrio

Новичок
Сообщения
8
Репутация
0
Да, действительно, вчера пробовал удалять по одной позиции с паузой и заметил что выделение автоматом падает на следующую позицию вTreeView и соответственно срабатывает событие *Click.
Очередной баг в UDF...

Проблему решил, по совету Yashied, пришлось писать отдельную процедуру на очистку TreeView,
удаляя выделенный элемент последним, вроде работает без глюков.

Yashied, CreatoR, madmasles
Всем большое спасибо!!!!!!!!
:beer:
 
Автор
V

Vitorrio

Новичок
Сообщения
8
Репутация
0
Это не UDF, это AutoIt.
Согласен, GUICtrlDelete() работает так же...

И я не уверен, что это баг.
:scratch: Вызывая одно событие, получаешь в придачу ещё и неконтролируемое другое, которое генерирует третье!
Причём важное, потому как на Click завязана вся процедура...
И как это называется?!
Я тоже не уверен, но тогда это ещё хуже... ;)
 
Верх