Wednesday, February 3, 2021

Drag & Drop In AutoCAD (1) - The Scenarios

Drag & drop is a common computer UI operation that most computer users know. The most used drag & drop operation is drag one or more files or folders in Windows Explorer to copy/move files/folders, or drag file and drop it into an application to open it. All AutoCAD users should know that when a file is dragged from Windows Explorer and dropped into AutoCAD, it is then be either inserted into currently opened drawing in AutoCAD as block, or be opened in AutoCAD for editing/viewing.

As AutoCAD programmers, we are, of course, more interested in how to incorporate drag & drop operation into our own AutoCAD custom applications.

Firstly I want to make it clear what is standard drag & drop operation known by average computer user: user selects something on an application's UI by pressing down mouse' left button and then holds the left button down while moving the mouse - this is drag; then user moves the mouse to a desired location on the same application, or another running application, releases the mouse left button - this is drop. During the dragging, the mouse cursor should show some some kind of visual hint to indicate whether the dragged data is valid to be dropped at certain location.

In terms of drag & drop in AutoCAD use, there are 5 scenarios that might interest us, as AutoCAD programmers:

  • Drag something from AutoCAD and drop onto an external application, be it developed by ourselves or not
  • Drag something from external application, again, be it developed by ourselves or not, and drop onto AutoCAD
  • Drag something from AutoCAD and drop onto our custom plugin UI (obviously, the UI has to be modeless form/window, or we wouldn't be able to drag something from AutoCAD)
  • Drag something from our custom plugin UI and drop onto AutoCAD. In this case, our custom plugin UI can be either modal or modeless
  • Drag something from our custom plugin UI to external application developed by ourselves, or vice versa

In Windows platform, the data exchange in drag & drop process uses IDataObject interface (System.Windows.Forms.IDataObject for WinForm, and System.Windows.IDataObject for WPF). What happens is that when dragging begins, if the UI component, where the dragging begins, has a MouseMove event and has a DoDragDrop() method, then we can handle the MouseMove event to test if the left button of the move is pressed; if yes, we can then create an instance of IDataObject and stuff some data into it (say, call its SetData() method), followed by calling DoDragDrop() method, which takes the data-filled IDataObject as argument. When the mouse' left button is released at a location of UI component of the same application, or another application, if the UI component allows dropping (AllowDrop property of the UI component), we can handle Drop event, where the data is passed in as IDataObject in the event handler's argument, calling IDataObject.GetData() can retrieve the data. Obviously, depending on the data type/format that was filled into IDataObject, the code on dropping side must be able to recognize the data type/format in order to retrieve/use it as expected. Based on these understandings, now we can see what we can do with each of the 4 aforementioned scenarios.

1. Drag something from AutoCAD (entities in AutoCAD's editor) and drop onto external application. 

In this scenario, there could be 2 different cases in terms of external application: an application has no, or very little accessible API for you, as programmer, to intercept into the drag & drop operation; or an application that we developed, thus we could, it seems at least, control what/how the data dragged from AutoCAD be dropped into your application.

For the former, there is nothing we can do, obviously. 

For the latter, even we have control at the dropping/receiving end, we do not have control what/how data get into IDataObject when user drags from AutoCAD editor. In code debugging process, we can peek into the IDataObject before it is dropped, where we could find quite a few pieces of data and the data most relevant to AutoCAD among them is in the format of System.IO.MemoryStream, which we have no way to translate it into meaningful information without Autodesk exposing a suitable API for it.

Therefore, this drag & drop scenario is not a "do-able" scenario.

2. Drag something from external application and drop onto AutoCAD (editor and/or other droppable area beyond editor).

Again, there could be 2 cases: an application we do not have much control as for what/how the data is placed in IDataObject when dragging begins; and an application we build, hence have control to stuff whatever data we desire into the IDataObject for the dragging.

For the former, again, what happens for the drag & drop operation is totally depends on AutoCAD and the application. For example, when dragging *.dwg file name from Windows Explorer into AutoCAD editor triggers AutoCAD's block insertion, or opens the drawing file in AutoCAD; dropping a plain *.txt file would trigger AutoCAD to insert an MText entity; dropping most other types of file would insert an OLE entity. There is nothing we can control here. It is all depends on how the external application is developed to handle its MouseMove event and how AutoCAD is designed to react to the dropping event.

For the latter, while we can control what to be packaged into IDataObject, AutoCAD on the receiving end would only do what it is built to do, which I am no sure I know all of them, but at least I know:

  • inserting a block/or opening a drawing when a *.dwg file name is dropped
  • inserting MText when a plain text file name or text string is dropped
So, when we develop our own desktop application, if we need somehow to drag something over to an running AutoCAD session, at least we know we could do these things when the business workflow requires them.

3. Drag entities from AutoCAD's editor and drop onto our custom developed plugin's modeless UI. While AutoCAD's API does not provide something to allow us a chance to stuff IDataObject with the data we need, therefore the usual way of using IDataObject to transfer data in drag & drop operation does not work. Fortunately, since our custom plugin works inside AutoCAD process, its .NET API provide different way to let us receive dragged data when they are dropped onto our custom UI. So, it is definitely a do-able task.

4. Drag something from our custom plugin UI and drop onto AutoCAD's editor and let AutoCAD generate whatever data in the drawing, be it database-residing objects or not (most likely, they would be entities). In this case, our UI can be either modeless or modal.

5. Drag something from one side of UI and drop on the other side of UI between our custom plugin application in AutoCAD and external application developed by ourselves. In this case, as long as we make sure both ends understand data inside IDataObject. One thing to be remembered is that since the data types defined in AutoCAD managed APIs cannot be used outside AutoCAD, thus the data transferred between our plugins and our custom external application cannot contain these data type. 

I'll follow this up with a series of posts to demonstrate some code on each of the "do-able" scenarios. Stay tuned.









No comments:

Post a Comment