Jump to content
Sign in to follow this  
Sokko

GUI List Operations

Recommended Posts

Sokko

I have a couple of quick questions about working with list controls:

1) I want to have a "Delete Selected Item" button for my list. I've looked all over the help files and found no reference to deleting only a single item. How can I do this?

2) I want to read off the entire contents of a list into an array, but for some reason there doesn't seem to be any function that deals with reading whole lists. Is there really no way to do this or am I just being dense?

Share this post


Link to post
Share on other sites
Gigglestick

1. See _GuiCtrlListDeleteItem in the help.

2. See _GuiCtrlListGetSelItemsText and _GuiCtrlListGetSelItems in the help for an array of the selected items or their indices.

These are both in the latest beta. I'm not sure about the latest release, but I have a feeling they're in there.

Edited by c0deWorm

My UDFs: ExitCodes

Share this post


Link to post
Share on other sites
GaryFrost

I have a couple of quick questions about working with list controls:

1) I want to have a "Delete Selected Item" button for my list. I've looked all over the help files and found no reference to deleting only a single item. How can I do this?

_GUICtrlListDeleteItem

2) I want to read off the entire contents of a list into an array, but for some reason there doesn't seem to be any function that deals with reading whole lists. Is there really no way to do this or am I just being dense?

<{POST_SNAPBACK}>

_GUICtrlListGetSelItemsText

Return Value

Array of selected items text, first element ($array[0]) contains the number items returned

these user defined functions are available in the beta.


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites
Sokko

Correction: Is there any way to do these things without mucking around in beta? Even if it's really complicated, having it work with the most recent stable release would be infinitely preferable. Thanks!

Share this post


Link to post
Share on other sites
GaryFrost

Const $LB_DELETESTRING = 0x182
GUICtrlSendMsg($h_listbox, $LB_DELETESTRING, $i_index, 0)

Const $LB_ERR = -1
Const $LB_GETCOUNT = 0x18B
Const $LB_GETSEL = 0x0187
Const $LB_GETTEXT = 0x0189

Func _GUICtrlListGetSelItemsText($h_listbox)
    Local $i, $s_list = "", $i_ret
    For $i = 0 To GUICtrlSendMsg($h_listbox, $LB_GETCOUNT, 0, 0) - 1
        $i_ret = GUICtrlSendMsg($h_listbox, $LB_GETSEL, $i, 0)
        If ($i_ret > 0) Then
            If (StringLen($s_list) > 0) Then
                $s_list = $s_list & ',' & $i
            Else
                $s_list = $i
            EndIf
        ElseIf ($i_ret == $LB_ERR) Then
            Return $LB_ERR
        EndIf
    Next;$s_list should now equal the selected items
    
    If (StringLen($s_list) > 0) Then
        Local $a_text = StringSplit($s_list, ",")
        For $i = 1 To $a_text[0]
            $a_text[$i] = GUICtrlRecvMsg($h_listbox, $LB_GETTEXT, $a_text[$i], 1)
        Next
        Return $a_text
    Else
        Return $LB_ERR
    EndIf
EndFunc  ;==>_GUICtrlListGetSelItemsText

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites
Sokko

Okay, now I'm really confused.

Const $LB_DELETESTRING = 0x182
GUICtrlSendMsg($h_listbox, $LB_DELETESTRING, $i_index, 0)

This seems to require an "index" that I don't know how to get. It does work when I replace the variable with an integer, but of course that doesn't help me if I want to delete whatever the currently-selected item is.

Const $LB_ERR = -1
Const $LB_GETCOUNT = 0x18B
Const $LB_GETSEL = 0x0187
Const $LB_GETTEXT = 0x0189

Func _GUICtrlListGetSelItemsText($h_listbox)
    Local $i, $s_list = "", $i_ret
    For $i = 0 To GUICtrlSendMsg($h_listbox, $LB_GETCOUNT, 0, 0) - 1
        $i_ret = GUICtrlSendMsg($h_listbox, $LB_GETSEL, $i, 0)
        If ($i_ret > 0) Then
            If (StringLen($s_list) > 0) Then
                $s_list = $s_list & ',' & $i
            Else
                $s_list = $i
            EndIf
        ElseIf ($i_ret == $LB_ERR) Then
            Return $LB_ERR
        EndIf
    Next;$s_list should now equal the selected items
    
    If (StringLen($s_list) > 0) Then
        Local $a_text = StringSplit($s_list, ",")
        For $i = 1 To $a_text[0]
            $a_text[$i] = GUICtrlRecvMsg($h_listbox, $LB_GETTEXT, $a_text[$i], 1)
        Next
        Return $a_text
    Else
        Return $LB_ERR
    EndIf
