|
VB .NET Techniques and References
|
|
|
Drag and Drop
|
|
Table of Contents
Screen Coordinates
As you work with the mouse and graphics, you will need to work with coordinates.
VB .NET uses two coordinate systems and this can be somewhat confusing.
In both systems the X axis is the horizontal axis where 0 is the leftmost position,
and the Y axis is the vertical axis where 0 is the topmost position.
Both systems use pixels as a default measure. You can change this measure, but there is no need to.
In both systems, each position is represented by an object of class
Point which is mostly a set of X,Y coordinates.
Here is how the two systems differ:
Absolute screen coordinates
These coordinates are the coordinates of an actual pixel on the physical screen.
The set of coordinates is called a Position and the coordinates are X and Y.
Coordinates relative to a form or control (called Client coordinates)
The position of an object A which is contained in an object B is given in terms
of coordinates relative to object B.
For example, the location of the panel that contains the tiles is relative to the form that it belongs to
and the location of all the tiles are relative to the panel that they belong to.
In this system the position is usually called a Location
and the individual coordinates are called X and Y.
What coordinates are used by the mouse?
Mouse events return client coordinates, which is exactly what you want most of the time.
You can also access the screen coordinates if you need them,
either by using the MousePosition property of a control over which the mouse happens to be,
or the Cursor.Position property which is a property of the entire cursor class that simply
tells you where the mouse is on the screen. You will not need these for this assignment
though.
Dragging and Dropping Objects
You will find out information about how to work with the mouse in .NET at
Mouse Input in a Windows Forms Application.
This page also contains a lot of information about how to use the built-in drag and drop features
of .NET. Unfortunately, this bruilt-in drag and drop functionality does not work satisfactorily:
it does not move an object, but moves a special cursor instead.
Therefore you should ignore the built-in drag and drop functionality
and implement your own drag and drop routines instead.
In order to do this, you will need to work with 3
mouse events:
MouseDown, MouseMove, MouseUp.
Here are the steps that you need to follow to implement your own drag and drop of an object:
- When the mouse is pressed down on the object:
- remember the position of the mouse inside the object to use later to implement a smooth motion of the object;
this position is provided in the parameters of the MouseDown event.
- tell your object that it is being moved.
Controls already have a property specifically for that: the
Capture Property.
It is normally used with the built-in .NET drag and drop routines, but you can use it with your own drag and drop.
- Make sure that your object is in front of all the others if you don't want it to slide behing
other objects as you drag it. This is done with the BringToFront() method.
- When the mouse moves over the object:
If the object is being moved (i.e. Capture is true), then
move the object exactly like the mouse was moved.
- You will get the new position of the mouse on the object from the MouseMove event
- You should know the original position of the mouse because you stored it when the mouse was pressed down.
- You can move an object by setting new values for its Location property.
For example, to move an object to a new location (x,y) relative to its container, do:
Me.Location = New Drawing.Point(x, y)
- When the mouse is released on the object:
tell the object that it is not being moved anymore.
Mouse Cursor
You can dynamically change the cursor that is associated with a control or form
by simply changing the value of that form's Cursor property.
You can get cursors 2 ways:
-
You can design your own cursors directly in Visual Studio by adding a new item which is a cursor:
- Add a new item which is a cursor file and give it a good name.
- Use the cursor designer to design your cursor. Every cursor has a "hotspot"
which is the actual location of the mouse pointer inside the cursor. Don't forget to
specify that hot spot.
- Save your cursor file.
-
You can use the
hand cursors provided to you and the system "no" cursor.
Simply add each file to your project using "Add existing item".
No matter which of these 2 methods you use, you will end up with cursor files which are part of
your project. However, at this point, they are only files which are associated with your project.
If you want to use them at run time, you can either
- deploy them with your project and read them in at run time, or
- imbed them into the project so they are compiled with it.
This is preferable because cursors don't take up much space in a project and you will have fewer files to deploy.
To do this, select in the Solution Explorer each cursor file you want to use
and change its Build Action property to "Embedded Resource".
Finally, you will need to turn these resources into instances of the class Cursor that you
can use in Visual Basic.
A simple way to do this is to keep them as static (class variables)
of the class where they will be used (e.g in the MyShape class below)
Public Class MyShape
...
Shared HandPointCursor As Cursor= New Cursor(GetType(MyShape), "H_POINT.CUR")
Shared HandMoveCursor As Cursor = New Cursor(GetType(MyShape), "H_MOVE.CUR")
' Note that in both cases, the Type passed to the constructor is the type of the object
' that will contain the cursor, i.e. a MyShape in this case
...
End Class
Then whenever you want to change the shape of the cursor as it passes over
a specific object, just change the Cursor property of that object.
More explanations are available at the
Mouse Pointers in Windows Forms page
When you implement your custom drag and drop routines as described above,
the mouse will always be above the dragged object and therefore only that object will
detect mouse movements.
Other objects in the interface will not have any default way of knowing if the dragged object is over them.
Therefore, in order to detect that an object A is passing over an object B,
object B needs to be asked whether this is the case based on information it receives about A.
In order to have each object in the form detect whether a specific object A is dragged over it,
the form needs to poll all its objects asking them one by one whether A is dragged over it.
Forms already contains a field with a list of all its controls, Me.Controls,
so if you need to poll all the controls in a form, you can use that field.
If, on the other hand, you only want to poll a specific set of controls,
then you will need to keep a separate list of these controls.
.NET has a method to help you figure out whether two rectangles intersect:
Rectangle.IntersectsWith method
This page is maintained by
Sophie Quigley
(cps613@cs.torontomu.ca)
Last modified
Sunday, 30-Oct-2022 09:58:45 EDT