[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.
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…
Re: Listbox Multiselect, Double Click, And Drag&Drop
Quote:
Originally Posted by
.paul.
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.
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
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
Re: Listbox Multiselect, Double Click, And Drag&Drop
Quote:
Originally Posted by
.paul.
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.
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.
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
Re: Listbox Multiselect, Double Click, And Drag&Drop
Quote:
Originally Posted by
.paul.
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 :)