投稿者 魔界の仮面弁士  (社会人) 投稿日時 2016/10/12 11:47:40
案1 で作ってみました。
古いバージョン(VB.NET 2002 など)だと使えない機能も含まれていますが御容赦を。

Ctrl を押しながら左ドラッグを開始すればコピーになりますが、
(左ドラッグを始めてから Ctrl を押すのはNG)

ついでに、ドラッグ中に[Esc]が押されたらドラッグ処理をキャンセルさせています。

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 ObjectByVal 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 ObjectByVal 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 ObjectByVal 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