EndFunc  ;==>_GUICtrlListGetSelItemsText

From the comment, it looks like this function is for dealing with selected items. It looks like it would work, but A) There is no function for selecting items in the first place, and B) You can only select one item at a time, and I haven't found a style that changes this. I tried manually selecting a list item and calling the function, but it returned $LB_ERR.

Edited by Sokko

Share this post


Link to post
Share on other sites
GaryFrost

Const $LB_GETCURSEL = 0x188

Func _GUICtrlListSelectedIndex($h_listbox)
    Return GUICtrlSendMsg($h_listbox, $LB_GETCURSEL, 0, 0)
EndFunc  ;==>_GUICtrlListSelectedIndex

Edited by gafrost

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites
GaryFrost

Think I would rather muck around with the beta than to keep going to the include that I wrote and copying and pasting code.

You can have both the release and beta versions on your system at the same time.


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites
Sokko

Okay, I'm looking at GuiList.au3 in the beta file, specifically the comment that says "DOES NOT WORK WITH SINGLE-SELECTION LIST BOXES". I wasn't aware that there was any type of list box other than one that accepts a single selection. There is no mention of multiple-select list boxes in either the help file or GUIConstants.au3, so I'm at a total loss here. If I knew how to configure a list box for multiple selections, I could probably figure out the rest from there.

Share this post


Link to post
Share on other sites
Gigglestick

FYI to the help file makers:

The documentation on the listview pages could be clearer on this, the GUI styles page organization is a nightmare for those new to GUIs, and the GUI styles page is incorrectly linked to from a few GUI pages (label references I mean).


My UDFs: ExitCodes

Share this post


Link to post
Share on other sites
Sokko

Thank you for your help! I had a hard time finding $LBS_MULTIPLESEL, since it was not present in GUIConstants, GUIList, or the styles index. I finally located it by searching the help file, which turned up a few references to 0x8 in the example scripts, and that turned out to work fine.

I have but one more question: Is there a function for deleting multiple selected items? All I can find is _GUICtrlListDeleteItem, and that only works for single-select lists.

Share this post


Link to post
Share on other sites
GaryFrost

It will work for multi-selected items, but you'll have to create your own loop to delete them


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites
Sokko

I'm probably overlooking something really stupid here...

$a = _GUICtrlListGetSelItems($memberlist)
For $i = 1 to $a[0]
_GUICtrlListDeleteItem($memberlist,$a[$i])
Next

This fails on GUICtrlListDeleteItem, which returns a -1. The comments say this should only happen if you pass it a value larger than the size of the list. I added a debugging MsgBox and it turned up the correct numbers for $a[$i] every time, always smaller than the list size. What's up, doc?

Share this post


Link to post
Share on other sites
Gigglestick

If _GUICtrlListGetSelCount($memberlist) > 0 Then
    For $i = _GuiCtrlListGetSelItems($memberlist) to 1 Step -1
    ; Start with the last one since the indices of 
    ; all items following the one deleted will shift
        _GuiCtrlListDeleteItem($memberlist, $i)
    Next
EndIf


My UDFs: ExitCodes

Share this post


Link to post
Share on other sites
Sokko

*bonks head* Duh, the order should be reversed. Unfortunately it still doesn't work; GUICtrlListDeleteItem returns -1 throughout the loop. The weird thing is that I can supply an integer and that works fine:

_GUICtrlListDeleteItem($memberlist,4)
_GUICtrlListDeleteItem($memberlist,2)
_GUICtrlListDeleteItem($memberlist,0)

If I select items 0, 2, and 4, the code below should have exactly the same effect as the code above. But it doesn't.

$a = _GUICtrlListGetSelItems($memberlist)
For $i = $a[0] to 1 step -1
_GUICtrlListDeleteItem($memberlist,$a[$i])
Next

Just for the heck of it, I tried copying and pasting your code wholesale, but $LB_ERR persisted. Argh.

Share this post


Link to post
Share on other sites
Sokko

