Opened 3 years ago
Last modified 3 years ago
#3848 closed Bug
_GUICtrlListView_GetItemTextArray does not return an error for multi-column listview if no row is selected. — at Initial Version
Reported by: | BugFix | Owned by: | |
---|---|---|---|
Milestone: | 3.3.15.5 | Component: | Standard UDFs |
Version: | 3.3.14.5 | Severity: | None |
Keywords: | Cc: |
Description
I had written a function _GUICtrlListView_SetItemTextArray as a counterpart to _GUICtrlListView_GetItemTextArray.
In doing so, I noticed that it was not possible to determine if _GUICtrlListView_GetItemTextArray was successful. In the help it says:
Failure: Array with the following format: [0] - Number of Columns in array (0).
This is only correct for the case of a listview with one column. Otherwise an empty array with column count +1 elements is returned: [iCount, '', '', ..]. But this cannot be distinguished from a valid empty array (row could be empty).
This is caused by the function _GUICtrlListView_GetItemTextString. In this function, if -1 is passed as index, the index of the selected row is used. This is returned by _GUICtrlListView_GetNextItem. However, if no line is marked, the return is -1.
Since this value is not checked, the queries of all (sub)items for index -1 are now executed with _GUICtrlListView_GetItemText. This causes empty strings and data separators to be strung together.
The result, although false, is returned without error detection.
In my modifications (_GUICtrlListView_GetItemTextArray_MOD, _GUICtrlListView_GetItemTextString_MOD) I have integrated the index check and thus it can be determined whether _GUICtrlListView_GetItemTextArray() was successful. (see my test script)
In general, I think it is recommended that all functions that work with indexes also check them for validity. Many functions call each other and the user has no possibility to check their result and find sources of errors.
Code highlighting:
#include <GuiListView.au3> #include <GUIConstants.au3> #include <WindowsConstants.au3> #include <Array.au3> $gui = GUICreate('Test') $lv = GuiCtrlCreateListView('a|b|c', 10, 10, 350, 250) For $i = 1 To 30 GUICtrlCreateListViewItem(StringFormat('%d|%d|%d', $i-1, Random(1,10,1), Random(1,10,1)), $lv) Next $hLV = GUICtrlGetHandle($lv) _GUICtrlListView_SetExtendedListViewStyle($hLV, BitOR($LVS_EX_FULLROWSELECT,$WS_EX_CLIENTEDGE,$LVS_EX_GRIDLINES)) _GUICtrlListView_SetColumnWidth($hLV, 0, 85) _GUICtrlListView_SetColumnWidth($hLV, 1, 85) _GUICtrlListView_SetColumnWidth($hLV, 2, $LVSCW_AUTOSIZE_USEHEADER) $bt1 = GUICtrlCreateButton('Set selected to 3', 10, 280, 120, 24) $bt2 = GUICtrlCreateButton('Set 5 to selected', 140, 280, 120, 24) $btRemove = GUICtrlCreateButton('Remove Selection', 270, 280, 120, 24) $cb = GUICtrlCreateCheckbox(' Use functions with Index check!', 10, 320) $bCheck = False GUISetState() $f = _GUICtrlListView_GetItemTextArray $fCheck = _GUICtrlListView_GetItemTextArray_MOD While True $bCheck = BitAND(GUICtrlRead($cb), $GUI_CHECKED) ? True : False Switch GUIGetMsg() Case -3 Exit Case $bt1 If _GUICtrlListView_SetItemTextArray($hLV, ($bCheck ? $fCheck($hLV) : $f($hLV)), 3) <> 1 Then _ MsgBox(0, 'Error', 'None Selection') Case $bt2 If _GUICtrlListView_SetItemTextArray($hLV, ($bCheck ? $fCheck($hLV, 5) : $f($hLV, 5))) <> 1 Then _ MsgBox(0, 'Error', 'None Selection') Case $btRemove _GUICtrlListView_SetItemSelected($hLV, _GUICtrlListView_GetNextItem($hLV), False, False) EndSwitch WEnd ; #FUNCTION# ==================================================================================================================== ; Author ........: Gary Frost (gafrost) ; Modified.......: @BugFix ; =============================================================================================================================== Func _GUICtrlListView_GetItemTextArray_MOD($hWnd, $iItem = -1) ;~ Local $sItems = _GUICtrlListView_GetItemTextString($hWnd, $iItem) ; Here occurs the error. This function produces a wrong output without @error. ; i.e.: listview with 3 columns, none selection but "$iItem = -1" - should use the current selection ; $sItems = "||", none error! Local $sItems = _GUICtrlListView_GetItemTextString_MOD($hWnd, $iItem) If $sItems = "" Then Local $aItems[1] = [0] Return SetError($LV_ERR, $LV_ERR, $aItems) EndIf Return StringSplit($sItems, Opt('GUIDataSeparatorChar')) EndFunc ;==>_GUICtrlListView_GetItemTextArray ; #FUNCTION# ==================================================================================================================== ; Author ........: Gary Frost (gafrost) ; Modified.......: @BugFix ; =============================================================================================================================== Func _GUICtrlListView_GetItemTextString_MOD($hWnd, $iItem = -1) Local $sRow = "", $sSeparatorChar = Opt('GUIDataSeparatorChar'), $iSelected If $iItem = -1 Then ; '$iItem = -1' says: use the current selection $iSelected = _GUICtrlListView_GetNextItem($hWnd) ; get current row selected ; But this function returns also "-1" if none item is selected Else $iSelected = $iItem ; get row EndIf ; here is required to check if _GUICtrlListView_GetNextItem() has failed If $iSelected < 0 Or $iSelected > _GUICtrlListView_GetItemCount($hWnd) - 1 Then Return SetError(1,0,0) For $x = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1 ; _GUICtrlListView_GetItemText() it does not matter at all whether a valid index was passed. ; In case of error there is no message and an empty string is returned. This cannot be distinguished from an actually empty item. ; For this reason, a wrong index must be caught before calling the function. $sRow &= _GUICtrlListView_GetItemText($hWnd, $iSelected, $x) & $sSeparatorChar Next Return StringTrimRight($sRow, 1) EndFunc ;==>_GUICtrlListView_GetItemTextString