Sign in to follow this  
Followers 0
-Ultima-

_GUICtrlListViewSetItemText() set all text with one function call

1 post in this topic

#1 ·  Posted (edited)

I was trying to use _GUICtrlListViewSetItemText() to set the text for an entire listview item in one shot (without needing to call the function multiple times), but I found that it wasn't possible, and would require a loop in my script. I ended up modifying the function directly, and it feels at least a bit more more... elegant (even though it's still more-or-less identical in implementation -- just moved to a location more transparent to the people using the function). The point is that _GUICtrlListViewSetItemText(), as is, doesn't sound like it's explicitly used only for setting one subitem only, and in fact, sounds more like it's supposed to be used for setting an entire listview item's text. With the current behavior requiring that you specify a subitem's index, it sounds like it should be named _GUICtrlListViewSetSubItemText() instead :)

The change was pretty simple: if $i_SubItem is -1, it'll indicate to _GUICtrlListViewSetItemText() that the user wants to set the entire listview item's text. Accordingly, the function will take $s_text and split it using the vertical pipe ("|") as the delimiter, then call itself recursively (but this time, setting $i_SubItem properly).

@gafrost (if you read this): Ignoring any possible glitches with the code itself (doubtful that there would be), is there any chance that at least the idea can be incorporated into the official UDF?

  • I think the change itself is pretty harmless, and adds a fair amount of functionality
  • From a logical standpoint, it makes the function more natural to use, and more encompassing, since the function would actually do what its name makes it sound like it does -- without breaking backwards compatibility
  • It'd make the function a nicer counterpart for _GUICtrlListViewGetItemText(), since the $i_SubItem is optional in that function as well (and if $i_SubItem is -1 in that function, it returns a pipe-delimited list of the subitems too)
(It'd also mean that I wouldn't have to keep a duplicate function in my script, or that I wouldn't have to remember to edit GuiListView.au3 at least once for every time I update AutoIt, but that's something that affects only me xD)

Func _GUICtrlListViewSetItemText($h_listview, $i_index, $i_SubItem, $s_text)
    If Not _IsClassName ($h_listview, "SysListView32") Then Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
    Local $ret
    Local $struct_LVITEM = DllStructCreate($LVITEM)
    If @error Then Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
    Local $struct_String = DllStructCreate("char[" & StringLen($s_text) + 1 & "]")
    If @error Then Return SetError($LV_ERR, $LV_ERR, $LV_ERR)

; START - MY ADDITION
    If $i_SubItem = -1 Then
        Local $i_cols = _GUICtrlListViewGetSubItemsCount($h_listview)
        Local $a_text = StringSplit($s_text, "|")
        If $i_cols > $a_text[0] Then $i_cols = $a_text[0]
        For $i = 1 To $i_cols
            $ret = _GUICtrlListViewSetItemText($h_listview, $i_index, $i - 1, $a_text[$i])
            If Not $ret Then ExitLoop
        Next
        Return $ret
    EndIf
; END - MY ADDITION

    DllStructSetData($struct_String, 1, $s_text)
    DllStructSetData($struct_LVITEM, $LVI_MASK, $LVIF_TEXT)
    DllStructSetData($struct_LVITEM, $LVI_IITEM, $i_index)
    DllStructSetData($struct_LVITEM, $LVI_ISUBITEM, $i_SubItem)
    If IsHWnd($h_listview) Then
        Local $sBuffer_pointer = DllStructGetPtr($struct_String)
        Local $LVITEM_pointer = DllStructGetPtr($struct_LVITEM)
        Local $i_Size = DllStructGetSize($struct_LVITEM)
        Local $struct_MemMap
        Local $Memory_pointer = _MemInit ($h_listview, $i_Size + StringLen($s_text) + 1, $struct_MemMap)
        If @error Then
            _MemFree ($struct_MemMap)
            Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
        EndIf
        Local $string_Memory_pointer = $Memory_pointer + $i_Size
        DllStructSetData($struct_LVITEM, $LVI_PSZTEXT, $string_Memory_pointer)
        If @error Then
            _MemFree ($struct_MemMap)
            Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
        EndIf
        _MemWrite ($struct_MemMap, $LVITEM_pointer)
        If @error Then
            _MemFree ($struct_MemMap)
            Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
        EndIf
        _MemWrite ($struct_MemMap, $sBuffer_pointer, $string_Memory_pointer, StringLen($s_text) + 1)
        If @error Then
            _MemFree ($struct_MemMap)
            Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
        EndIf
        $ret = _SendMessage($h_listview, $LVM_SETITEMTEXTA, 0, $Memory_pointer)
        If @error Then
            _MemFree ($struct_MemMap)
            Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
        EndIf
        _MemFree ($struct_MemMap)
        If @error Then Return SetError($LV_ERR, $LV_ERR, $LV_ERR)
    Else
        DllStructSetData($struct_LVITEM, $LVI_PSZTEXT, DllStructGetPtr($struct_String))
        $ret = GUICtrlSendMsg($h_listview, $LVM_SETITEMTEXTA, $i_index, DllStructGetPtr($struct_LVITEM))
    EndIf
    Return $ret
EndFunc   ;==>_GUICtrlListViewSetItemText
Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

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  
Followers 0