Any ideas on why this isn't working? Anyone? I've tried everything I can think of, and drawn a total blank. Even a simple replacement of $a[$i] with an integer results in a working function. A MsgBox placed in the loop is enough to verify that $a[$i] is indeed a valid integer that is not greater than the size of the list. So the only possible explanation is that _GUICtrlListDeleteItem just doesn't like variables for some reason. What on earth is going on here? :whistle:

Share this post


Link to post
Share on other sites
Sokko

Sure thing. I've isolated the code that deals with this particular window. It can stand by itself, so copy-and-paste the whole thing into a blank AU3 file if you want to see the problem in action. There's a few comments at the relevant location, near the end.

#include <GuiConstants.au3>
#include <GuiList.au3>

;This is not defined in either of the above, for some reason, so I put it here
Global Const $LBS_MULTIPLESEL = 0x8

;Create the list window and add a bunch of controls
$listwindow = GuiCreate("Crew List", 470, 400,(@DesktopWidth-470)/2, (@DesktopHeight-400)/2 , $WS_OVERLAPPED + $WS_CAPTION + $WS_THICKFRAME + $WS_MINIMIZEBOX + $WS_VISIBLE + $WS_CLIPSIBLINGS)
GuiSetState(@SW_SHOW)
GuiSetIcon("%SystemRoot%\system32\SHELL32.dll",134)
$memberlist = GuiCtrlCreateList("", 10, 10, 450, 292, $LBS_MULTIPLESEL)
$Checkbox_1 = GuiCtrlCreateCheckbox("", 20, 310, 80, 20)
$Checkbox_2 = GuiCtrlCreateCheckbox("", 110, 310, 80, 20)
$Checkbox_3 = GuiCtrlCreateCheckbox("", 200, 310, 80, 20)
$Checkbox_4 = GuiCtrlCreateCheckbox("", 290, 310, 80, 20)
$Checkbox_5 = GuiCtrlCreateCheckbox("", 380, 310, 80, 20)
$Checkbox_6 = GuiCtrlCreateCheckbox("", 20, 340, 80, 20)
$Checkbox_7 = GuiCtrlCreateCheckbox("", 110, 340, 80, 20)
$Checkbox_8 = GuiCtrlCreateCheckbox("", 200, 340, 80, 20)
$Checkbox_9 = GuiCtrlCreateCheckbox("", 290, 340, 80, 20)
$Checkbox_10 = GuiCtrlCreateCheckbox("", 380, 340, 80, 20)
$nameinput = GuiCtrlCreateInput("", 20, 370, 60, 20)
$addbutton = GuiCtrlCreateButton("<-- Add member", 90, 370, 100, 20)
GUICtrlSetState($addbutton,$GUI_DEFBUTTON)
$delbutton = GuiCtrlCreateButton("Delete selected members", 200, 370, 150, 20)
$finbutton = GuiCtrlCreateButton("Finished", 360, 370, 80, 20)
For $i = $Checkbox_1 to $Checkbox_10
    GuiCtrlSetState($i,$GUI_CHECKED)
Next

;Message loop for GUI
While 1
    $msg = GuiGetMsg(1)
    Select
    Case $msg[0] = $GUI_EVENT_CLOSE or $msg[0] = $finbutton
        ExitLoop
    Case $msg[0] = $addbutton and GuiCtrlRead($nameinput) <> "" and StringInStr(GuiCtrlRead($nameinput),"-") = 0
        $j = GuiCtrlRead($nameinput)&" ("
        For $i = $Checkbox_1 to $Checkbox_10
            If GuiCtrlRead($i) = $GUI_CHECKED Then $k = "1"
            If GuiCtrlRead($i) = $GUI_UNCHECKED Then $k = "0"
            $j = $j&$k&"-"
        Next
        GuiCtrlSetData($memberlist,StringTrimRight($j,1)&")")
        GuiCtrlSetData($nameinput,"")
    Case $msg[0] = $delbutton and _GUICtrlListGetSelCount($memberlist) > 0
        $a = _GUICtrlListGetSelItems($memberlist)
        For $i = $a[0] to 1 step -1
            ;Put the following function into a MsgBox and watch it return a -1
            ;Then replace $a[$i] with an integer and watch it succeed
            _GUICtrlListDeleteItem($memberlist,$a[$i])
        Next
    EndSelect
WEnd

Exit

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  

×