Jump to content
Sign in to follow this  
Armag3ddon

Sorting Treeview created via UDF

Recommended Posts

Armag3ddon

Hi!

I try to sort a treeview with a sort function. I got a solution from the forum, it's here:

I copied _GUICtrlTreeView_Sort

Problem is, this only works when the treeview control was created using GUICtrlCreateTreeView like in Authenticity's example. I use a treeview that was created via _GUICtrlTreeView_Create. I can't figure out what the problem is resp. what I need to change.

Can anyone help?

I've attached Authenticity's example script, modified so it uses _GUICtrlTreeView_Create. I added ConsoleWrite in the _CompareFunc which shows what the problem is: Both ilParam and ilParam2 are 0 when the function is called.

#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GuiTreeView.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars', 1)
$Debug_TV = False ; Check ClassName being passed to functions, set to True and use a handle to another control to see it work
Global Const $TVSORTCB = "ptr Parent;ptr Compare;lparam SortParam;"
_Main()
Func _Main()
    Local $hItem[10], $hChildItem[30], $hGrandChildItem[90], $hGrandGrantChildItem[180]
    Local $iCItem = 0, $iGCItem = 0, $IGGCItem = 0, $i1 = 10, $i2 = 30, $i3 = 90, $i4 = 180
    Local $hWnd, $hTreeView, $hFunc
    Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS)
    $hWNd = GUICreate("TreeView Sort", 400, 300)
    $hTreeView = _GUICtrlTreeView_Create($hWnd, 2,2, 396,268, $iStyle, $WS_EX_CLIENTEDGE)
    _GUICtrlTreeView_SetUnicodeFormat($hTreeView, True)
    GUISetState()
    _GUICtrlTreeView_BeginUpdate($hTreeView)
    For $a = 0 To 9
        $hItem[$a] = _GUICtrlTreeView_Add($hTreeView, $hTreeView, StringFormat("[%02d] New Item", $i1))
        For $b = 1 To 3
            $hChildItem[$iCItem] = _GUICtrlTreeView_AddChild($hTreeView, $hItem[$a], StringFormat("[%02d] New Child", $i2))
            For $c = 1 To 3
                $hGrandChildItem[$iGCItem] = _GUICtrlTreeView_AddChild($hTreeView, $hChildItem[$iCItem], StringFormat("[%02d] New Grandchild", $i3))
                For $d = 1 To 2
                    $hGrandGrantChildItem[$IGGCItem] = _GUICtrlTreeView_AddChild($hTreeView, $hGrandChildItem[$iGCItem], StringFormat("[%02d] New GrandGrandChild", $i4))
                    $IGGCItem += 1
                    $i4 -= 1
                Next
                $iGCItem += 1
                $i3 -= 1
            Next
            $iCItem += 1
            $i2 -= 1
        Next
        $i1 -= 1
    Next
    _GUICtrlTreeView_Expand($hTreeView)
    _GUICtrlTreeView_EndUpdate($hTreeView)
    _GUICtrlTreeView_SelectItem($hTreeView, $hItem[0])
    $hFunc = DllCallbackRegister("_CompareFunc", "int", "lparam;lparam;lparam")
    MsgBox(4160, "Information", "Sorting ascending")
    _GUICtrlTreeView_BeginUpdate($hTreeView)
    __GUICtrlTreeView_Sort($hTreeView, $hFunc)
    _GUICtrlTreeView_EndUpdate($hTreeView)
    _GUICtrlTreeView_SelectItem($hTreeView, $hItem[9])
    MsgBox(4160, "Information", "Sorting descending")
    _GUICtrlTreeView_BeginUpdate($hTreeView)
    __GUICtrlTreeView_Sort($hTreeView, $hFunc, False)
    _GUICtrlTreeView_EndUpdate($hTreeView)
    _GUICtrlTreeView_SelectItem($hTreeView, $hItem[0])
    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    DllCallbackFree($hFunc)
    GUIDelete()
