Jump to content

Listviews: How to allow drag select on multiple items


Achilles
 Share

Recommended Posts

This is kind of hard to explain, but here's my attempt: I know how to make a listview allow multiple selections. On that listview, if you try to start dragging an item nothing will happen except the cursor changing (it does for me on Vista). You can select multiple items by left clicking and holding down the mouse, and then creating a box that includes the items you want selected. However, if you try that and start ontop of a listview item, it doesn't work. Is there a way to allow the user to make selection boxes when they begin their mouse drag ontop of a listview item?

Foobar2000 does what I want to do, so if you have foobar you could try it...

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIImagelist.au3>
#include <GUIListView.au3>

GUICreate("listview items", 420, 450, 100, 200)

$listview = GUICtrlCreateListView("col1  |col2|col3  ", 10, 10, 400, 350, $LVS_NOCOLUMNHEADER + $LVS_REPORT, $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER + $LVS_EX_SNAPTOGRID );,$LVS_SORTDESCENDING)
;~ $button = GUICtrlCreateButton("Value?", 75, 170, 70, 20)
$item1 = GUICtrlCreateListViewItem("item2|col22|col23", $listview)
$item2 = GUICtrlCreateListViewItem("item1|col12|col13", $listview)
$item3 = GUICtrlCreateListViewItem("item3|col32|col33", $listview)
;~ $input1 = GUICtrlCreateInput("", 20, 200, 150)
GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; to allow drag and dropping
GUISetState()

Do
    $msg = GUIGetMsg()
    
    Select
;~      Case $msg = $button
;~          MsgBox(0, "listview item", GUICtrlRead(GUICtrlRead($listview)), 2)
        Case $msg = $listview
            MsgBox(0, "listview", "clicked=" & GUICtrlGetState($listview), 2)
    EndSelect
Until $msg = $GUI_EVENT_CLOSE
Edited by Achilles
My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]
Link to comment
Share on other sites

This is kind of hard to explain, but here's my attempt: I know how to make a listview allow multiple selections. On that listview, if you try to start dragging an item nothing will happen except the cursor changing (it does for me on Vista). You can select multiple items by left clicking and holding down the mouse, and then creating a box that includes the items you want selected. However, if you try that and start ontop of a listview item, it doesn't work. Is there a way to allow the user to make selection boxes when they begin their mouse drag ontop of a listview item?

Foobar2000 does what I want to do, so if you have foobar you could try it...

Hmm... this seem a trick, but anyway:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <Misc.au3>

Global $hDLL = DllOpen("User32.dll")

GUICreate("listview items", 420, 450)

$listview = GUICtrlCreateListView("col1  |col2|col3  ", 10, 10, 400, 350, $LVS_SHOWSELALWAYS)

$item1 = GUICtrlCreateListViewItem("item2|col22|col23", $listview)
$item2 = GUICtrlCreateListViewItem("item1|col12|col13", $listview)
$item3 = GUICtrlCreateListViewItem("item3|col32|col33", $listview)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

DllClose($hDLL)

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndListView, $tNMHDR, $hWndFrom, $iCode
    
    $hWndListView = $listview
    If Not HWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($listview)
    
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_BEGINDRAG
                    Return 1
                Case $LVN_HOTTRACK
                    Local $tINFO = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iItem = DllStructGetData($tINFO, "Item")
                    
                    If ($iItem <> -1) And (_IsPressed("01", $hDLL)) Then _
                        _GUICtrlListView_SetItemSelected($hWndFrom, $iItem, True, True)
            EndSwitch
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

:mellow:

Edited by rasim
Link to comment
Share on other sites

If I understand correctly you want listview items to be selected like ListBox items with the $LBS_EXTENDEDSEL style.

@rasim, you could use GUIGetCursorInfo($hWnd) instead of_IsPressed(), but this still needs work. (deselection is buggy)

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

GUICreate("listview items", 420, 450)

$listview = GUICtrlCreateListView("col1  |col2|col3  ", 10, 10, 400, 350, $LVS_SHOWSELALWAYS)

$item1 = GUICtrlCreateListViewItem("item2|col22|col23", $listview)
$item2 = GUICtrlCreateListViewItem("item1|col12|col13", $listview)
$item3 = GUICtrlCreateListViewItem("item3|col32|col33", $listview)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndListView, $tNMHDR, $hWndFrom, $iCode
   
    $hWndListView = $listview
    If Not HWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($listview)
   
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
   
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_BEGINDRAG
                    Return 1
                Case $LVN_HOTTRACK
                    Local $tINFO = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iItem = DllStructGetData($tINFO, "Item")
                    Local $aCursInfo = GUIGetCursorInfo($hWnd)
                    If ($iItem <> -1) And ($aCursInfo[2] = 1) Then 
                        If _GUICtrlListView_GetItemSelected($hWndFrom, $iItem) Then
                            ;_GUICtrlListView_SetItemSelected($hWndFrom, $iItem, False, False) ;<-- this causes flickering :(
                        Else
                            _GUICtrlListView_SetItemSelected($hWndFrom, $iItem, True, True) 
                        EndIf
                    EndIf
                    
            EndSwitch
    EndSwitch
   
    Return $GUI_RUNDEFMSG
EndFunc
Don't bother, It's inside your monitor!------GUISetOnEvent should behave more like HotKeySet()
Link to comment
Share on other sites

Got it :mellow:

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

GUICreate("listview items", 420, 450)

$listview = GUICtrlCreateListView("col1  |col2|col3  ", 10, 10, 400, 350, $LVS_SHOWSELALWAYS)

Global $iTrack, $iFirst, $dir, $TrackDir
For $i = 1 To 40
    $temp = GUICtrlCreateListViewItem("item" & $i & "|col" & $i & "2|col" & $i & "3", $listview)
    Assign("item" & $i, $temp)
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndListView, $tNMHDR, $hWndFrom, $iCode
   
    $hWndListView = $listview
    If Not HWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($listview)
   
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
   
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_BEGINDRAG
                    Local $tINFO = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iItem = DllStructGetData($tINFO, "Item")
                    $iTrack = $iItem
                    $iFirst = $iItem
                    _GUICtrlListView_SetItemSelected($hWndFrom, -1, False)
                    _GUICtrlListView_SetItemSelected($hWndFrom, $iItem)
                    Return 1
                Case $LVN_HOTTRACK
                    Local $tINFO = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iItem = DllStructGetData($tINFO, "Item")
                    Local $aCursInfo = GUIGetCursorInfo($hWnd)
                    If ($iItem <> -1) And ($aCursInfo[2] = 1) And ($iTrack <> $iItem) Then
                        If $iItem > $iTrack Then
                            $TrackDir = 1
                        Else
                            $TrackDir = -1
                        EndIf
                        If $iItem > $iFirst Then
                            $dir = 1
                        Else
                            $dir = -1
                        EndIf
                        _GUICtrlListView_EnsureVisible($hWndFrom, $iItem + $TrackDir)
                        If $TrackDir <> $dir Or $iItem == $iFirst Then
                            For $i = $iTrack To $iItem - $TrackDir Step $TrackDir
                                _GUICtrlListView_SetItemSelected($hWndFrom, $i, False, False)
                            Next
                        EndIf
                        
                        $iTrack = $iItem
                        For $i = $iFirst To $iItem Step $dir
                            _GUICtrlListView_SetItemSelected($hWndFrom, $i, True)
                        Next
                    EndIf
            EndSwitch
    EndSwitch
   
    Return $GUI_RUNDEFMSG
EndFunc
Edited by wraithdu
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...