Sign in to follow this  
Followers 0
RichardTwickenham

How to tell which listview items are selected

16 posts in this topic

I would like to use a listview which allows multiple items to be selected at the same time, or in AutoIt terminology to be given focus at the same time. I've attached a sample script in which I've done this. But, the problem I have is how do I detect which ListViewItems are selected. I've tried using GuiCtrlRead and GuiCtrlGetState but I've only managed to get hold of the handle of the first selected ListViewItem. Does anyone know how to get the handles of all the items which are selected? Any help would be very welcome.

#include <GuiConstantsEx.au3>
#include <AVIConstants.au3>
#include <TreeViewConstants.au3>
#include <ListViewConstants.au3>
; GUI
GUICreate("Sample GUI", 400, 400)

; LIST VIEW
Local $iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 110, 80, $LVS_SHOWSELALWAYS)
$a = GUICtrlCreateListViewItem("A|One", $iListView)
$b = GUICtrlCreateListViewItem("B|Two", $iListView)
$c = GUICtrlCreateListViewItem("C|Three", $iListView)
GUICtrlSetState ($b, $GUI_FOCUS)
GUICtrlSetState ($c, $GUI_FOCUS)

; GUI MESSAGE LOOP
GUISetState(@SW_SHOW)
$HandleOfSelectedItem = GUICtrlRead ($iListView)
Msgbox(0,"Handle of selected item", $HandleOfSelectedItem)
While 1
Switch GUIGetMsg()
  Case $GUI_EVENT_CLOSE
   Exit
EndSwitch
WEnd

Share this post


Link to post
Share on other sites



Thanks Admiral. :)

I've attached the new version of my test script in case anyone is interested.

#include <GuiConstantsEx.au3>
#include <AVIConstants.au3>
#include <TreeViewConstants.au3>
#include <ListViewConstants.au3>
#include <GuiListView.au3>
#include <Array.au3>
; GUI
GUICreate("Sample GUI", 400, 400)

; LIST VIEW
Local $iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 110, 80, $LVS_SHOWSELALWAYS)
$a = GUICtrlCreateListViewItem("A|One", $iListView)
$b = GUICtrlCreateListViewItem("B|Two", $iListView)
$c = GUICtrlCreateListViewItem("C|Three", $iListView)
GUICtrlSetState ($a, $GUI_FOCUS)
;GUICtrlSetState ($b, $GUI_FOCUS)
GUICtrlSetState ($c, $GUI_FOCUS)

; GUI MESSAGE LOOP
GUISetState(@SW_SHOW)
$SelectedItemsArray = _GUICtrlListView_GetSelectedIndices($iListView, True)
_ArrayDisplay($SelectedItemsArray)

While 1
Switch GUIGetMsg()
  Case $GUI_EVENT_CLOSE
   Exit
EndSwitch
WEnd

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I have a similar problem so sorry for hijacking your thread.

I want to get a notification everytime an item in my listview is selected/unselected so I can enable/disable a button. This works only for mouseclicks though.

#include <GuiConstantsEx.au3>
#include <GuiListView.au3>

Dim $a[3]
GUICreate("Sample GUI", 400, 400)

$iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 180, 180, $LVS_SHOWSELALWAYS)
$ibut = GUICtrlCreateButton("Sample", 220, 10, 110, 80)
$a[0] = GUICtrlCreateListViewItem("A|One", $iListView)
$a[1] = GUICtrlCreateListViewItem("B|Two", $iListView)
$a[2] = GUICtrlCreateListViewItem("C|Three", $iListView)

GUISetState(@SW_SHOW)
GUICtrlSetState($ibut, $GUI_DISABLE)

While 1
    $msg = GUIGetMsg()
    If $msg > 0 then MsgBox(0, "", $msg)
    For $i = 0 To UBound($a) - 1
        If($msg = $a[$i]) Then
            If _GUICtrlListView_GetSelectedCount($iListView) = 0 Then
                    GUICtrlSetState($ibut, $GUI_DISABLE)
            Else
                    GUICtrlSetState($ibut, $GUI_ENABLE)
            EndIf
            ExitLoop
        EndIf
    Next

    Switch $msg
      Case $GUI_EVENT_CLOSE
       Exit
    EndSwitch
WEnd

If I (select and afterwards) unselected a listview item with Ctrl+Mouseclick, the script works. Unfortunately the listbox doesn't drop a message for GuiGetMsg() when I just go up and down in the list with arrow keys, (or when I click in the white area of the listview, (or when I select multiple list items with mouse drag)), etcetc.

How can I get a notification ALWAYS when the amount of selected items change?

TIA,

Hawk

Edited by Hawk

Share this post


Link to post
Share on other sites

Hawk,

The problem you have is that once you have selected an item in the ListView you cannot return to a "no selection" state. It might look as if you can, but in fact the selection is still there - the colour for unfocused selection is almost the same as the background of the ListView so you cannot see it. If you colour the ListView you can see that the selection remains:

#include <GuiConstantsEx.au3>
#include <GuiListView.au3>

Global $a[3]

GUICreate("Sample GUI", 400, 400)

$iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 180, 180, $LVS_SHOWSELALWAYS)
GUICtrlSetBkColor(-1, 0xFFCCCC)
$a[0] = GUICtrlCreateListViewItem("A|One", $iListView)
$a[1] = GUICtrlCreateListViewItem("B|Two", $iListView)
$a[2] = GUICtrlCreateListViewItem("C|Three", $iListView)
$ibut = GUICtrlCreateButton("Sample", 220, 10, 110, 80)

GUISetState(@SW_SHOW)

GUICtrlSetState($ibut, $GUI_DISABLE)

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case Else
            For $i = 0 To UBound($a) - 1
                If $msg = $a[$i] Then
                    If _GUICtrlListView_GetSelectedCount($iListView) = 0 Then
                        GUICtrlSetState($ibut, $GUI_DISABLE)
                    Else
                        GUICtrlSetState($ibut, $GUI_ENABLE)
                    EndIf
                    ExitLoop
                EndIf
            Next
    EndSwitch
WEnd

So you always get a positive return from _GUICtrlListView_GetSelectedCount. ;)

You need to actually deselect items if you want a true "no selection" state as you can see here: :)

#include <GuiConstantsEx.au3>
#include <GuiListView.au3>

Global $a[3]

GUICreate("Sample GUI", 400, 400)

$iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 180, 180, $LVS_SHOWSELALWAYS)
GUICtrlSetBkColor(-1, 0xFFCCCC)
$a[0] = GUICtrlCreateListViewItem("A|One", $iListView)
$a[1] = GUICtrlCreateListViewItem("B|Two", $iListView)
$a[2] = GUICtrlCreateListViewItem("C|Three", $iListView)
$ibut = GUICtrlCreateButton("Unselect", 220, 10, 110, 80)

GUISetState(@SW_SHOW)

GUICtrlSetState($ibut, $GUI_DISABLE)

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $ibut
            For $i = 0 To UBound($a) - 1
                _GUICtrlListView_SetItemSelected($iListView, $i, False)
            Next
            GUICtrlSetState($ibut, $GUI_DISABLE)
        Case Else
            For $i = 0 To UBound($a) - 1
                If $msg = $a[$i] Then
                    If _GUICtrlListView_GetSelectedCount($iListView) <> 0 Then
                        GUICtrlSetState($ibut, $GUI_ENABLE)
                    EndIf
                    ExitLoop
                EndIf
            Next
    EndSwitch
WEnd

I hope that makes sense - please ask again if not. ;)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Thanks for your answer Melba23.

I can indeed "unselect" a selected item and _GUICtrlListView_GetSelectedCount really returns 0 afterwards and the button can become invisible. I made a very small video you might want to look at.

http://www.2shared.com/video/UMRfQ5yA/Feb06-2012-01-54PM.html

First I click on an item -> GuiGetMsg() recognizes it and the button becomes activated (_GUICtrlListView_GetSelectedCount returns 1)

Then I hold Ctrl and click again on that item -> GuiGetMsg() recognizes it and the button deactivates (_GUICtrlListView_GetSelectedCount returns 1)

Then I drag 3 items and release the mousebutton outside of the listbox -> GuiGetMsg() doesn't get a message. Nothing happens even though 3 items have been selected.

Then I use the arrow keys to select items -> GuiGetMsg() doesn't get a message. Nothing happens even though items have been selected.

In the last two cases the button stays invisible even though items in the list are selected (_GUICtrlListView_GetSelectedCount would return a value >0). That is my problem, I want to always get some notification when the selection changes, no matter from what source (mouseclick, drag, arrowkeys, etc) the change comes.

Is that possible? It doesn't need to be the message loop respectively, I am also okay with workarounds.

Share this post


Link to post
Share on other sites

Hawk,

Thank you for explaining that - I did not know you could deselect with the Ctrl key. My learning point for today! :)

I am not surprised GUIGetMsg does not react - I imagine we will have to look at registering a Windows message. I will start to look into which one it might be. ;)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Hawk,

While I am looking into this, here is a way to do it using Adlib: :)

#include <GuiConstantsEx.au3>
#include <GuiListView.au3>

Global $a[3]

GUICreate("Sample GUI", 400, 400)

$iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 180, 180, $LVS_SHOWSELALWAYS)
GUICtrlSetBkColor(-1, 0xFFCCCC)
$a[0] = GUICtrlCreateListViewItem("A|One", $iListView)
$a[1] = GUICtrlCreateListViewItem("B|Two", $iListView)
$a[2] = GUICtrlCreateListViewItem("C|Three", $iListView)
$ibut = GUICtrlCreateButton("Sample", 220, 10, 110, 80)
GUICtrlSetState($ibut, $GUI_DISABLE)

GUISetState(@SW_SHOW)

AdlibRegister("_Sel_Check", 500)

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func _Sel_Check()

    If _GUICtrlListView_GetSelectedCount($iListView) = 0 Then
        If BitAnd(GUICtrlGetState($ibut), $GUI_ENABLE) Then GUICtrlSetState($ibut, $GUI_DISABLE)
    Else
        If BitAnd(GUICtrlGetState($ibut), $GUI_DISABLE) Then GUICtrlSetState($ibut, $GUI_ENABLE)
    EndIf