EndFunc   ;==>_Main
Func _CompareFunc($ilParam1, $ilParam2, $fAscending)
ConsoleWrite("ilParam: " & $ilParam1 & " | ilParam2: " & $ilParam2)
ConsoleWrite(@CRLF)
    Local $sText1, $sText2, $iCompare
    $sText1 = GUICtrlRead($ilParam1, 1)
    $sText2 = GUICtrlRead($ilParam2, 1)
    $iCompare = StringCompare($sText1, $sText2) ; case-insensitive
    If $fAscending Then ; Ascending case
        If $iCompare < 0 Then ; Text1 < Text2 so return -1 (Item1 should precede Item2)
            Return -1
        ElseIf $iCompare > 0 Then ; Text2 < Text1 so return 1 (Item2 should precede Item1)
            Return 1
        Else ; Text1 = Text2 so return 0 (don't swap)
            Return 0
        EndIf
    Else ; Descending case
        If $iCompare > 0 Then ; Text1 > Text2 so return -1 (Item1 should precede Item2)
            Return -1
        ElseIf $iCompare < 0 Then ; Text2 > Text1 so return 1 (Item2 should precede Item1)
            Return 1
        Else ; Text1 = Text2 so return 0 (don't swap)
            Return 0
        EndIf
    EndIf
EndFunc ; _CompareFunc
Func __GUICtrlTreeView_Sort($hWnd, $hFunc, $fAscending = True)
    If $Debug_TV Then __UDF_ValidateClassName($hWnd, $__TREEVIEWCONSTANT_ClassName)
    Local $pFunc = DllCallbackGetPtr($hFunc)
    If $pFunc = 0 Then Return SetError(1, 0, False)
    Local $tSort, $pSort
    $tSort = DllStructCreate($TVSORTCB)
    $pSort = DllStructGetPtr($tSort)
    ; lparam = 1 sort ascending
    ; lparam = 0 sort descending
    DllStructSetData($tSort, "SortParam", $fAscending) ; It's up to the callback function to do whatever it wants to do with SortParam
    DllStructSetData($tSort, "Compare", $pFunc)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Local $hItem = _SendMessage($hWnd, $TVM_GETNEXTITEM, $TVGN_CHILD, $TVI_ROOT, 0, "wparam", "handle", "handle")
    If Not $hItem Then Return
    While $hItem
        If _GUICtrlTreeView_GetChildren($hWnd, $hItem) Then
            DllStructSetData($tSort, "Parent", $hItem)
            _SendMessage($hWnd, $TVM_SORTCHILDRENCB, 0, $pSort, 0, "wparam", "ptr")
        EndIf
        $hItem = _GUICtrlTreeView_GetNext($hWnd, $hItem)
    WEnd
    DllStructSetData($tSort, "Parent", $TVI_ROOT)
    _SendMessage($hWnd, $TVM_SORTCHILDRENCB, 0, $pSort, 0, "wparam", "ptr")
    Return SetError(0, 0, True)
EndFunc

Share this post


Link to post
Share on other sites
Armag3ddon

Bump. No one has any idea? ;)

Share this post


Link to post
Share on other sites
Armag3ddon

Oops, sorry. Won't happen again.

Share this post


Link to post
Share on other sites
Yashied

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GuiTreeView.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars', 1)
$Debug_TV = False ; Check ClassName being passed to functions, set to True and use a handle to another control to see it work
Global Const $TVSORTCB = "ptr Parent;ptr Compare;lparam SortParam;"

Global $Data[500]

_Main()

Func _Main()
    Local $hItem[10], $hChildItem[30], $hGrandChildItem[90], $hGrandGrantChildItem[180]
    Local $iCItem = 0, $iGCItem = 0, $IGGCItem = 0, $i1 = 10, $i2 = 30, $i3 = 90, $i4 = 180
    Local $hWnd, $hTreeView, $hFunc
    Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS)
    $hWnd = GUICreate("TreeView Sort", 400, 300)
    $hTreeView = _GUICtrlTreeView_Create($hWnd, 2, 2, 396, 268, $iStyle, $WS_EX_CLIENTEDGE)
    _GUICtrlTreeView_SetUnicodeFormat($hTreeView, True)
    GUISetState()
    _GUICtrlTreeView_BeginUpdate($hTreeView)
    Local $Count = 0
    For $a = 0 To 9
        $Data[$Count] = StringFormat("[%02d] New Item", $i1)
        $hItem[$a] = _GUICtrlTreeView_Add($hTreeView, $hTreeView, $Data[$Count])
        _GUICtrlTreeView_SetItemParam($hTreeView, $hItem[$a], $Count)
        $Count += 1
        For $b = 1 To 3
            $Data[$Count] = StringFormat("[%02d] New Child", $i2)
            $hChildItem[$iCItem] = _GUICtrlTreeView_AddChild($hTreeView, $hItem[$a], $Data[$Count])
            _GUICtrlTreeView_SetItemParam($hTreeView, $hChildItem[$iCItem], $Count)
            $Count += 1
            For $c = 1 To 3
                $Data[$Count] = StringFormat("[%02d] New Grandchild", $i3)
                $hGrandChildItem[$iGCItem] = _GUICtrlTreeView_AddChild($hTreeView, $hChildItem[$iCItem], $Data[$Count])
                _GUICtrlTreeView_SetItemParam($hTreeView, $hGrandChildItem[$iGCItem], $Count)
                $Count += 1
                For $d = 1 To 2
                    $Data[$Count] = StringFormat("[%02d] New GrandGrandChild", $i4)
                    $hGrandGrantChildItem[$IGGCItem] = _GUICtrlTreeView_AddChild($hTreeView, $hGrandChildItem[$iGCItem], $Data[$Count])
                    _GUICtrlTreeView_SetItemParam($hTreeView, $hGrandGrantChildItem[$IGGCItem], $Count)
                    $Count += 1
                    $IGGCItem += 1
                    $i4 -= 1
                Next
                $iGCItem += 1
                $i3 -= 1
            Next
            $iCItem += 1
            $i2 -= 1
        Next
        $i1 -= 1
    Next
    _GUICtrlTreeView_Expand($hTreeView)
    _GUICtrlTreeView_EndUpdate($hTreeView)
    _GUICtrlTreeView_SelectItem($hTreeView, $hItem[0])
    $hFunc = DllCallbackRegister("_CompareFunc", "int", "lparam;lparam;lparam")
    MsgBox(4160, "Information", "Sorting ascending")
    _GUICtrlTreeView_BeginUpdate($hTreeView)
    __GUICtrlTreeView_Sort($hTreeView, $hFunc)
    _GUICtrlTreeView_EndUpdate($hTreeView)
    _GUICtrlTreeView_SelectItem($hTreeView, $hItem[9])
    MsgBox(4160, "Information", "Sorting descending")
    _GUICtrlTreeView_BeginUpdate($hTreeView)
    __GUICtrlTreeView_Sort($hTreeView, $hFunc, False)
    _GUICtrlTreeView_EndUpdate($hTreeView)
    _GUICtrlTreeView_SelectItem($hTreeView, $hItem[0])
    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    DllCallbackFree($hFunc)
    GUIDelete()
