[blue]Option Explicit
Private Const LB_GETITEMRECT = &H198
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private InDrag As Boolean
Private TrackX As Single
Private TrackY As Single
Private Sub Check1_Click()
' Set whether List2 can be dragged to a new position or whether, instead, an item is selected when we click on List2
List2.DragMode = Check1
End Sub
Private Sub Form_DragDrop(Source As Control, X As Single, Y As Single)
Source.Left = TrackX + X
Source.Top = TrackY + Y
InDrag = False
Source.Visible = True
LineLink
End Sub
Private Sub Form_Load()
Dim word
' Set up for example...
Line1(0).Visible = False
Form1.ScaleMode = vbPixels
List1.Clear
List1.Height = 100
List2.Clear
List2.Height = 100
' just some random words to populate listboxes
For Each word In Split("Lorem ipsum dolor sit amet consectetuer adipiscing elit Maecenas porttitor congue massa", " ")
List1.AddItem word
List2.AddItem word
Next
Check1.Caption = "Allow List2 Drag"
Check1_Click
End Sub
Private Sub List1_Click()
LineLink
End Sub
Private Sub List1_Scroll()
LineLink
End Sub
Public Sub LineLink()
Dim start As RECT
Dim starttop As Long
Dim finish As RECT
Dim finishtop As Long
Dim lineindex As Long
Static maxlinecount As Long
Dim lp As Long
For lp = 1 To maxlinecount
Line1(lp).Visible = False ' we might prefer to unload unused controls, but you cannot do that in a scroll event
Next
maxlinecount = 0
For lp = 0 To List1.ListCount - 1
If List1.Selected(lp) Then
lineindex = lineindex + 1
On Error Resume Next ' ignore the fact that lines might already be loaded
Load Line1(lineindex) ' dynamically load line controls
Load Line1(lineindex + 1)
Load Line1(lineindex + 2)
On Error GoTo 0
SendMessage List1.hwnd, LB_GETITEMRECT, lp, start
SendMessage List2.hwnd, LB_GETITEMRECT, List2.ListIndex, finish
starttop = (start.Top + start.Bottom) / 2
If starttop < 0 Then starttop = 0
If starttop > List1.Height Then starttop = List1.Height - 2 ' 2 is magic number for 3d border width
finishtop = (finish.Top + finish.Bottom) / 2
If finishtop < 0 Then finishtop = 0
If finishtop > List1.Height Then finishtop = List2.Height - 2
Line1(lineindex).X1 = List1.Left + start.Right + 2 + 18 ' 20 is a magic number for scroll bar width ...
Line1(lineindex).X2 = Line1(lineindex).X1 + 10 ' 10 is an arbitary width for line stub
'Line1(lineindex).X2 = List2.Left
Line1(lineindex).Y1 = List1.Top + starttop + 2
Line1(lineindex).Y2 = Line1(lineindex).Y1
Line1(lineindex + 1).X2 = List2.Left
Line1(lineindex + 1).X1 = Line1(lineindex + 1).X2 - 10 '10 is an arbitary width for line stub
Line1(lineindex + 1).Y2 = List2.Top + finishtop + 2
Line1(lineindex + 1).Y1 = Line1(lineindex + 1).Y2
Line1(lineindex + 2).X1 = Line1(lineindex).X2
Line1(lineindex + 2).X2 = Line1(lineindex + 1).X1
Line1(lineindex + 2).Y1 = Line1(lineindex).Y1
Line1(lineindex + 2).Y2 = Line1(lineindex + 1).Y2
Line1(lineindex).Visible = True ' and now show lines if not already visble
Line1(lineindex + 1).Visible = True
Line1(lineindex + 2).Visible = True
lineindex = lineindex + 2
End If
Next
If lineindex > maxlinecount Then maxlinecount = lineindex
End Sub
Private Sub List2_Click()
LineLink
End Sub
Private Sub List2_DragOver(Source As Control, X As Single, Y As Single, State As Integer)
If Not InDrag Then
TrackX = -(X / 15) ' twips to pixels
TrackY = -(Y / 15) ' twips to pixels
InDrag = True
Source.Visible = False
End If
End Sub
Private Sub List2_Scroll()
LineLink
End Sub[/blue]