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
Armag3ddon

Bump.

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
Armag3ddon

Yay! Thanks! ;)

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  

×