EndFunc   ;==>_Main
Func _CompareFunc($ilParam1, $ilParam2, $fAscending)
    ConsoleWrite("ilParam: " & $ilParam1 & " | ilParam2: " & $ilParam2)
    ConsoleWrite(@CRLF)
    Local $sText1, $sText2, $iCompare
    $sText1 = $Data[$ilParam1]
    $sText2 = $Data[$ilParam2]
    $iCompare = StringCompare($sText1, $sText2) ; case-insensitive
    If $fAscending Then ; Ascending case
        If $iCompare < 0 Then ; Text1 < Text2 so return -1 (Item1 should precede Item2)
            Return -1
        ElseIf $iCompare > 0 Then ; Text2 < Text1 so return 1 (Item2 should precede Item1)
            Return 1
        Else ; Text1 = Text2 so return 0 (don't swap)
            Return 0
        EndIf
    Else ; Descending case
        If $iCompare > 0 Then ; Text1 > Text2 so return -1 (Item1 should precede Item2)
            Return -1
        ElseIf $iCompare < 0 Then ; Text2 > Text1 so return 1 (Item2 should precede Item1)
            Return 1
        Else ; Text1 = Text2 so return 0 (don't swap)
            Return 0
        EndIf
    EndIf
EndFunc   ;==>_CompareFunc
Func __GUICtrlTreeView_Sort($hWnd, $hFunc, $fAscending = True)
    If $Debug_TV Then __UDF_ValidateClassName($hWnd, $__TREEVIEWCONSTANT_ClassName)
    Local $pFunc = DllCallbackGetPtr($hFunc)
    If $pFunc = 0 Then Return SetError(1, 0, False)
    Local $tSort, $pSort
    $tSort = DllStructCreate($TVSORTCB)
    $pSort = DllStructGetPtr($tSort)
    ; lparam = 1 sort ascending
    ; lparam = 0 sort descending
    DllStructSetData($tSort, "SortParam", $fAscending) ; It's up to the callback function to do whatever it wants to do with SortParam
    DllStructSetData($tSort, "Compare", $pFunc)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Local $hItem = _SendMessage($hWnd, $TVM_GETNEXTITEM, $TVGN_CHILD, $TVI_ROOT, 0, "wparam", "handle", "handle")
    If Not $hItem Then Return
    While $hItem
        If _GUICtrlTreeView_GetChildren($hWnd, $hItem) Then
            DllStructSetData($tSort, "Parent", $hItem)
            _SendMessage($hWnd, $TVM_SORTCHILDRENCB, 0, $pSort, 0, "wparam", "ptr")
        EndIf
        $hItem = _GUICtrlTreeView_GetNext($hWnd, $hItem)
    WEnd
    DllStructSetData($tSort, "Parent", $TVI_ROOT)
    _SendMessage($hWnd, $TVM_SORTCHILDRENCB, 0, $pSort, 0, "wparam", "ptr")
    Return SetError(0, 0, True)
EndFunc   ;==>__GUICtrlTreeView_Sort

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×