|
■No67737 (魔界の仮面弁士) に追記
> 「ドロップされた側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Drag 系のイベントが使われますが、
> 「ドラッグされる側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Mouse 系のイベントを使った方が便利です。
作ってみました。こういうイメージで良いのかな。
Public Class Form1
#Region "コントロールの配置処理"
Private panel1 As New FlowLayoutPanel() With {.AutoScroll = True, .Dock = DockStyle.Fill}
Private labels As New List(Of Label)() With {.Capacity = 1000}
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
'1000 個のラベルを載せたパネルを生成
Controls.Add(panel1)
For l As Integer = 0 To 999
Dim lbl As New Label()
lbl.AutoSize = True
lbl.BorderStyle = BorderStyle.Fixed3D
lbl.Text = l.ToString("000")
AddHandler lbl.MouseUp, AddressOf labels_MouseUp
AddHandler lbl.MouseDown, AddressOf labels_MouseDown
AddHandler lbl.MouseMove, AddressOf labels_MouseMove
labels.Add(lbl)
Next
panel1.Controls.AddRange(labels.ToArray())
'AutoScroll の領域を再計算させるためのおまじない
Me.Width += 32
Me.Width -= 32
End Sub
#End Region
#Region "ドラッグ & ドロップ処理"
'ドラッグの開始元/終了先の番号(0〜999)。-1 なら領域外。
Private labelFrom As Integer = -1
Private labelTo As Integer = -1
Private Sub labels_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
If e.Button = MouseButtons.Left Then
labelFrom = labels.FindIndex(Function(lbl) lbl Is sender)
AddHandler Application.Idle, AddressOf AppIdle
Else
labelFrom = -1
End If
labelTo = labelFrom
End Sub
Private Sub labels_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
If labelFrom >= 0 Then
Dim pos As Point = panel1.PointToClient(Cursor.Position)
labelTo = labels.FindIndex(Function(lbl) lbl.Bounds.Contains(pos))
End If
End Sub
Private Sub labels_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
If labelFrom >= 0 Then
RemoveHandler Application.Idle, AddressOf AppIdle
UpdateLabelColor()
labelFrom = -1
labelTo = -1
End If
End Sub
#End Region
#Region "ラベルの背景を着色"
Private Sub UpdateLabelColor()
For l As Integer = 0 To labels.Count - 1
If labelTo >= 0 AndAlso l.Between(labelFrom, labelTo) Then
labels(l).BackColor = Color.Gold
Else
labels(l).ResetBackColor()
End If
Next
End Sub
Private Sub AppIdle(ByVal sender As Object, ByVal e As EventArgs)
UpdateLabelColor()
End Sub
#End Region
End Class
#Region "ヘルパーメソッド"
Public Module Sample
<System.Runtime.CompilerServices.Extension()> _
Public Function Between(Of T As IComparable)(ByVal value As T, ByVal lower As T, ByVal higher As T) As Boolean
If lower.CompareTo(higher) < 0 Then
Return lower.CompareTo(value) <= 0 AndAlso value.CompareTo(higher) <= 0
Else
Return higher.CompareTo(value) <= 0 AndAlso value.CompareTo(lower) <= 0
End If
End Function
End Module
#End Region
|