Public Class Form1 Private dragTarget As Control = Nothing Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load KeyPreview = True 'コントロールをドラッグ可能にする AddHandler TextBox1.MouseDown, AddressOf Target_MouseDown AddHandler Label1.MouseDown, AddressOf Target_MouseDown AddHandler CheckBox1.MouseDown, AddressOf Target_MouseDown End Sub Private Sub Target_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) If e.Button <> System.Windows.Forms.MouseButtons.Left Then Return End If 'ドラッグされたコントロール自身 Dim this As Control = DirectCast(sender, Control) 'Ctrl が押されていたかどうか Dim isCopy As Boolean = (Control.ModifierKeys And Keys.Control) = Keys.Control 'Ctrl が押されていなければ自身をセット '押されてたらコントロールを複製してセット If isCopy Then '新しいコントロールを作成し、位置・サイズ・内容等を複製 dragTarget = DirectCast(Activator.CreateInstance(this.GetType()), Control) dragTarget.Text = this.Text dragTarget.Parent = this.Parent dragTarget.SetBounds(this.Left, this.Top, this.Width, this.Height) this.Capture = False dragTarget.Visible = True dragTarget.BringToFront() dragTarget.Focus() dragTarget.Capture = True AddHandler dragTarget.MouseDown, AddressOf Target_MouseDown Else dragTarget = this End If Cursor = Cursors.Hand 'コピーと移動でカーソルを変えるのも良いかも '現在の位置情報を Tag プロパティに保存しています Dim oldPos As Point = dragTarget.Location Dim dragOffset As Size = dragTarget.Parent.PointToClient(MousePosition) - oldPos dragTarget.Tag = New Object() {dragOffset, oldPos, isCopy} 'イベントを動的に付与します AddHandler dragTarget.MouseMove, AddressOf Target_MouseMove AddHandler dragTarget.MouseUp, AddressOf Target_MouseUp End Sub Private Sub Target_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) If dragTarget Is Nothing Then Return End If 'Tag プロパティに保存していた位置情報を復元 Dim target As Control = DirectCast(sender, Control) Dim pack() As Object = CType(target.Tag, Object()) Dim dragOffset As Size = CType(pack(0), Size) Dim oldPos As Point = CType(pack(1), Point) '現在の位置情報 Dim curPos As Point = target.Parent.PointToClient(MousePosition) - dragOffset '縦横どちらに多く動かしたかを調べて、 '垂直移動と水平移動を切り替えています Dim moveOffset As New Size(Math.Abs(curPos.X - oldPos.X), Math.Abs(curPos.Y - oldPos.Y)) If moveOffset.Width = moveOffset.Height Then target.Location = oldPos ElseIf moveOffset.Width < moveOffset.Height Then target.Location = New Point(oldPos.X, curPos.Y) ElseIf moveOffset.Width > moveOffset.Height Then target.Location = New Point(curPos.X, oldPos.Y) End If End Sub Private Sub Target_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) If dragTarget IsNot Nothing AndAlso e.Button = System.Windows.Forms.MouseButtons.Left Then Dim target As Control = DirectCast(sender, Control) EndDrag(target) End If End Sub 'ドラッグを完了させる Private Sub EndDrag(ByVal target As Control) RemoveHandler target.MouseUp, AddressOf Target_MouseUp RemoveHandler target.MouseMove, AddressOf Target_MouseMove Cursor = Cursors.Default target.Tag = Nothing dragTarget = Nothing End Sub Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 'Esc が押されたらドラッグをキャンセル If dragTarget IsNot Nothing AndAlso e.KeyCode = Keys.Escape Then Dim pack() As Object = CType(dragTarget.Tag, Object()) If CBool(pack(2)) Then 'コピー中のコントロールを破棄 Using dragTarget dragTarget.Parent.Controls.Remove(dragTarget) EndDrag(dragTarget) End Using Else '移動中のコントロールの位置を戻す dragTarget.Location = CType(pack(1), Point) EndDrag(dragTarget) End If End If End Sub End Class