Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.
These properties, events and method allow you to put drag-and-drop with VFP objects in your applications. It’s astonishingly easy to get simple drag-and-drop to work, but making it look smooth and elegant is another story. Drag-and-drop with other applications or ActiveX controls uses a collection of properties and methods whose names start with OLEDrag or OLEDrop.
oObject.DragMode = nDragMode
nDragMode = oObject.DragMode
oObject.Drag( [ nDragAction ] )
Parameter |
Value |
Meaning |
nDragMode |
0 |
Use manual dragging. |
1 |
Enable automatic dragging. |
|
nDragAction |
0 |
Cancel dragging. |
1 or Omitted |
Start dragging. |
|
2 |
Stop dragging. |
Any draggable object can have dragging enabled in either of two ways. The object’s DragMode can be set for automatic dragging. In that case, when the user presses the left mouse button on that object, dragging begins immediately.
Most people prefer manual dragging for the additional control it provides. In that case, you leave DragMode set to 0 and call the object’s Drag method to turn dragging on when you’re ready. Usually, Drag(1) is called in the object’s MouseDown method—you can test to make sure it’s a good time for drag-and-drop. MouseMove is another good place to start dragging. You can check whether the mouse has moved far enough to indicate dragging, in case the user’s hand simply twitched.
Regardless of which way you start, when you’re dragging, the object doesn’t recognize mouse events—even the MouseUp that ends the drag. In fact, with manual dragging, you stay in the method that started the drag until the mouse button is released. (This is an intricate bit of cooperation between Windows itself, which provides the drag features, and FoxPro. We guess technically you’re in the Drag method all that time and return to the method that started the drag when you stop dragging.)
Normally, a drag ends when the user releases the mouse button. The other two values for nDragAction let you put an abrupt stop to dragging. With 0 (cancel), that’s the end of it. With 2 (stop), the DragDrop event of the object you’re over at the time fires. We can come up with some silly examples for this, but truly useful cases are harder to think of.
In VFP 3, timers and drag-and-drop don’t mix very well. Timer events get backed up until you stop dragging. The problem is gone in VFP 5 and later.
oObject.DragIcon = cCursorFile
cCursorFile = oObject.DragIcon
This property lets you specify an icon to be used for the object while you’re dragging it. If you don’t specify one, you drag a hazy outline of the object itself.
You can change DragIcon dynamically. The DragOver event of another object can change the dragged object’s DragIcon to indicate valid actions. Most often, you see this in the form of the international “no” symbol when dropping isn’t valid. But, you can indicate all kinds of things—use a down arrow for “please drop here” or a magnifying glass to indicate that dropping zooms in.
DragIcon expects a CUR cursor file—not, as its name suggests, an ICO. VFP can be picky about its cursors, too, but VFP 5 and later seem to be a lot more flexible about this than VFP 3. (In VFP 3, you must have a VGA-Mono 2-Color 32 x 32 format cursor or things get weird. Naturally, lots of the cursors that came with VFP 3 weren’t in that format.) A bunch of cursors get installed in Visual FoxPro’s samples (check the directory HOME(4)). Starting in VFP 6, you can use the GETPICT()
function, which is a specialized File | Open dialog for pictures, to look at them. In earlier versions of VFP, GETPICT()
can’t read CUR files! Starting in VFP 5, however, any version of the File | Open dialog shows you the picture next to the file name. In VFP 3, you can use the Imagedit application that’s installed by the Professional edition to look at exploded versions of them.
PROCEDURE oObject.DragOver
LPARAMETERS [ nIndex, ] oSource, nXCoord, nYCoord, nState
PROCEDURE oObject.DragDrop
LPARAMETERS [ nIndex, ] oSource, nXCoord, nYCoord
Parameter |
Value |
Meaning |
nIndex |
Numeric |
This object is part of a control array. nIndex is the item number within the array. |
Omitted |
The object is not part of a control array. |
|
oSource |
Object |
A reference to the object being dragged. |
nXCoord, nYCoord |
Numeric |
The mouse coordinates relative to the form when the event fires. |
nState |
0 |
The dragged object is just entering this object's space. |
1 |
The dragged object is now leaving this object's space. |
|
2 |
The dragged object remains over this object's space. |
These two events belong not to the object being dragged, but to the target—the object over which you’re dragging or onto which you’re dropping. When you drag an object over another object (even over a form itself), the DragOver event of the latter object fires. An easy way to see this happening is to put WAIT WINDOW “Dragging over “+This.Name NOWAIT in the DragOver event of everything under the sun. When you drop an object, the DragDrop event of the target object fires.
Both events give you access to the object being dragged via the oSource parameter. It’s very cool—you can change the object you’re dragging based on where it is or where you drop it.
Use the nState parameter of DragOver to make decisions about what to do—the most common is to change DragIcon of the dragged object. A typical setup is to have your code for nState=0 save the object’s old icon and set a new one, then the code for nState=1 can reset DragIcon to the old value. Two caveats. First, you’ll have to save the old icon to a property somewhere (a property of the dragged object makes the most sense to us). You can’t use a local variable in the DragOver method because you don’t stay in DragOver—it gets called repeatedly. The more serious problem is restoring the icon. If you drag over the object so the icon gets changed, but then drop without leaving that object, the old icon is never restored. Next time you drag this object, it’s still set to the replacement icon. Be sure to restore it after the drop or before you start dragging again.
If an object is small enough, it's possible to drag another object over it without firing the small object's DragOver method. When dragging slowly, DragOver always fires, but if you drag quickly across a narrow object, DragOver may fail to fire. |
If the DragIcon of the source object is set to a cursor file, issuing Drag(0) in the DragOver event of another object is useless. The drag isn't canceled. As long as the DragIcon is the default fuzzy box, Drag(0) works just fine. |
* This form is included in the Developer Downloads
* available at <a href="http://www.hentzenwerke.com/" target="_blank">www.hentzenwerke.com</a> as Dragger.SCX.
* The object we want to drag is a text box. Put it in the
* middle of the form. In the prop sheet:
DragIcon = HOME(4) + "CURSORS\DRAGPICT.CUR"
* In the text box's MouseDown event:
This.Drag(1)
This.DragIcon = HOME(4)+"CURSORS\DRAGPICT.CUR"
* The form contains 4 other objects: a button, a shape and
* two vertical lines. Position one vertical line near the left
* edge of the form and put this code in its DragOver:
oSource.Drag(0) && Cancel drag
* Put the other line near the right edge of the form.
* In its DragOver, put:
oSource.Drag(2) && End drag
* In this line's DragDrop method, put:
WAIT WINDOW "Ouch, that hurts!" NOWAIT
* Put the button and the shape between the two lines, but not
* on top of the text box. In the button's DragOver method, put:
DO CASE
CASE nState = 0
oSource.DragIcon = HOME(4) + ;
"CURSORS\NODROP01.CUR"
CASE nState = 1
oSource.DragIcon = HOME(4) +;
"CURSORS\DRAGPICT.CUR"
ENDCASE
* In the shape's DragOver method, put:
DO CASE
CASE nState = 0
oSource.DragIcon = HOME(4) + ;
"CURSORS\BULLSEYE.CUR"
CASE nState = 1
oSource.DragIcon = HOME(4) + ;
"CURSORS\DRAGPICT.CUR"
ENDCASE
In the shape's DragDrop method, put:
WAIT WINDOW "Right on target!"
In the form's DragDrop method, put:
oSource.Left = nXCoord
oSource.Top = nYCoord
GetPict(), Home(), MouseDown, MouseMove, OLE drag and drop, OLEDrag, OLEDragDrop, OLEDragMode, OLEDragOver, OLEDragPicture