Quantcast
Channel: AutoIt v3 - Developer Chat
Viewing all articles
Browse latest Browse all 750

_GUICtrlListView_SimpleSort, a problem, a solution and a question

$
0
0

Problem

I am trying to sort a list view with checkboxes in descending order. The _GUICtrlListView_SimpleSort function works as intended but upon first sort if all the checkboxes are uncheck when the sort is complete the item that was at index 0 is checked. This seems to be a problem when __GUICtrlListView_GetCheckedIndices used by the simplesort returns a blank\empty result.

 

It's not often I look at the default includes, I'm normally just happy functions work but there is some code in the sorting function in GuiListView.au3 that checks for comparision and if the items match then the checked state is set to True,

For $Z = 1 To $i_checked[0]     If $a_lv[$x][UBound($a_lv, 2) - 1] = $i_checked[$Z] Then     _GUICtrlListView_SetItemChecked($hWnd, $x, True)     ExitLoop    EndIf Next

This comparison is correct as ithe first index (0) matches the __GUICtrlListView_GetCheckedIndices returned string (blank seen as 0) to it is assumed that the checkbox is to be selected.

 

The __GUICtrlListView_GetCheckedIndices seems to be longer than required and uses Redim inside a loop which, from information picked up on the forum, is a not ideal. I have searched on the bug tracker for tickets related to _GUICtrlListView_SimpleSort and they're all closed and the latest beta performs the same, so this may not be a problem. I know that _GUICtrlListView_RegisterSortCallBack sorts checkbox items correctly and the checked state remain the same but this would mean more code and probably my own sorting function to sort desecending by default.

 

My Solution

I have used the simplesort example from the help file and removed code I don't need and have also added __GUICtrlListView_SimpleSort to enable use of a shortened _GUICtrlListView_GetCheckedIndices that does not alter the checkbox state when sorting.