EndFunc   ;==>_Sel_Check

Not the most elegant solution, but it will keep you going for a while. ;)

m23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Probably tracking this notification would help?

http://msdn.microsoft.com/en-us/library/windows/desktop/bb774843%28v=vs.85%29.aspx

I already have a WM_Notify Message registered to track doubleclicks in the listview. I will try to add this notification also, there just might be a problem in how to port structures to AutoIT for me. :)

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Hawk,

More difficult than I thought it would be to find a suitable message - here is another workaround for you in the meantime: ;)

#include <guiconstantsex.au3>
#include <guilistview.au3>

Global $a[3]

GUICreate("Sample GUI", 400, 400)

$iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 180, 180, $LVS_SHOWSELALWAYS)
GUICtrlSetBkColor(-1, 0xFFCCCC)
$a[0] = GUICtrlCreateListViewItem("A|One", $iListView)
$a[1] = GUICtrlCreateListViewItem("B|Two", $iListView)
$a[2] = GUICtrlCreateListViewItem("C|Three", $iListView)
$ibut = GUICtrlCreateButton("Sample", 220, 10, 110, 80)
GUICtrlSetState($ibut, $GUI_DISABLE)

GUISetState(@SW_SHOW)

$sCurrent_Selection = ""

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    ; Look for selection changes in the ListView
    $sSelection = _GUICtrlListView_GetSelectedIndices($iListView)
    ; Has it changed?
    If $sSelection <> $sCurrent_Selection Then
        If _GUICtrlListView_GetSelectedCount($iListView) = 0 Then
            If BitAnd(GUICtrlGetState($ibut), $GUI_ENABLE) Then GUICtrlSetState($ibut, $GUI_DISABLE)
        Else
            If BitAnd(GUICtrlGetState($ibut), $GUI_DISABLE) Then GUICtrlSetState($ibut, $GUI_ENABLE)
        EndIf
        $sCurrent_Selection = $sSelection
    EndIf

WEnd

M23

Edit: Our posts crossed. I tried that one and could not get it to work, but maybe you will have more luck. :)

Edited by Melba23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Hawk,

Found it - you need to trap $LVN_ITEMCHANGING. But you need to use a flag in the main loop as the count is not reset until the handler returns: ;)

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>

Global $a[3], $fChange = False

GUICreate("Sample GUI", 400, 400)

$iListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 180, 180, $LVS_SHOWSELALWAYS)
$hListView = GUICtrlGetHandle($iListView)
GUICtrlSetBkColor(-1, 0xFFCCCC)
$a[0] = GUICtrlCreateListViewItem("A|One", $iListView)
$a[1] = GUICtrlCreateListViewItem("B|Two", $iListView)
$a[2] = GUICtrlCreateListViewItem("C|Three", $iListView)
$ibut = GUICtrlCreateButton("Sample", 220, 10, 110, 80)
GUICtrlSetState($ibut, $GUI_DISABLE)

GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")


While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    If $fChange Then
        If _GUICtrlListView_GetSelectedCount($iListView) = 0 Then
            If BitAnd(GUICtrlGetState($ibut), $GUI_ENABLE) Then GUICtrlSetState($ibut, $GUI_DISABLE)
        Else
            If BitAnd(GUICtrlGetState($ibut), $GUI_DISABLE) Then GUICtrlSetState($ibut, $GUI_ENABLE)
        EndIf
        $fChange = False
    EndIf

WEnd

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $LVN_ITEMCHANGING
                    $fChange = True
            EndSwitch
    EndSwitch

EndFunc

Thanks for that - I always enjoy a new challenge. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Thanks for the two workarounds. The Adlib solution is not as time critical as I would want the function to be.. (except if I set the time difference to 1-15ms, which I'd like to avoid :))

The second method I was about to code yesterday, but my head was bloated from coding too long so I delayed that. It works fast and fine, only when the window is flooded with messages, the program uses 5-30% CPU Time during that time (for example when you just hover your mouse around in the main window).

But at least it works at the moment ;)

Share this post


Link to post
Share on other sites

Hawk,

Look at my last post - I have solved it. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

It's funny how our posts cross all the time :) Your latest solution works like a charm. I don't know why but I feel better using

LVN_ITEMCHANGED instead of LVN_ITEMCHANGING

but now it works perfectly as it should without any significant CPU Load!

Thanks a bunch!

Share this post


Link to post
Share on other sites

I will try to add this notification also, there just might be a problem in how to port structures to AutoIT for me. :)

Well, since the structures are not only already implemented but also already #included by your script, what an odd thing to say.

Just do a Search>Find in Files... on the include folder if you don't know the layout of things.

Share this post


Link to post
Share on other sites

Well, since the structures are not only already implemented but also already #included by your script, what an odd thing to say.

Just do a Search>Find in Files... on the include folder if you don't know the layout of things.

I didn't learn about that yet, that's why I told that it would be difficult for me. The next project containing such code will teach me how to handle windows structures!

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