RichardTwickenham Posted February 2, 2012 Posted February 2, 2012 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
AdmiralAlkex Posted February 2, 2012 Posted February 2, 2012 Try _GUICtrlListView_GetSelectedIndices() .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface
RichardTwickenham Posted February 3, 2012 Author Posted February 3, 2012 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
Hawk Posted February 6, 2012 Posted February 6, 2012 (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 February 6, 2012 by Hawk
Moderators Melba23 Posted February 6, 2012 Moderators Posted February 6, 2012 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: expandcollapse popup#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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
Hawk Posted February 6, 2012 Posted February 6, 2012 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.htmlFirst 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.
Moderators Melba23 Posted February 6, 2012 Moderators Posted February 6, 2012 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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
Moderators Melba23 Posted February 6, 2012 Moderators Posted February 6, 2012 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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
Hawk Posted February 6, 2012 Posted February 6, 2012 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.
Moderators Melba23 Posted February 6, 2012 Moderators Posted February 6, 2012 (edited) Hawk, More difficult than I thought it would be to find a suitable message - here is another workaround for you in the meantime: expandcollapse popup#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 February 6, 2012 by Melba23  Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
Moderators Melba23 Posted February 6, 2012 Moderators Posted February 6, 2012 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: expandcollapse popup#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 EndFuncThanks 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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
Hawk Posted February 6, 2012 Posted February 6, 2012 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
Moderators Melba23 Posted February 6, 2012 Moderators Posted February 6, 2012 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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
Hawk Posted February 6, 2012 Posted February 6, 2012 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 usingLVN_ITEMCHANGED instead of LVN_ITEMCHANGINGbut now it works perfectly as it should without any significant CPU Load!Thanks a bunch!
AdmiralAlkex Posted February 6, 2012 Posted February 6, 2012 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. .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface
Hawk Posted February 6, 2012 Posted February 6, 2012 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!
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now