Drag and Drop images

Posted on 2011-03-24
Last Modified: 2012-05-11
I built an application where you drag and drop images from one place to another.
Then user, now, wants to see the image is being dragged. For example, when you drag and you go to the drop point it shows you a rectangle with an arrow that tells yuo that you can drop it there.

Is there a way you can see what's being dragged. Take the example of the windows solitaire game where you can see the card at every moment.

Question by:arcross

Accepted Solution

Labelsoft earned 250 total points
ID: 35206111
That is indeed not a standard functionality from .NET. There is however a relatively easy way to implement this. It's explained here:

It's in C# sorry, but I bet you'll figure it out.
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35207168 either:
(1) Use a custom cursor as in Labelsoft's example
(2) Physically change the position of the "thing" during the drag.

Can you give more details about the setup of your application?

Author Comment

ID: 35207345
Basically, this person wants to modify something i did long time ago to use it in a 'smartboard' to teach kids some basic maths. For example, multiplication tables dragging the solutions into different boxes, and few other similar games....
Since it is going to be used (and dragged) by little kiddos id like it to look a little more animated and also they d know at every moment what they d be dragging.
LVL 38

Assisted Solution

by:Tom Beck
Tom Beck earned 250 total points
ID: 35215582
A while back I developed an application in VB for dragging photos to re-arrange them. The application accomplished your requirement of keeping images visible as you drag them. It also prevents users from dropping images on any place other than a valid drop point and locks the image into the new position so everything stays lined up. I thought it might work for you so I extracted the relevant code and made a new working sample. You will have to create three 128 x 128 pixel images and load them into ImageList1 to make this work. A simple white background image with a number in the middle would be adequate.

Note that there are two code sections, one for the form designer and one for the VB code.

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class DragAndDrop
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing AndAlso components IsNot Nothing Then
            End If
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(DragAndDrop))
        Me.Panel1 = New System.Windows.Forms.Panel
        Me.dropPoint3 = New System.Windows.Forms.Panel
        Me.dropPoint2 = New System.Windows.Forms.Panel
        Me.dropPoint1 = New System.Windows.Forms.Panel
        Me.pic3 = New System.Windows.Forms.Panel
        Me.pic2 = New System.Windows.Forms.Panel
        Me.pic1 = New System.Windows.Forms.Panel
        Me.ImageList1 = New System.Windows.Forms.ImageList(Me.components)
        Me.Panel1.AllowDrop = True
        Me.Panel1.BackColor = System.Drawing.Color.FromArgb(CType(CType(239, Byte), Integer), CType(CType(236, Byte), Integer), CType(CType(185, Byte), Integer))
        Me.Panel1.Location = New System.Drawing.Point(12, 12)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(323, 418)
        Me.Panel1.TabIndex = 1
        Me.dropPoint3.BackColor = System.Drawing.Color.FromArgb(CType(CType(255, Byte), Integer), CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer))
        Me.dropPoint3.Location = New System.Drawing.Point(180, 278)
        Me.dropPoint3.Name = "dropPoint3"
        Me.dropPoint3.Size = New System.Drawing.Size(128, 128)
        Me.dropPoint3.TabIndex = 45
        Me.dropPoint2.BackColor = System.Drawing.Color.FromArgb(CType(CType(255, Byte), Integer), CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer))
        Me.dropPoint2.Location = New System.Drawing.Point(180, 143)
        Me.dropPoint2.Name = "dropPoint2"
        Me.dropPoint2.Size = New System.Drawing.Size(128, 128)
        Me.dropPoint2.TabIndex = 40
        Me.dropPoint1.BackColor = System.Drawing.Color.FromArgb(CType(CType(255, Byte), Integer), CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer))
        Me.dropPoint1.Location = New System.Drawing.Point(180, 9)
        Me.dropPoint1.Name = "dropPoint1"
        Me.dropPoint1.Size = New System.Drawing.Size(128, 128)
        Me.dropPoint1.TabIndex = 35
        Me.pic3.AllowDrop = True
        Me.pic3.Location = New System.Drawing.Point(14, 279)
        Me.pic3.Name = "pic3"
        Me.pic3.Size = New System.Drawing.Size(128, 128)
        Me.pic3.TabIndex = 10
        Me.pic2.AllowDrop = True
        Me.pic2.Location = New System.Drawing.Point(14, 144)
        Me.pic2.Name = "pic2"
        Me.pic2.Size = New System.Drawing.Size(128, 128)
        Me.pic2.TabIndex = 5
        Me.pic1.AllowDrop = True
        Me.pic1.Location = New System.Drawing.Point(14, 9)
        Me.pic1.Name = "pic1"
        Me.pic1.Size = New System.Drawing.Size(128, 128)
        Me.pic1.TabIndex = 0
        Me.ImageList1.ImageStream = CType(resources.GetObject("ImageList1.ImageStream"), System.Windows.Forms.ImageListStreamer)
        Me.ImageList1.TransparentColor = System.Drawing.Color.Transparent
        Me.ImageList1.Images.SetKeyName(0, "1.jpg")
        Me.ImageList1.Images.SetKeyName(1, "2.jpg")
        Me.ImageList1.Images.SetKeyName(2, "3.jpg")
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(347, 445)
        Me.Name = "DragAndDrop"
        Me.Text = "DragAndDrop"

    End Sub
    Friend WithEvents Panel1 As System.Windows.Forms.Panel
    Friend WithEvents dropPoint3 As System.Windows.Forms.Panel
    Friend WithEvents dropPoint2 As System.Windows.Forms.Panel
    Friend WithEvents dropPoint1 As System.Windows.Forms.Panel
    Friend WithEvents pic3 As System.Windows.Forms.Panel
    Friend WithEvents pic2 As System.Windows.Forms.Panel
    Friend WithEvents pic1 As System.Windows.Forms.Panel
    Friend WithEvents ImageList1 As System.Windows.Forms.ImageList
