Beginning Visual Basic (Visual Studio 2008) - Project 4

Dragging and Dropping with the Mouse

Project 4

In your fourth Visual Basic project you will enhance the 3rd Project. In addition to pointing and clicking on the form to move the PictureBoxes, you will enable clicking and dragging them with the mouse.

Creating Project 4 from Project 3

Open Project3-4 by selecting it on the start page, as shown:

You may also open it by selected Open Project on the File drop-down menu.

Rename the Form file by changing its File Name property 

Select the frmProj3.vb form file in the Solution Explorer window, as shown:

Change the File Name property from frmProj3.vb to frmProj4.vb:

Renaming the form file should have automatically rename the form as well.  In design view click once on the form to select it and display its properties in the Properties Window.  Be sure that the Name property of the form is now frmProj4 and change the Text property of the form to Project 4, as shown:

Before going on, click on the Save All button on the toolbar to save your project.
 


Setting the AllowDrop property to enable Dragging and Dropping on a form

By default, the AllowDrop property of every control is set to False.  This prevents the control from detecting if something has been dragged and dropped onto it.  To allow dragging and dropping on our form, select the form in design view, so that it's properties are displayed in the Properties window, and set it's AllowDrop property to True, as shown:

Using the DoDragDrop method, and the DragEnter and DragDrop event procedures

The DoDragDrop method of the PictureBoxes allows the user to drag and drop them.  Let's do the code for the picCircles picturebox first.  Add the following code to the picCircles_MouseDown event procedure so that Dragging will be enabled when the user points at the picCircles picturebox and clicks down on the left mouse button:

'Allow dragging only if the rdoCircles radio button
'    is on and the user clicks down on the Left
'    mouse button.
If rdoCircles.Checked = True And _
    e.
Button =
Windows.Forms.MouseButtons.Left Then
    picCircles.DoDragDrop( _
        picCircles,
DragDropEffects.Move)
End If

The DoDragDrop method requires two parameters, they are:

    picCircles.DoDragDrop(picCircles, DragDropEffects.Move)
 

  1. The object to be dragged.  In our case we use the name of the picturebox itself (picCircles) since the entire picturebox control is being moved.  If we wanted to copy just the Image from the picturebox to another picturebox (for example) we would have used picCircles.Image for this parameter.
  2. The DragDropEffects specification.  There are several choices that include Move, Copy, None, etc.  This changes how the mouse cursor looks during the actual dragging process.

An object's DragEnter event procedure is raised once when the user drags something onto it.  We must include a DragDropEffects specification here to control how the mouse pointer appears as dragging is happening.  This may seem redundant after including the DragDropEffects.Move parameter in the call to the DoDragDrop method of the picturebox (above in picCircles_MouseDown).  But this is important because it allows us to dynamically change the appearance of the mouse pointer as we drag it over different controls on our form—more on this later.  Add the following line of code to the DragEnter event procedure of the form.  Note: To access the Event Procedures of the form, drop down the Class Name list at the top left side of the code window and choose (frmProj4 Events).  Then choose the DragEnter event procedure from the Method Name list at the top right side of the code window.  Add the following line of code to the frmProj4_DragEnter event procedure:

'Apply the Move effect to the mouse pointer
'    while dragging.
e.Effect = DragDropEffects.Move

The e parameter of the DragEnter event procedure—and all other Drag related event procedures such as DragOver, DragDrop, and DragLeave—has information about the item that is actually being dragged.  The e's Effect property (shown in the illustration below) is set to the DragDropEffects specification that the mouse will display while being dragged over the object:

The DragDrop event procedure of the form is where we add the code that actually moves the PictureBox to where the user drops it.  In fact, the user never really drags the object at all.  The dragging effect is all they see—the object is not actually moving as they are dragging it.  We need to add the code to move the object to the location they actually drop it.  Add the following code to the frmProj4_DragDrop event procedure:

Dim MyForm As Form
'To access the properties of the sender object you
'    need to dimension an object variable of the
'    sender type (Form in this case) and reference
'    the sender object with it.
MyForm = sender
'Move the PictureBox if its radio button is on.
If rdoCircles.Checked = True Then
   
picCircles.Left = e.X - MyForm.Location.X
   
picCircles.Top = e.Y - MyForm.Location.Y
End If

Normally e.X and e.Y would represent the location of the mouse pointer relative to the upper left corner of the form—as they do in the form's MouseDown, MouseUp, and MouseMove event procedures.  But in the DragDrop event procedure e is a DragEventArgs type not a MouseEventArgs type.  So e.X and e.Y represent the location of the mouse point relative to the upper left corner of the screen, NOT the form!  To calculate X and Y coordinate values relative to the upper left corner of the form, we need to subtract the X and Y coordinates values of the form's position on the screen (MyForm.Location.X and MyForm.Location.Y) from e.X and e.Y. We did this in the above code to give us the actual mouse pointer location relative to the upper left corner of the form. 

Testing the program so far

Click on the Save All button on the toolbar to save your project.  Now click the start debugging button to run the project.  With the Circles radio button selected, click on and drag the picCircles picturebox down a few inches on the form and drop it.  Did it move?  Did the mouse pointer change while you where dragging it to indicate that dragging was happening?  What happens when you drop the picCircles picturebox on top of one of your buttons?  Does the picturebox end up on top of the button, or behind it?  Right now the picturebox ends up below and to the right of the mouse pointer when we drop it.  That needs to be fixed.

Improving the Drag and Drop effect and other minor issues

