The prerequisites for this session are having some familiarity
with Visual FoxPro Forms and the controls we use in those forms. Also being comfortable
with the designers and the property sheets will be helpful in following this session.
The session is aimed at a skill level that is between beginner
and intermediate. The content will cover some issues that are of interest to all skill
levels, including advanced, however the nature of the material is not beyond the
understanding of someone who is just beyond pure beginner.
During this session we will introduce the concept of direct
manipulation as a user interface tool. This will show us that Drag and Drop is one of the
direct manipulation techniques. Drag and Drop is the technique we will dig even deeper
into as a user interface tool understanding the various states of objects during a drag
and drop process. We will compare the two methods of implementing drag and drop in Visual
FoxPro 6.0, the native and the OLE drag and drop methods. Finally, we will focus our
attention on the OLE Drag and Drop implementation in Visual FoxPro 6.0 and examine most of
the basic features of that methodology.
An excellent book about user interface design is About Face The
Essentials of User Interface Design by Alan Cooper. In this book Mr. Cooper describes
three elements that comprise direct manipulation in a use interface.
An even simpler definition of direct manipulation, Cooper says,
would be clicking-and-dragging things around.
However if you review the three items listed above only one is
involved with what the user does, the other two have to do with the visual feedback that
the user gets from the operation. In our later discussion of drag and drop we will present
methods for controlling the visual feedback the user will get.
Lest we venture off thinking that drag and drop is the only
direct manipulation method your users will see, lets just list some of the others. Below
is a list of some of the direct manipulation interfaces you and your users deal with every
The Anatomy of Drag and Drop
The drag and drop process involves two objects, the source
that is the object that originated the drag operation and the target that is the
object being dropped on. The source object is the one that controls the entire drag and
drop process. It is the master of the operation.
There are three states to the drag and drop operation start,
capture, and end. Any well-designed drag and drop interface will provide
visual feedback to the user relaying the state of the operation.
The start is the action that the user must take to initiate the
drag operation. This is usually simply pressing the left mouse button, but could be set up
to require the right button or the shift or control keys with the left button. This is the
beginning of the drag operation.
Is the period when the source is being dragged. During this phase
you are most interested in giving the user feedback indicating that they are dragging
something and whether or not it is currently over a place where it can be dropped.
End of drag is the drop. Here you are concerned with giving the
user clear visual feedback that the drop has occurred and what the effect of that drop has
The Two Types of Drag and Drop
There are two types of drag and drop operations that can be used.
One is the internal or non-negotiated drag and drop. The second is external
or negotiated drag and drop. These two operations differ in that with internal the
source and target of the operation are in the same application and therefore there is no
need for any negotiation between the source and target. With external drag and drop the
source and target of the operation are not in the same application and there is a
necessity for the target and source to negotiate with each other regarding on exactly what
should happen and how it should happen.
Visual FoxPro 6.0 can be the source or the target of an external
drag and drop operation. When it is the target the Visual FoxPro object that receives the
drop must examine the data being dropped to find out what type it is and whether or not it
can accept that type of data. This is the negotiation referred to in the name.
If Visual FoxPro is the source of an external drag operation then
it must place data in the data object of the drag and identify the type that the data is.
This needs to be done so that the target can do the negotiating in order to determine how
to handle the drop.
What Do We Know So Far?
We have now examined the drag and drop operation to expose and
understand the various steps it involves. The phases of the operation are clearly defined
and the nature of the two types, internal and external, drag operations are clear.
Before going further lets put some concerns to rest. Visual
FoxPro handles most of the issues we have described automatically for us. Visual FoxPro,
as it often does, also exposes to us the ability to manage these issues ourselves through
code. I just wanted to eliminate any concerns that may have been developing because of the
number of issues with external drag and drop.
Why Use Drag and Drop At All?
With all of the above concerns why should we consider using drag
and drop in our user interfaces? There are a few very good reasons to implement drag and
drop into your user interface designs.
Provide an intuitive method for the user to interact with the
One of the things that very often put users off in a computer
application is the strange way they have to do things. Most users are not programmers and
they do not think like programmers. Tabbing to a certain control on screen and then
pressing a function key, then tabbing somewhere else and pressing a different function key
in order to take the text in one place and move it to the other place is non-intuitive to
Clicking on the source text and then dragging the mouse to the
target location and letting go of the mouse button is an intuitive method of accomplishing
the same operation.
Efficient method for manipulating two objects, their data, and
I have often heard that a mouse slows computer users down,
however I offer the challenge of coming up with a keyboard only interface that is as
efficient as the Visual FoxPro Form Designer for moving things around on the screen.
Drag and drop is a very efficient method for managing two objects
and their data, or for managing the geography of objects on the screen.
Allows complex operations to have a simple interface
During the presentation I will demonstrate a drag and drop
interface that accomplishes a myriad of activities behind the scenes while the user only
grabs an object, drags it to a location, and drops it there.
Once taught it is seldom forgotten
This may be the single most important reason for using drag and
drop interfaces. I use Microsoft Word for most of my writing. Every now and then I need to
do some kind of special formatting of a document. I get into the help file and look up the
steps in doing that and get it done. You can be guaranteed that the next time I need to do
that I will again be looking up the steps.
However, show a new user how to drag text from one place to
another once and they will likely never forget how to do that.
Visual FoxPro 6.0 and Drag and Drop
Visual FoxPro has had drag and drop capabilities since version
3.0 was released. The implementation of drag and drop in 3.0 and 5.0 were native to Visual
FoxPro and therefore only worked when dragging to and/or from a Visual FoxPro object. This
method of drag and drop is still available in Visual FoxPro 6.0.
Native Drag and Drop
There are a number of events and methods that provide access to
the native drag and drop features. The Drag method starts or stops a drag
operation. The DragMode property can be set to automatically start a drag when the
mouse button was depressed over the control. The DragIcon property assigns a mouse
icon to be used during the dragging of the control.
The three items above are related to the drag source, there are
also two events for the drag targets DragOver and DragDrop. The DragOver
event fires for a control whenever there is something being dragged over that control and
the DragDrop event fire when the item being dragged is dropped on the control. These two
events are passed a number of parameters, DragOver gets 4 and DragDrop gets 3. The
parameters are oSource, nXCoord, nYCoord, and nState. nState is the one that is not
received by the DragDrop event. The oSource parameter is an object reference to the
control that is being dragged. The nXCoord and nYCoord parameters are the x and y position
of the mouse pointer. The nState parameter is one of 3 values 0 meaning the drag is
entering the space over the control, 1 meaning the drag is leaving the space over the
control, or 2 meaning the drag is occurring over the controls space.
There are some advantages to the native drag and drop features of
Visual FoxPro. It is easy to implement and it works very well with the native Visual
FoxPro objects. The major limitation of this drag and drop approach is that it ONLY
works with native Visual FoxPro objects.
This is as deeply as we will venture into the native drag and
drop features of Visual FoxPro in this session. The rest of the time we will spend
investigating the new OLE Drag and Drop features of Visual FoxPro 6.0.
SPECIAL NOTE: Visual FoxPro Native Drag and Drop and OLE Drag and
Drop do NOT work together. This is a one or the other proposition.
Introducing OLE Drag and Drop
Visual FoxPro 6.0 introduces us to OLE Drag and Drop. OLE drag
and drop will allow us to do all of the things we have done with the native drag and drop
features of past versions, but it also enables the drag and drop to originate from or
terminate on a non Visual FoxPro application or control. We can now drag and drop onto an
ActiveX control, or we can drag text from a Visual FoxPro textbox and drop that text in a
Microsoft Word document or an Excel spreadsheet. The flow goes the other way too; we can
drag text from a Microsoft Word document and drop it in a Visual FoxPro editbox.
OLE drag and drop has certain advantages over the native drag and
drop in Visual FoxPro. OLE drag and drop works well with Visual FoxPro native objects just
like the native drag and drop does. OLE drag and drop is relatively easy to implement,
Visual FoxPro automatically handles many of the functions with little or no intervention
by the developer. OLE drag and drop works with all OLE drag and drop enabled applications
which allows the use of drag and drop between Visual FoxPro and other applications. OLE
drag and drop has very flexible data management capabilities. There are at least seven
different data types that may be involved with the OLE drag action.
One difference we should mention right away is that the object
being dragged around is not the control or application that originated the drag operation,
it is a data object that contains the data that was put in it by the source of the drag
operation. We will see later that there is some default data that can get in that data
object, but there are also some methods of that object that allow us to put whatever data
in there that we choose.
New Problems to Conquer
There is no free lunch, with the added capabilities of OLE drag
and drop there are some added problems we need to address. For one the thing being dropped
on our Visual FoxPro control may not be coming from Visual FoxPro at all. This means that
it is possible that a drop may occur on a textbox that is carrying a graph from Microsoft
Excel. Obviously our textbox cant do a whole lot with an Excel graph.
The data being carried by the dragged object can be complex that
is it may be an array of data or a number of data items of different types. Our drop
management will need to deal with this situation.
One of our Visual FoxPro objects may be dragged and dropped in
another application. Now although we have no control over how that other application will
handle the drop, we may need to take certain precautions on our management of the data
object in the drag operation.
Managing OLE Drag and Drop in Visual FoxPro
We will work from the simple to the sublime with this subject.
This session is not intended to produce OLE Drag and Drop experts, but rather to expose us
to the capabilities of OLE Drag and Drop. There will be some examples and demonstrations
of the techniques. We will examine certain of the properties and methods in detail.
However, there will be other properties and methods related to OLE Drag and Drop that we
will not discuss. Those will be left for you to read and learn about on your own.
Starting the Drag
The screen shot shown below figure 1 shows a simple Visual FoxPro
form with two textboxes.
Figure 1 A simple Visual FoxPro form.
We will refer to the text boxes in the form above as text1 and
tgext2 with text1 being the top one. The simplest method for enabling OLE drag and drop
between these two text boxes is to set the OLEDragMode for text1 to 1
Automatic and to set the OLEDropMode for text2 to 1 Enabled.
These settings will allow you to drag the text from Text1 and
drop it on Text2. Text2 will, by default, insert the text being dragged at the point of
the drop. You can also drag the highlighted text from Text1 and drop it into a Microsoft
Word document and the text will be inserted in that document at the drop point as well.
Later we will look into taking more control over the drop action,
but for now lets focus on the drag initiation. In the first example we started the
drag by setting the OLEDragMode to automatic for Text1. Lets now see how we
can start tge drag ourselves.
In the next example the OLEDragMode has been reset to its
default of manual. Instead of using the automatic drag start we will use text1s MouseDown
event to call the OLEDrag method to start the drag. In the MouseDown of Text1 we
have put the following line of code.
LPARAMETERS nButton, nShift, nXCoord, nYCoord
The OLEDrag method will start a drag on the control. This
method takes two arguments a logical .T. will cause the control to delay a short time
before beginning the drag, thus allowing the user to release the mouse button and cancel
the drag. Passing a .F. to the OLEDrag causes the drag to begin immediately with no
delay. In the second form we are still using the OLEDropMode of Enabled for Text2.
Next lets see the insertion of the dragged text at the
location of the drop. We3 have created a new form named Insert.scx. This form has Text1
with the OLEDrag(.T.) in its MouseDown event. However this form has an editbox in
it that has its OLEDropMode set to Enabled. The next two figures 2 and 3 show how
we can drop text at a specific point in the editbox.
Figure 2 A drop insertion before the action.
The next figure shows the form after we have dragged the word
text from the textbox and dropped it before the word dropping in the editbox.
Figure 3 After the drag and drop
Notice that the word test is gone from the te3xtbox, that is
because we did a simple click and drag. If we wanted to copy the word we should have used
a Ctrl-Click and drag.
All of the things you have seen so far are being done through
some very simple settings of the OLEDragMode, OLEDropMode, and the use of
the OLEDrag method.
Giving Feedback to the User
The OLEGiveFeedBack event can be used to set the drag
mouse visual effect. We have entered the following line of code into the Textboxs OLEGiveFeedBack
event of the form seen in figure 3.
eMouseCursor = "dragguy.ani"
Dragguy.ani is an animated mouse cursor that we created. Figure 4
shows the effect (of course you cannot see the animation in the still shot).
Figure 4 Using the OLEGiveFeedBack event to control the visual
feedback to the user
Sensing a Drag Over
The OLEDragOver event will fire whenever an OLE Drag
object is dragged over a control if the OLEDropMode is set to Enabled. There are a
number of parameters that are passed to the OLEDragOver event.
The oDataObject parameter is an object reference to the data
object that is being dragged. The nEffect parameter is kind of unique in that we can set
its value in the OLEDragOver event and control the drop action allowed. The possible
values for the nEffect parameter are 0 for no drop, 1 for copy, 2 for move, and 4 for
link. The nButton parameter tells us which mouse buttons are down with 1 for right, 2 for
left, and 3 for middle. The nShift parameter tells us the state of the Ctrl, Alt, and
Shift keys with 1 for shift , 2 for Ctrl, and 4 for Alt. This property may be a
combination so that Ctrl + Shift would have a value of 3. The nXCoord and nYCoord
parameters tell us the x and y position of the mouse pointer. Finally the nState parameter
tells us if the drag is entering the control, leaving the control or moving over the
control with 0 indicating entering, 1 representing exiting, and 2 representing dragging
over the control.
On the sample code for this session is a form named DragOver.scx.
This form has a textbox, an image, and an edit box in it. Both the textbox and the image
are OLEDragMode automatic. The editbox is OLEDropMode enabled. In the OLEDragOver event of
the editbox is the code below .
LPARAMETERS oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord, nState
IF NOT oDataObject.GetFormat("CF_TEXT")
nEffect = 0 && No Drop
nEffect = 1 && Copy
This code first calls the GetFormat method of the data object and
asks if the data type of the data is CF_TEXT (the data object will be described in more
detail alter). The GetFormat method will return a .T. or .F. indicating if the stated data
type is in the data object. The code above is setting the nEffect parameter to 0 (No drop)
if the data type is not CF_TEXT and to 1 (Copy) if the data type is CF_TEXT.
When running this form we can type some text in to the text box
then highlight and drag it over the editbox. When we are dragging the text from the
textbox the editbox will indicate that a drop is allowed and will accept the text if a
drop is done. If the image is dragged over the editbox then the GetFormat call will return
.F. because the data is not text but is a BMP, the nEffect is set to 0 and the no drop
icon is displayed and a drop is not allowed.
Since with OLE drag and drop we have no idea of what might be
dragged over our control, using the OLEDragOver event this way if an effective method of
limiting the drops allowed to only those with data that our control can handle.
The Data Object (oDataObject)
In certain of the events, like OLEDragDrop, one of the parameters
passed is oDataObject. Unlike in the native Visual FoxPro drag and drop, where the oSource
is an object reference to the control that is the source of the drag operation, OLE drag
and drop has a DataObject that is being dragged around.
The DataObject cannot be created outside of a drag operation and
it is destroyed as soon as the drag ends. The DataObject is passed to OLESetData
and OLEStartDrag events of the drag source. The OLEStartDrag event is called when a
drag operation is started and this event can be used to populate the DataObject with data.
Depending on the object that is the source of the start of the drag operation the
DataObject may be automatically populated with data (as we have seen in the examples so
far). The OLESetData event is called for the Drag source whenever a drop target calls the
GetData method of the DataObject and no data is in the object of the type requested.
Either of these methods can use the SetData method of the DataObject to place data in the
The other two places where the DataObject is passed are the
OLEDragDrop and the OLEDragOver event a drop target. Either of these events receive the
DataObject as a parameter named oDataObject and they can use the methods of the DataObject
to investigate the data being dragged.
Methods of the DataObject
The DataObject has five methods available. They are ClearData,
GetData, SetData, GetFormat, and SetFormat. These methods are described in the table
We can make use of these methods to allow a drag source to
customize the format of the data according to our needs. Figure 5 shows a form with an
image of an American flag, a text box, and a container.
Figure 5 Our custom OLE DataObject form DragChng.scx.
The idea of this form is that we can drag the image and drop it.
If we drop it on the textbox we want to get text saying "American Flag", if we
drop it on the container we want to see the image of the flag.
We accomplish this by customizing the contents of the DataObject
when the drag starts. In the Images OLEStartDrag event there is the following code.
LPARAMETERS oDataObject, nEffect
* Clear out all data from the data object
*-- Specify that data can only be copied
nEffect = 1
*-- Register the text (1) format
oDataObject.SetFormat( 1 )
*-- Register private format in the dataobject
oDataObject.SetFormat( "Private Format" )
This code first clears the data object of any data. It then
registers the text data format and a special format. In the OLESetData event the code
LPARAMETERS oDataObject, eFormat
CASE trans( eFormat ) == '1' && Text format
* If Text data is requested by the drop target
* Put "American Flag" in the data object
oDataObject.SetData( "American Flag", 1 )
CASE trans( eFormat ) == "Private Format" && Private format
* If "Private Format" is requested
* put the picture file name into the data object
* as "Private Format"
oDataObject.SetData( This.Picture, "Private Format" )
What we have done so far is to react to the start of a drag of
the image. When the drag is started we registered two data formats in the data object text
and private format. The OLESetData event wont get fired until a drop target tries to
get data our of the data object matching a certain format. When the drop target requests
the text format the OLESetData event will put "American Flag" into the data
object as text format. If the drop target requests our private format then the name of the
file in the images picture property will be put in the data object as the private
There is no special code in the textbox as its OLEDragDrop
automatically requests Text format. The container is a little special though. In its
OLEDragOver it has the following code.
IF nState == 0 && Drag Enter
*-- We only need to check out the data format once upon enter
CASE oDataObject.GetFormat( "Private Format" )
* I can handle drops of "Private Format"
* Tell OLEDragDrop that I know how to handle this
This.OLEDropHasData = 1
* Tell OLEDragDrop that I want to copy this
This.OLEDropEffects = 1
CASE oDataObject.GetFormat( 15 ) && Files
* I can handle drops of files
This.OLEDropHasData = 1
This.OLEDropEffects = 1
When the Container requests the data type Private Format, the
OLESetData event will respond by putting the name of the picture file in the data object
as type private format. In the containers OLEDragDrop event we handle the drop with
the code below.
LOCAL aFiles[ 1 ], nFiles, i, cExt
CASE oDataObject.GetFormat( "Private Format" ) && Private format
* I can handle "Private Format" data
* Hide the label
This.lblDropSpace.Visible = .F.
* Set the picture property
This.Picture = oDataObject.GetData( "Private Format" )
* Set the copy attribute
nEffect = 1
* Draw the container
* Stop the default action of the drag and drop event
CASE oDataObject.GetFormat( 15 )
* I can handle file data
* Get the file data into an array
IF oDataObject.GetData( 15, @aFiles )
* If we got any set the count
nFiles = alen( aFiles, 1 )
* Set the count to 0
nFiles = 0
* Check each of the files
FOR i = 1 to nFiles
* Get the extension
cExt = Upper( JustExt( aFiles[ i ] ))
IF ( cExt == "BMP" ) or ( cExt == "JPG" ) or ( cExt == "GIF" )
* If it is a file we can handle
* Hide the label
This.lblDropSpace.Visible = .F.
* Set the picture property
This.Picture = aFiles[ i ]
* Draw he container
* Pause for a few seconds in case there was more than one file
* Set the copy only attribute
nEffect = 1
* stop the default action of this drag and drop
The above code is riddled with comments explaining each and every
line. If you read it carefully you will see that we can actually drag file names from the
explorer and drop them in this container and the container will display the image.
Figure 6 shows the same form after the image has been dropped on
both the textbox and the container.
Figure 5 Our custom OLE DataObject form after the drops.
As you have seen in this last example form, the OLE Drag and Drop
operation is a two-way communication between the drag source and the drop target. When the
drop target makes a request the drag source can respond. It is this two-way communication
that makes OLE Drag and Drop so much more powerful even if it is only used within a Visual
FoxPro application. The communication allows different data to be sent depending on where
the drop occurred. It also gives the drop target a say in what it will or will not handle.
All of this and the ability to drag from and drop on non Visual
FoxPro objects, well OLE drag and drop certainly has me hooked. Whenever I need Drag and
Drop interface components I will be using OLE Drag and Drop.