Jump to content
Sign in to follow this  
Achilles

Listviews: How to allow drag select on multiple items

Recommended Posts

Achilles

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]

Share this post


Link to post
Share on other sites
rasim

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

Share this post


Link to post
Share on other sites
WeMartiansAreFriendly

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()

Share this post


Link to post
Share on other sites
Achilles

Well, at least you both know what I'm after... However, as close as they are they both have bugs with deselection like mrRevoked said. This isn't really a crucial thing... It would just be nice to have.


My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]

Share this post


Link to post
Share on other sites
wraithdu

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

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  

×