DragnDropFromControl Copy event

Started by honkinberry, May 22, 2012, 02:55:58 PM

Previous topic - Next topic

honkinberry

I'm implementing Drag n Drop on a Tree Control.
I see that the icon changes to the Copy icon when the user holds down the Ctrl key, but I don't see any way to intercept this.  It would seem there would need to be an additional Flags argument passed to DragnDropFromControl in order to know if that was the case, correct?
Is there a recommendation on how to handle this?

Many, many thanks as always!

--J

honkinberry

ah, I hate to be That Guy, but I think I just answered my own question.
In DragBegin I can return the bit code of what is allowed, as well as in DragOver.
But since I'm only concerned with Move vs. Copy, when a successful Drag operation is completed, if the Node of the source item is still around, I can safely assume that the user had the Ctrl key down, yes?  And when the source Key node is gone, then that must have been a successful Move operation.
Does that sound right?

--J

honkinberry

Nope, that didn't work either.
In the Drag complete event after a Move, GetItemHandle still returns the source node.
And whether Moving or Copying, there is no difference in the DropPoint argument, and even the GetSelectedItem still returns the same source node for a Move.
So sorry, still stumped. Thanks for any help!

--J

owenwengerd

The general design goal is for the built-in drag/drop behavior to be usable as-is, but if you implement any of the drag and drop event handlers, you're expected to handle everything and the built-in behavior is not used. Since it sounds like you're only copying and moving existing nodes around, I wonder what exactly you need that the built in behavior doesn't provide. The built in behavior may simply need to be fixed or improved. On the other hand, I'm not sure I understand the problem. It would help if you could upload a very simple project along with instructions to reproduce the problem.

honkinberry

Here you go.

First, I need to know what node was dragged onto what node.
That's pretty easy, I just need a global var to store the key from the DragDropBegin method.

But I also need to know if the user was holding Ctrl, which presents the user with a nice Copy icon during the drag.

As for the built-in behavior -- when I Move a node, it just disappears.  I don't see how that could possibly be usable as-is, I will always need to recreate the node in the destination location, yes?
If the user holds down Ctrl and gets the Copy icon, the source node stays there, but there is no node automatically created at the destination, correct?  And no ability for me to ascertain that the Ctrl key was depressed.

Many thanks for your help!

--J

owenwengerd

You say "when I Move a node, it just disappears". I can't reproduce that. When I move, it reappears as a child of the node I dropped it on. When I copy, the original stays, but a new copy appears. I just took your sample file and unchecked the two handled events on the tree control.

I can see how it would be useful to know whether the drop is a move or copy in the drop handler. A new argument could be added, but that would break existing code. Hopefully in this case the built in behavior will work for you.

honkinberry

I need my handled events, however.
After a user drags an item, there are corresponding files that need to moved/copied, and updates in a database that need to be effected.
I also need the Drag Over event, so that I can dynamically set the allowable operations of Move, Copy, Disallow.
Not to mention just the confirmation screen -- "Are you sure you wish to move/copy the selected item?"

--J

owenwengerd

In that case, your best bet is probably to treat every drop as a copy, then fire off a post process check (perhaps using DelayedInvoke) to see whether the source is still there, and handle the situation appropriately if it is no longer present.

honkinberry

I think I'm going to allow only Move operations, then have a custom confirmation screen that allows selecting Move or Copy.

I'd really like all the code to be self-contained within the functions handling the dialog box, and not have to require a public callable function, global variables for source and destination key, and then have access back to the dialog box to add the new node.

I have all the code I need for this, and it's all very familiar to the version we did with a TreeList control for the Visual Basic version of the application.  Yet there, the OLECompleteDrag passes a parameter for the style of drag:
http://msdn.microsoft.com/en-us/library/x013da05(v=vs.80).aspx

I understand that changing the number of parameters for the DragDropFromControl Event would break existing code, but it would also make the event far more usable.  As it is, I can't really do anything with it off the shelf.  A treelist correlates with something -- block definitions, source drawings, organization chart, you name it.  So in any real-world usage, a drag drop event requires something else to be done to effect the user's intent.
I would offer, that the simplest fix, would be to move the Event fire to *after* the default dragdrop behavior.  In this case, I could query the treelist to see if the source node was still there, or if it had been copied, and then perform all my additional cleanup routines.

Thanks for the info!

--J

owenwengerd

It isn't possible to change the event handler timing because the return value from the drop event handler is needed as the ultimate return value of the initiating drag operation, but you can already postpone a *notification* using the technique I mentioned earlier, so not much would be gained anyway. If I could get some feedback from users of drop handler events, I might be persuaded to add a new argument to the drop handler even though it would break existing code.

honkinberry

Any word on this?
We've implemented this feature, and the quirkiness is already soliciting feedback from users.

Here's what we have:
a TreeList control, with DragBegin (that sets what can and can't be moved/copied), DragOver (which sets where things can/can't be dropped), and DragDropFromControl (which confirms the operation, then moves the files, updates the database with the new filenames).
As I have a custom DragDropFromControl, the default control behavior is what is most troublesome.  If the user clicks No, the node still disappears!  Poof!  Gone!  But it's not in the new location.  And I can't add it back if they click No, because that event hasn't happened yet, so the node is actually still there when my code fires.

What would be simplest would be if I could prevent the default behavior from happening at all, depending on my return value of DragDropFromControl.  That would seem to be the easiest change for any existing code, yes?

But in addition to that, I need to be able to know if the user was holding down Ctrl for Copy.  This is a standard with other DragDrop handlers.  I get that either changing DropPoint, or adding an additional parameter will break existing code -- but again, how can any existing code actually accomplish anything if it can't tell if the operation is a Move or Copy?  Or add a simple confirmation screen to DragDrop operation?

--J

owenwengerd

Quote from: honkinberry on June 22, 2012, 09:55:01 AM
Any word on this?

I'm not sure what you mean. If you're asking whether the OpenDCL user community has provided any new feedback on this subject, the answer is "no".


Quote from: honkinberry on June 22, 2012, 09:55:01 AM
What would be simplest would be if I could prevent the default behavior from happening at all, depending on my return value of DragDropFromControl.  That would seem to be the easiest change for any existing code, yes?

I think it's bad UI design to display a modal dialog during a drop, but it might be possible to use the return value without too much disruption. It would be the same return value as DragOverFromControl, with the same meaning. The change could break existing code if the existing event handler happens to return an integer, but the odds would be fairly small.


Quote from: honkinberry on June 22, 2012, 09:55:01 AM
...how can any existing code actually accomplish anything if it can't tell if the operation is a Move or Copy?  Or add a simple confirmation screen to DragDrop operation?

The drag/drop design is based on a philosophy of insulating the drag from the drop. A well designed drop handler does not know or care about the source of the drop, and vice versa. That means the drop handler should always treat a drop as "insert a new item", then let the drag handler decide what to do with the original item based on the drop type. A modal UI (which is what I assume you mean by "simple confirmation screen") freezes the drag/drop message pump while it's in the middle of a drop, which is a risky business and not recommended. If the goal is to let the user back out after an inadvertent drag, then it would be better to provide an "Undo" mechanism or a way to disable drag/drop at runtime and only enable it on demand.