AutoIt         
#include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> $Debug_LV = False ; Check ClassName being passed to ListView functions, set to True and use a handle to another control to see it work Global $hListView _Main() Func _Main()     GUICreate("ListView SimpleSort", 400, 300)     $hListView = GUICtrlCreateListView("col1|col2|col3", 2, 2, 394, 268)     GUICtrlSendMsg($hListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_GRIDLINES, $LVS_EX_GRIDLINES)     GUICtrlSendMsg($hListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_FULLROWSELECT, $LVS_EX_FULLROWSELECT)     GUICtrlSendMsg($hListView, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_CHECKBOXES, $LVS_EX_CHECKBOXES) ; added     GUICtrlCreateListViewItem("line4|5|more_a", $hListView)     GUICtrlCreateListViewItem("line5|4.50 |more_c", $hListView)     GUICtrlCreateListViewItem("line5|4.0 |more_c", $hListView)     GUICtrlCreateListViewItem("line3|23|more_e", $hListView)     GUICtrlCreateListViewItem("line2|0.34560 |more_d", $hListView)     GUICtrlCreateListViewItem("line1|1.0 |more_b", $hListView)     GUICtrlCreateListViewItem("line1|0.1 |more_b", $hListView)     GUICtrlCreateListViewItem("line1|10|more_b", $hListView)     _GUICtrlListView_SetColumnWidth($hListView, 0, 75)     _GUICtrlListView_SetColumnWidth($hListView, 1, 75)     _GUICtrlListView_SetColumnWidth($hListView, 2, 75)     GUISetState()     GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")     Global $B_DESCENDING[_GUICtrlListView_GetColumnCount($hListView)]     ; Loop until user exits     Do     Until GUIGetMsg() = $GUI_EVENT_CLOSE     GUIDelete() EndFunc   ;==>_Main Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)     #forceref $hWnd, $iMsg, $iwParam     Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo     $hWndListView = $hListView     If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)     $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)     $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))     $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")     $iCode = DllStructGetData($tNMHDR, "Code")     Switch $hWndFrom         Case $hWndListView             Switch $iCode                 Case $LVN_COLUMNCLICK ; A column was clicked                     $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam) ;~                  _GUICtrlListView_SimpleSort($hWndListView, $B_DESCENDING, DllStructGetData($tInfo, "SubItem")) ; original help file line                     __GUICtrlListView_SimpleSort($hWndListView, $B_DESCENDING, DllStructGetData($tInfo, "SubItem")) ; line to use reworked function             EndSwitch     EndSwitch     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_NOTIFY ; #FUNCTION# ==================================================================================================================== ; Name...........: _GUICtrlListView_SimpleSort ; Description ...: Sorts a list-view control (limited) ; Syntax.........: _GUICtrlListView_SimpleSort($hWnd, ByRef $vDescending, $iCol) ; Parameters ....: $hWnd        - Handle to the control ;                  $vDescending - Can be: ;                  | True       - Sort Descending ;                  | False      - Sort Ascending ;                  +Array       - With the following format: ;                  |[0]         - First Column ;                  |[1]         - Second Column ;                  |[n]         - Last Column ;                  $iCol        - Column number ; Return values .: None ; Author ........: Gary Frost (gafrost) ; Modified.......: ; Remarks .......: This is a basic sort fuction, for advanced sort see GUICtrlRegisterListViewSort ; Related .......: GUICtrlRegisterListViewSort ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func __GUICtrlListView_SimpleSort($hWnd, ByRef $vDescending, $iCol)     If $Debug_LV Then __UDF_ValidateClassName($hWnd, $__LISTVIEWCONSTANT_ClassName)     If _GUICtrlListView_GetItemCount($hWnd) Then         Local $b_desc         If (IsArray($vDescending)) Then             $b_desc = $vDescending[$iCol]         Else             $b_desc = $vDescending         EndIf         Local $columns = _GUICtrlListView_GetColumnCount($hWnd)         Local $items = _GUICtrlListView_GetItemCount($hWnd)         Local $temp_item = ""         Local $SeparatorChar = Opt('GUIDataSeparatorChar')         For $x = 1 To $columns             $temp_item = $temp_item & " " & $SeparatorChar         Next         $temp_item = StringTrimRight($temp_item, 1)         Local $a_lv[$items][$columns + 1]         Local $i_selected = StringSplit(_GUICtrlListView_GetSelectedIndices($hWnd), $SeparatorChar)         Local $i_checked = _GUICtrlListView_GetCheckedIndices($hWnd, $SeparatorChar) ; new line ;~      Local $i_checked = StringSplit(__GUICtrlListView_GetCheckedIndices($hWnd), $SeparatorChar) ; UDF line         Local $v_item, $iFocused = -1         For $x = 0 To UBound($a_lv) - 1 Step 1             If $iFocused = -1 Then                 If _GUICtrlListView_GetItemFocused($hWnd, $x) Then $iFocused = $x             EndIf             _GUICtrlListView_SetItemSelected($hWnd, $x, False)             _GUICtrlListView_SetItemChecked($hWnd, $x, False)             For $Y = 0 To UBound($a_lv, 2) - 2 Step 1                 $v_item = StringStripWS(_GUICtrlListView_GetItemText($hWnd, $x, $Y), 2)                 If (StringIsFloat($v_item) Or StringIsInt($v_item)) Then                     $a_lv[$x][$Y] = Number($v_item)                 Else                     $a_lv[$x][$Y] = $v_item                 EndIf             Next             $a_lv[$x][$Y] = $x         Next         _ArraySort($a_lv, $b_desc, 0, 0, $iCol)         For $x = 0 To UBound($a_lv) - 1 Step 1             For $Y = 0 To UBound($a_lv, 2) - 2 Step 1                 _GUICtrlListView_SetItemText($hWnd, $x, $a_lv[$x][$Y], $Y)             Next             For $Z = 1 To $i_selected[0]                 If $a_lv[$x][UBound($a_lv, 2) - 1] = $i_selected[$Z] Then                     If $a_lv[$x][UBound($a_lv, 2) - 1] = $iFocused Then                         _GUICtrlListView_SetItemSelected($hWnd, $x, True, True)                     Else                         _GUICtrlListView_SetItemSelected($hWnd, $x, True)                     EndIf                     ExitLoop                 EndIf             Next             For $Z = 1 To $i_checked[0]                 If $a_lv[$x][UBound($a_lv, 2) - 1] = $i_checked[$Z] Then                     _GUICtrlListView_SetItemChecked($hWnd, $x, True)                     ExitLoop                 EndIf             Next         Next         If (IsArray($vDescending)) Then             $vDescending[$iCol] = Not $b_desc         Else             $vDescending = Not $b_desc         EndIf     EndIf EndFunc   ;==>__GUICtrlListView_SimpleSort Func _GUICtrlListView_GetCheckedIndices($hWnd, $sDelim)     If $Debug_LV Then __UDF_ValidateClassName($hWnd, $__LISTVIEWCONSTANT_ClassName)     Local $aIndices[1] = [0] ; empty array for return if no items checked     Local $sIndices = ''     For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1         If _GUICtrlListView_GetItemChecked($hWnd, $i) Then $sIndices &= $i & $sDelim     Next     If Not $sIndices Then Return $aIndices ; return the empty array if the string is blank     Return StringSplit(StringTrimRight($sIndices, StringLen($sDelim)), $sDelim) EndFunc   ;==>_GUICtrlListView_GetCheckedIndices

If there is a better way to do the above using the standard includes?. Searching the forum I found guiness has done a similar function to get checked states here http://www.autoitscript.com/forum/topic/148874-count-listview-checked-items/?p=1059439 and based mine on his.

 

Question

What are the reasons for sending an array as the $B_DESCENDING parameter rather than True\False

 

Thanks


Viewing all articles
Browse latest Browse all 750

Latest Images

Trending Articles



Latest Images