First of all, let's make sure that the PictureBoxes don't end up behind any of the other controls when they are dropped.  One control can be on top of another, or behind it, depending upon it's location in the z-order.  The z-order is the 3rd dimension on a form.  All controls have BringToFront and SendToBack methods so that you can use code to change where they are in the z-order.  The z-order only affects controls on the same form (or in the same container control, like a GroupBox).  To make sure that the PictureBoxes don't end up behind any of the other controls when they are dropped, we need to bring them to the front of the z-order.  This is easy to do at design time.  Select all three PictureBoxes—click on picCircles to select it, then hold down the shift key and click on the other two pictureboxes to select them as well. Now right-click on one of them.  Choose Bring to Front on the context menu (as shown below), to bring all three of them to the top of the z-order:

If the picCircles picturebox was dropping behind any of the buttons during your first test run of the program, run the program now and test it.  The picCircles picturebox will drop on top of the buttons and radio buttons from now on.

As it is now, when you drop the picturebox it is moved to a position below and to the right of the mouse pointer.  This just doesn't look right.  One thing that we didn't take into account when we calculated the position of the mouse pointer in the frmProj4_DragDrop event procedure was the border width of the form, and the height of the caption at the top of the form.   Let's add those values to our location calculation in the frmProj4_DragDrop event procedure.  Begin by add these two lines of code to the Declarations section at the top of the code view window (add the following two lines of code below the dimension statements for iCircleX, iCircleY, etc.)

'The form's border is 4 Pixels wide
Const FORM_BORDER = 4
'The form's caption bar is 30 Pixels high
Const FORM_CAPTION = 30

Your declarations section should now look something like this:

The addition of these two lines of code create two constants.  A constant is a descriptive name that represents some value.  By using constants with descriptive names in your code instead of the values they represent, it makes your code much easier to read.  Modify the the two lines of code that set the Left and Top properties of the picCircles picturebox in the fromProj4_DragDrop event procedure to include these constants, like this:

    picCircles.Left _
        e.
X - MyForm.Location.X - FORM_BORDER
   
picCircles.Top =  _
        e.
Y - MyForm.Location.Y - FORM_CAPTION

Test the program again

Click on the Save All button on the toolbar to save your project.  Now click the start button to run it.  With the Circles radio button selected, click on and drag the picCircles picturebox down a few inches on the form and drop it.  Is the mouse pointer pointing at the upper left corner of the picCircles picturebox?   It should be, because that is the point where the Left and Top property values cross each other. 

It still doesn't look right!

The mouse pointer should be pointing at the center of the picturebox after we move it, not the top left corner of it.  What would happen if we also subtracted half of the value of picCircles.Width from the e.X value, and half of the value of picCircles.Height from the e.Y value?  Would this shift the picturebox so that the mouse pointer was pointing at the center of it?  Modify the the two lines of code that set the Left and Top properties of the picCircles picturebox in the fromProj4_DragDrop event procedure one more time, like this:

    picCircles.Left =  _
        e.
X - MyForm.Location.X - _
       
FORM_BORDER - picCircles.Width / 2
   
picCircles.Top =  _
        e.
Y - MyForm.Location.Y - _
        FORM_CAPTION -
picCircles.Height / 2

Test the program again

What happens now when you drag and drop the picCircles picturebox?  is the mouse pointer left pointing at the center of it when it's dropped?  That looks a lot better!

Moving the PictureBox while it is being dragged - the DragOver event procedure

One other problem is that the picCircles picturebox just sits there while we are dragging it, and doesn't move until it's dropped.  It would look a lot better if it actually moved while we were dragging it.  Instead of moving the picturebox in the DragDrop event procedure of the form, we could move it in the DragOver event procedure.  The DragOver event procedure is raised over and over again as the user drags something over the form. 

Select all the code in frmProj4_DragDrop and move it to the frmProj4_DragOver.

Test the program again

Click on the Save All button on the toolbar to save your project.  Now click the start button to run the project.  What happens when you drag the picCircles picturebox now?  It should move as you are dragging it.

Getting Drag and Drop working for picCarved and picStraw

The code you've added so far to get dragging and dropping working for the picCircles picturebox should help you get dragging and dropping working for the picCarved and picStraw picture boxes.  Use that code as a template and get dragging and dropping working for the picCarved and picStraw picture boxes.

Required Enhancement


Properties/Procedures Table

Properties (all properties set in the previous project remain the same except the Form’s AllowDrop property).

Object Property Setting
Form AllowDrop True

Event Procedures

Not provided.  See the project above.
 


To copy a Project folder from your Projects folder on the Hard Drive to a floppy diskette or pen-drive follow these steps:

  1. Exit Visual Studio 2008 and insert the floppy diskette or pen-drive, that you want to copy the Project3-4 folder to:
  2. Select the My Documents item on the Start Menu to open the My Documents folder.
  3. In the My Documents folder, double-click the Visual Studio 2008 folder to open it.
  4. Double-click on your Projects folder to open it.
  5. Open the Project3-4 folder by double-clicking on it.  Inside the Project3-4 folder, delete the Obj and Bin folders—these folders are created automatically when you open a project.  You do not need to copy them, or their contents, to your floppy diskette or pen-drive.  Important: Be sure not to delete the My Project folder or Resources folder.
  6. Once you have deleted the Obj and Bin folders, hit the Backspace key once—or click the Back button on the toolbar.  This moves you from inside the Project3-4 folder to back inside your Projects folder.
  7. Right-click on the Project3-4 folder and selected: 31/2" Floppy A: or your pen-drive on the Send To fly-out menu.  This copies the Project3-4 folder to your floppy diskette or pen-drive.