End Class

'''VB CODE''

Public Class DragAndDrop

    Dim photos As ArrayList
    Private Dragging As Boolean = False
    Private allPanels() As Panel
    Private allDropPoints() As Panel
    Private WithEvents replacementPanel As Panel
    Private draggedPhoto As Panel = Nothing
    Private imageNumber As Integer = 0
    Private firstMove As Boolean = True
    Private locInPhoto As Point
    Private canDrop As Boolean = False
    Private curRow As Integer = 0

    Private Sub DragAndDrop_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load = New ArrayList
        For Each photo As Image In Me.ImageList1.Images
        Me.allPanels = New Panel() {Me.pic1, Me.pic2, Me.pic3}
        Me.allDropPoints = New Panel() {Me.dropPoint1, Me.dropPoint2, Me.dropPoint3}
    End Sub

    Private Sub AddPhotos()
        For i As Integer = 0 To - 1
            Me.allPanels(i).BackgroundImage = 'Add image to panel
    End Sub

    Private Sub PicBox_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic1.MouseDown, pic2.MouseDown, pic3.MouseDown
        'This sub runs once when the mouse button hits the bottom of a click
        Dragging = True
        Me.replacementPanel = New Panel      'New, movable, panel to replace the one clicked on
        Dim imageNum As String = sender.Name 'Extract the panel number being dragged
        imageNum = imageNum.Substring(3)
        Me.imageNumber = CType(imageNum, Integer) - 1
        Me.draggedPhoto = allPanels(Me.imageNumber)
        Me.replacementPanel.Height = 128
        Me.replacementPanel.Width = 128
        Me.replacementPanel.BackgroundImage = Me.draggedPhoto.BackgroundImage()
        AddHandler Me.draggedPhoto.MouseMove, AddressOf PicBox_MouseMove
        AddHandler Me.draggedPhoto.MouseUp, AddressOf PicBox_MouseUp
        Me.replacementPanel.Location = Me.draggedPhoto.Location
        Me.draggedPhoto.Visible = False  'Hide the original panel 
    End Sub

    Private Sub PicBox_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        'This sub runs repeatedly as the photo is being dragged
        Dim pLoc As Point
        pLoc = Me.Panel1.PointToClient(Cursor.Position)  'Position of cursor relative to the top left corner of the main panel's borders
        If Me.firstMove Then  'If the move is just staring, get the position of the cursor relative to the dragged panel's top left corner 
            Me.locInPhoto = Me.draggedPhoto.PointToClient(Cursor.Position)
            Me.firstMove = False
        End If
        Dim loc As Point
        loc.X = pLoc.X - Me.locInPhoto.X  'adjust the replacement panel's position to reflect where it was clicked to prevent it from jumping too far from the originals's position
        loc.Y = pLoc.Y - Me.locInPhoto.Y
        If Dragging Then
            Me.replacementPanel.Location = loc
            canDrop = False
            Me.curRow = 0
            Dim curPanel As String = ""
            loc.X = loc.X + Me.locInPhoto.X  'Add back the correction made above to get the actual cursor position
            'set the row of the drop point that the cursor is currently passing over
            If loc.X > 180 Then 'then we know the image has been dragged far enough right to be over a drop point
                loc.Y = loc.Y + Me.locInPhoto.Y  'Add back the correction made above to get the actual cursor position
                Select Case loc.Y  'determine wich row the user is dragging the image to
                    Case Me.allDropPoints(0).Location.Y To (Me.allDropPoints(0).Location.Y + 128)
                        curRow = 1
                    Case Me.allDropPoints(1).Location.Y To (Me.allDropPoints(1).Location.Y + 128)
                        curRow = 2
                    Case Me.allDropPoints(2).Location.Y To (Me.allDropPoints(2).Location.Y + 128)
                        curRow = 3
                End Select
            End If
            If Not Me.curRow = 0 Then
                canDrop = True
            End If
        End If
    End Sub

    Private Sub PicBox_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        If Dragging Then
            Dragging = False
            RemoveHandler Me.draggedPhoto.MouseMove, AddressOf PicBox_MouseMove
            If canDrop Then 'If the cursor is over the drop point...
                Me.draggedPhoto.Visible = True 'Restore the original photo
                Me.draggedPhoto.Location = Me.allDropPoints(Me.curRow - 1).Location
                Me.allDropPoints(Me.curRow - 1).Visible = False
                Me.replacementPanel.Visible = False  'Hide the replacement
                Me.replacementPanel = Nothing
                Me.imageNumber = 0
            Else '..the cursor is not over a drop point. Undo the move.
                Me.draggedPhoto.Visible = True
                Me.replacementPanel.Visible = False
                Me.replacementPanel = Nothing
            End If
        End If
    End Sub
End Class

Open in new window


Expert Comment

ID: 35215713
You could also try WPF by the way. The support for drag & drop and graphics are amazing.

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
DataGridView 2 29
reports, calling from code. 3 30
Round up to 100% in .NET 10 44
Protecting vb6 & .Net code Obfuscation 18 51
Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String ( Literal, only instead of starting and ending with w…
Introduction When many people think of the WebBrowser ( control, they immediately think of a control which allows the viewing and navigation of web pages. While this is true, it's a…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now