Results 1 to 9 of 9

Thread: [RESOLVED] Listbox Multiselect, Double Click, And Drag&Drop

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Jan 2022
    Posts
    23

    Resolved [RESOLVED] Listbox Multiselect, Double Click, And Drag&Drop

    Hello!
    I have an application that has two list box controls, and I've tried to enable the drag and drop feature between the two lists, but I have some problems, I want to combine the drag and drop with some other features:
    1-The list box has the multi extended selection mode enabled.
    2-The double-click on an item opens a form with the selected item properties.
    3-The right click opens a context menu.

    I've tried to use a custom control that I found on this forum, but I still have bugs with the double click, sometimes "enables" the drag and drop instead of opening the properties form. Here is the custom control I'm using:
    https://www.vbforums.com/showthread....=1#post3079759

    Here are the methods I'm using:

    Code:
    Private Sub ListBox_DataBaseSFX_MouseMove(sender As Object, e As MouseEventArgs) Handles ListBox_DataBaseSFX.MouseMove
    	If sender IsNot Nothing AndAlso e.Button = MouseButtons.Left AndAlso e.Clicks = 1 Then
    		ListBox_DataBaseSFX.DoDragDrop(ListBox_DataBaseSFX.SelectedItems, DragDropEffects.Move)
    	End If
    End Sub
    
    Private Sub ListBox_DataBaseSFX_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles ListBox_DataBaseSFX.MouseDoubleClick
    	'Ensure that we have selected an item
    	Dim itemIndex = ListBox_DataBaseSFX.IndexFromPoint(e.Location)
    	If itemIndex <> ListBox.NoMatches Then
    		'Get item and file path
    		Dim selectedSFX As String = ListBox_DataBaseSFX.Items(itemIndex)
    		'Open editor
    		Dim sfxEditor As New SfxEditor(selectedSFX)
    		sfxEditor.ShowDialog()
    	End If
    End Sub
    
    Private Sub ListBox_DataBaseSFX_DragOver(sender As Object, e As DragEventArgs) Handles ListBox_DataBaseSFX.DragOver
    	e.Effect = DragDropEffects.Copy
    End Sub
    
    Private Sub ListBox_DataBaseSFX_DragDrop(sender As Object, e As DragEventArgs) Handles ListBox_DataBaseSFX.DragDrop
    	If e.Effect = DragDropEffects.Copy AndAlso ListBox_DataBases.SelectedItems.Count > 0 Then
    		If e.Data.GetDataPresent(GetType(ListBox.SelectedObjectCollection)) Then
    			Dim itemsData As ListBox.SelectedObjectCollection = e.Data.GetData(GetType(ListBox.SelectedObjectCollection))
    			For Each data As String In itemsData
    				ListBox_DataBaseSFX.Items.Add(data)
    			Next
    		End If
    	End If
    End Sub
    EDIT:
    This custom control, gives me the option to select rows by clicking one row and dragging it, as we can do in Excel, for example. The idea is to combine this with the drag and drop and also allowing the double click.
    Last edited by jms2505; Jan 29th, 2022 at 04:54 AM.

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    To start, sender will never be Nohing in your MouseMove event, sender is the Control that raised the event.
    I’d use the MouseDown event, checking for a double click with a windows API. I don’t remember the name, I’ll find it for you…

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Jan 2022
    Posts
    23

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    Quote Originally Posted by .paul. View Post
    To start, sender will never be Nohing in your MouseMove event, sender is the Control that raised the event.
    I’d use the MouseDown event, checking for a double click with a windows API. I don’t remember the name, I’ll find it for you…
    Yeah, I've tried using the MouseDown event, but the problem is that I can't select multiples items with the mouse, when I press the mouse button and I move down, I can select multiples items, but using this event, I can't do it.

  4. #4
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    This is how to get double click time

    https://docs.microsoft.com/en-us/dot...owsdesktop-6.0

    Not sure which version that was released with, so try it.

    In your Form_Load, set a Form level variable to Environment.TickCount
    In your ListBox_MouseDown, check if it’s a doubleclick by subtracting last click time from Environment.TickCount
    Set your last clicked time variable to Environment.TickCount

    Process single click code
    If double click, then also process double click code

  5. #5
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    Here’s an example, which is almost what I’ve described above, but it’ll work for you…

    https://www.vbforums.com/showthread....stview-listbox

  6. #6

    Thread Starter
    Junior Member
    Join Date
    Jan 2022
    Posts
    23

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    Quote Originally Posted by .paul. View Post
    Here’s an example, which is almost what I’ve described above, but it’ll work for you…

    https://www.vbforums.com/showthread....stview-listbox
    Hmm, not sure how to implement it, could you give me another example?
    The problem here is that if I use the MouseDown, conflicts with the mouse multi selection.
    Last edited by jms2505; Jan 28th, 2022 at 05:16 PM.

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Jan 2022
    Posts
    23

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    So the thing is, this custom control, gives me the option to select rows by clicking one row and dragging it, as we can do in Excel, for example. The idea is to combine this with the drag and drop and also allowing the double click.
    Any idea about what should I modify to make it working?

    btw, sorry for my bad English, is not my first language.
    Last edited by jms2505; Jan 28th, 2022 at 05:43 PM.

  8. #8
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    Try this...

    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim items() As String = {"one", "two", "three", "four", "five"}
            ListBox1.Items.AddRange(items)
        End Sub
    
        Private Sub ListBox2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragDrop
            For Each item As Object In (e.Data.GetData(GetType(ListBox.SelectedObjectCollection)))
                ListBox2.Items.Add(item)
            Next
        End Sub
    
        Private Sub ListBox2_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragOver, ListBox2.DragOver
            If (e.Data.GetDataPresent(GetType(ListBox.SelectedObjectCollection))) Then
                e.Effect = DragDropEffects.Move
            Else
                e.Effect = DragDropEffects.None
            End If
        End Sub
    
        Private Sub ListBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.DoubleClick
            'doubleclicked
            'Ensure that we have selected an item
            Dim itemIndex = ListBox1.IndexFromPoint(ListBox1.PointToClient(MousePosition))
            If itemIndex <> ListBox.NoMatches Then
                'Get item and file path
                'Dim selectedSFX As String = ListBox1.Items(itemIndex)
                'Open editor
                'Dim sfxEditor As New SfxEditor(selectedSFX)
                'sfxEditor.ShowDialog()
                MsgBox(ListBox1.Items(itemIndex))
            End If
        End Sub
    
    End Class
    This is the extended ListBox. Add the class to your project, rebuild your project, then you'll find MultiSelListBox at the top of your toolbox...

    Code:
    Public Class MultiSelListBox
        Inherits ListBox
    
        Private MouseDownOnIndex As Integer
        Private bMouseDownOnSelection As Boolean
        Private bMouseDownOutsideSelection As Boolean
        Private Const WM_LBUTTONDOWN As Integer = &H201
        Private Const WM_LBUTTONUP As Integer = &H202
        Private Const WM_MOUSEMOVE As Integer = &H200
        Private Const MK_LBUTTON As Integer = &H1&
        Private lastClickedPosition As Point
    
        Protected Overrides Sub OnCreateControl()
            lastClickedPosition = Point.Empty
            MyBase.OnCreateControl()
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            Select Case m.Msg
                Case WM_LBUTTONDOWN
                    Dim pt As New Point(m.LParam.ToInt32)
                    MouseDownOnIndex = Me.IndexFromPoint(pt)
                    If Me.SelectedItems.Count >= 1 _
                        And Me.SelectedIndices.Contains(MouseDownOnIndex) _
                            And m.WParam = MK_LBUTTON Then
                        bMouseDownOnSelection = True
                        lastClickedPosition = pt
                        Return
                    Else
                        bMouseDownOutsideSelection = True
                        lastClickedPosition = Point.Empty
                        MyBase.WndProc(m)
                    End If
                Case WM_MOUSEMOVE
                    If bMouseDownOnSelection Then
                        Dim pt As New Point(m.LParam.ToInt32)
                        If Math.Abs(pt.X - lastClickedPosition.X) < 3 OrElse _
                            Math.Abs(pt.Y - lastClickedPosition.Y) < 3 Then
                            Me.DoDragDrop(Me.SelectedItems, DragDropEffects.Move)
                        End If
                    End If
                    bMouseDownOnSelection = False
                    MyBase.WndProc(m)
                Case WM_LBUTTONUP
                    Dim pt As New Point(m.LParam.ToInt32)
                    If MouseDownOnIndex = Me.IndexFromPoint(pt) _
                        And m.WParam = 0 And Not bMouseDownOutsideSelection Then
                        Dim down As New Message()
                        down.HWnd = m.HWnd
                        down.Msg = WM_LBUTTONDOWN
                        down.WParam = m.WParam
                        down.LParam = m.LParam
                        down.Result = IntPtr.Zero
                        MyBase.WndProc(down)
                        lastClickedPosition = Point.Empty
                    End If
                    bMouseDownOutsideSelection = False
                    MyBase.WndProc(m)
                Case Else
                    MyBase.WndProc(m)
            End Select
        End Sub
    
    End Class

  9. #9

    Thread Starter
    Junior Member
    Join Date
    Jan 2022
    Posts
    23

    Re: Listbox Multiselect, Double Click, And Drag&Drop

    Quote Originally Posted by .paul. View Post
    Try this...

    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim items() As String = {"one", "two", "three", "four", "five"}
            ListBox1.Items.AddRange(items)
        End Sub
    
        Private Sub ListBox2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragDrop
            For Each item As Object In (e.Data.GetData(GetType(ListBox.SelectedObjectCollection)))
                ListBox2.Items.Add(item)
            Next
        End Sub
    
        Private Sub ListBox2_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragOver, ListBox2.DragOver
            If (e.Data.GetDataPresent(GetType(ListBox.SelectedObjectCollection))) Then
                e.Effect = DragDropEffects.Move
            Else
                e.Effect = DragDropEffects.None
            End If
        End Sub
    
        Private Sub ListBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.DoubleClick
            'doubleclicked
            'Ensure that we have selected an item
            Dim itemIndex = ListBox1.IndexFromPoint(ListBox1.PointToClient(MousePosition))
            If itemIndex <> ListBox.NoMatches Then
                'Get item and file path
                'Dim selectedSFX As String = ListBox1.Items(itemIndex)
                'Open editor
                'Dim sfxEditor As New SfxEditor(selectedSFX)
                'sfxEditor.ShowDialog()
                MsgBox(ListBox1.Items(itemIndex))
            End If
        End Sub
    
    End Class
    This is the extended ListBox. Add the class to your project, rebuild your project, then you'll find MultiSelListBox at the top of your toolbox...

    Code:
    Public Class MultiSelListBox
        Inherits ListBox
    
        Private MouseDownOnIndex As Integer
        Private bMouseDownOnSelection As Boolean
        Private bMouseDownOutsideSelection As Boolean
        Private Const WM_LBUTTONDOWN As Integer = &H201
        Private Const WM_LBUTTONUP As Integer = &H202
        Private Const WM_MOUSEMOVE As Integer = &H200
        Private Const MK_LBUTTON As Integer = &H1&
        Private lastClickedPosition As Point
    
        Protected Overrides Sub OnCreateControl()
            lastClickedPosition = Point.Empty
            MyBase.OnCreateControl()
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            Select Case m.Msg
                Case WM_LBUTTONDOWN
                    Dim pt As New Point(m.LParam.ToInt32)
                    MouseDownOnIndex = Me.IndexFromPoint(pt)
                    If Me.SelectedItems.Count >= 1 _
                        And Me.SelectedIndices.Contains(MouseDownOnIndex) _
                            And m.WParam = MK_LBUTTON Then
                        bMouseDownOnSelection = True
                        lastClickedPosition = pt
                        Return
                    Else
                        bMouseDownOutsideSelection = True
                        lastClickedPosition = Point.Empty
                        MyBase.WndProc(m)
                    End If
                Case WM_MOUSEMOVE
                    If bMouseDownOnSelection Then
                        Dim pt As New Point(m.LParam.ToInt32)
                        If Math.Abs(pt.X - lastClickedPosition.X) < 3 OrElse _
                            Math.Abs(pt.Y - lastClickedPosition.Y) < 3 Then
                            Me.DoDragDrop(Me.SelectedItems, DragDropEffects.Move)
                        End If
                    End If
                    bMouseDownOnSelection = False
                    MyBase.WndProc(m)
                Case WM_LBUTTONUP
                    Dim pt As New Point(m.LParam.ToInt32)
                    If MouseDownOnIndex = Me.IndexFromPoint(pt) _
                        And m.WParam = 0 And Not bMouseDownOutsideSelection Then
                        Dim down As New Message()
                        down.HWnd = m.HWnd
                        down.Msg = WM_LBUTTONDOWN
                        down.WParam = m.WParam
                        down.LParam = m.LParam
                        down.Result = IntPtr.Zero
                        MyBase.WndProc(down)
                        lastClickedPosition = Point.Empty
                    End If
                    bMouseDownOutsideSelection = False
                    MyBase.WndProc(m)
                Case Else
                    MyBase.WndProc(m)
            End Select
        End Sub
    
    End Class
    Thank you very much!, That's what I've looking for
    Last edited by jms2505; Jan 29th, 2022 at 05:12 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width