Drag and Drop images between numerous picture boxes

删除回忆录丶 提交于 2019-12-11 11:37:26

问题


I'm working on a form that has ten picture boxes. Children should be able to drag a picture from one picture box to any of the others. I read an excellent Microsoft article that explained the steps in setting up a drag/drop between two picture boxes. There were five sub routines to drag and drop one way into a second picture box.

My concern is that if the form has ten picture boxes, and the user can drag/drop between any of the ten boxes, that is a lot of code and and a lot of sub routines.

Is there a more elegant way to do this? I've put the code below for utilizing drag/drop between two picture boxes. I'm using Visual Basic 2010 Express. Thanks.

' Enable dropping.
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As  _
        System.EventArgs) Handles MyBase.Load
            PictureBox2.AllowDrop = True
        End Sub
' Set a flag to show that the mouse is down for PictureBox1
        Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As  _
        System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
            If Not PictureBox1.Image Is Nothing Then
                MouseIsDown = True
            End If
        End Sub
' Initiate dragging and allow either copy or move for PictureBox1
        Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As  _
        System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
            If MouseIsDown Then
                PictureBox1.DoDragDrop(PictureBox1.Image, DragDropEffects.Copy Or _
        DragDropEffects.Move)
            End If
            MouseIsDown = False
        End Sub
 'Copy or Move data from PictureBox1
        Private Sub PictureBox1_DragEnter(ByVal sender As Object, ByVal e As  _
        System.Windows.Forms.DragEventArgs) Handles PictureBox1.DragEnter
            If e.Data.GetDataPresent(DataFormats.Bitmap) Then
                ' Check for the CTRL key. 
                If e.KeyState = 9 Then
                e.Effect = DragDropEffects.Copy
                Else
                    e.Effect = DragDropEffects.Move
                End If
            Else
                e.Effect = DragDropEffects.None
            End If
         End Sub
 ' Assign the image to the PictureBox2
        Private Sub PictureBox2_DragDrop(ByVal sender As Object, ByVal e As  _
        System.Windows.Forms.DragEventArgs) Handles PictureBox2.DragDrop
            PictureBox2.Image = e.Data.GetData(DataFormats.Bitmap)
            ' If the CTRL key is not pressed, delete the source picture.
            If Not e.KeyState = 8 Then
                 PictureBox1.Image = Nothing
            End If
         End Sub

回答1:


You can use AddHandler to wire up any number of PictureBoxes to the same handler methods. The "sender" parameter in those handlers will tell you which PictureBox is the source of the event. Note in the code below that none of the methods have the "Handles" clause at the ends of them; everything is being wired up dynamically in the Load() event of the Form. All PictureBoxes that are contained directly by the Form will be wired up. In my test project I placed ten of them on the Form:

Public Class Form1

    Private Source As PictureBox = Nothing

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each PB As PictureBox In Me.Controls.OfType(Of PictureBox)()
            PB.AllowDrop = True
            AddHandler PB.MouseMove, AddressOf PBs_MouseMove
            AddHandler PB.DragEnter, AddressOf PBs_DragEnter
            AddHandler PB.DragDrop, AddressOf PBs_DragDrop
            AddHandler PB.DragOver, AddressOf PBs_DragOver
        Next
    End Sub

    Private Sub PBs_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        Dim PB As PictureBox = DirectCast(sender, PictureBox)
        If Not IsNothing(PB.Image) AndAlso e.Button = Windows.Forms.MouseButtons.Left Then
            Source = PB
            PB.DoDragDrop(PB.Image, DragDropEffects.Copy Or DragDropEffects.Move)
        End If
    End Sub

    Private Sub PBs_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs)
        If e.Data.GetDataPresent(DataFormats.Bitmap) Then
            If My.Computer.Keyboard.CtrlKeyDown Then
                e.Effect = DragDropEffects.Copy
            Else
                e.Effect = DragDropEffects.Move
            End If
        Else
            e.Effect = DragDropEffects.None
        End If
    End Sub

    Private Sub PBs_DragOver(sender As Object, e As DragEventArgs)
        If e.Data.GetDataPresent(DataFormats.Bitmap) Then
            If My.Computer.Keyboard.CtrlKeyDown Then
                e.Effect = DragDropEffects.Copy
            Else
                e.Effect = DragDropEffects.Move
            End If
        Else
            e.Effect = DragDropEffects.None
        End If
    End Sub

    Private Sub PBs_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs)
        Dim PB As PictureBox = DirectCast(sender, PictureBox)
        PB.Image = e.Data.GetData(DataFormats.Bitmap)
        If e.Effect = DragDropEffects.Move Then
            If Not (PB Is Source) Then
                Source.Image = Nothing
            End If
        End If
    End Sub

End Class

From the comments:

Using the AddHandlers, is it possible to "swap" two pictures with one drag/drop?

It certainly is; and is quite easy. With the change in code below to DragDrop(), the default behavior for Move will be to Swap the two images. If they hold down Ctrl to Copy then it will overwrite without swapping:

Private Sub PBs_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs)
    Dim PB As PictureBox = DirectCast(sender, PictureBox)
    Dim tmpImage As Image = PB.Image ' store the current image
    PB.Image = e.Data.GetData(DataFormats.Bitmap) ' change it to the dropped image
    If e.Effect = DragDropEffects.Move Then
        If Not (PB Is Source) Then
            Source.Image = tmpImage ' put the stored image in the source picturebox (swap)
        End If
    End If
End Sub

From the comments:

How would I exclude one specific picturebox from being "draggable"?

In the Load() event, you'd check for the PB to exclude in the loop. For example, this would exclude "PictureBox1":

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    For Each PB As PictureBox In Me.Controls.OfType(Of PictureBox)()
        If Not (PB Is PictureBox1) Then
            PB.AllowDrop = True
            AddHandler PB.MouseMove, AddressOf PBs_MouseMove
            AddHandler PB.DragEnter, AddressOf PBs_DragEnter
            AddHandler PB.DragDrop, AddressOf PBs_DragDrop
            AddHandler PB.DragOver, AddressOf PBs_DragOver
        End If
    Next
End Sub



回答2:


Regarding my last question about excluding certain pictureboxes from being draggable (see last comment), I discovered the "enabled" property of pictureboxes. It was quite easy to turn that property on or off as needed.



来源:https://stackoverflow.com/questions/27537362/drag-and-drop-images-between-numerous-picture-boxes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!