Saturday, February 6, 2021

Drag & Drop In AutoCAD (2) - Drag From External Application And Drop OnTo AutoCAD

This is the second of this series on Drag & Drop operation in AutoCAD. See previous ones here:

    Drag & Drop In AutoCAD (1) - The Scenarios

In this post I look into the scenario of dragging from external application and dropping onto a running AutoCAD session.

There are 2 types of external applications user could be dragging something from:

1. Applications that we, as programmers, do not have much control on how the dragging is handled. For example, we cannot control what happens when dragging document content from a Word document into AutoCAD, or we do not have control when the document content is drooped onto AutoCAD editor. The behaviours of drag & drop from both applications (Word and AutoCAD) are designed/built in them and exposed as API for us to intercept into the drag & drop process to manipulate it. So, I'll leave this case out of the discussion here. 

2. Applications we developed, thus, we  have the control at the dragging end of the drag & drop operation. That is, we can choose to use UI components that support drag operation (i.e. having MouseMove event and support DoDragDrop() method) to let drag & drop operation begins at dragging end (our application side). However, at the drop end, AutoCAD runs as a different application, thus, when the drag & drop operation is initialized from our application, we do not have control on how AutoCAD receive the data being dragged and dropped onto it: AutoCAD will do what is was designed to do. There are some dropping behaviours of AutoCAD are known to most AutoCAD users:

  • Insert block
  • Open drawing
  • Insert Text/MText entity
  • Insert OLE object
There could be other behaviours that I am not aware of, but inserting block, opening drawing and inserting MText are the most encountered dropping task when AutoCAD being at the dropping end of drag & drop operation.

Here I built a WinForm desktop application to demonstrate how file name and text string can be dragged from the application, dropped onto AutoCAD and what happens in AutoCAD.

The WinForm application's UI includes a Listbox that can be filled with file names, and a Textbox where user can input text string. There are different options (represented by Radiobuttons) for dragging content in Listbox and/or Textbox that would result in different dropping effect at AutoCAD end.



Here is the code behind the form:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
 
namespace DragFromExeToAcad
{
    public partial class MainForm : Form
    {
        private readonly string _tempTextFile = "";
 
        public MainForm()
        {
            InitializeComponent();
 
            string folder =
            Path.Combine(Environment.GetFolderPath(
                Environment.SpecialFolder.LocalApplicationData), "Temp");
            _tempTextFile = folder + "\\Dragged_Text.txt";
        }
 
        private void SelectFiles()
        {
            IEnumerable<string> files = null;
            using (var dlg = new OpenFileDialog()
            {
                Title="Select Files",
                Multiselect=true
            })
            {
                if (dlg.ShowDialog()== DialogResult.OK)
                {
                    files = dlg.FileNames;
                }
            }
 
            if (files!=null)
            {
                DragFileListBox.Items.Clear();
                foreach (var f in files)
                {
                    DragFileListBox.Items.Add(f);
                }
            }
 
        }
 
        private void SaveAsTempFile(string textString)
        {
            if (!string.IsNullOrEmpty(_tempTextFile))
            {
                try
                {
                    File.Delete(_tempTextFile);
                }
                catch { }
            }
 
            File.WriteAllText(_tempTextFile, textString);
        }
 
        
 
        private void ExitButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }
 
        private void SelectFileButton_Click(object sender, EventArgs e)
        {
            SelectFiles();
        }
 
        private void DragTextBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (DragTextBox.Text.Trim().Length == 0) return;
            if (e.Button != MouseButtons.Left) return;
 
            string txt = DragTextBox.SelectionLength == 0 ?
                DragTextBox.Text.Trim() : DragTextBox.SelectedText.Trim();
 
            DataObject data;
            if (TextFileRadioButton.Checked)
            {
                // drag the text string as a temporary *.txt file
                SaveAsTempFile(txt);
                data = new DataObject();
                data.SetFileDropList(
                    new System.Collections.Specialized.StringCollection { _tempTextFile });
            }
            else
            {
                data = new DataObject(txt);
            }
            
            DragTextBox.DoDragDrop(data, DragDropEffects.All);
        }
 
        private void DragFileListBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (DragFileListBox.SelectedItems.Count == 0) return;
            if (e.Button != MouseButtons.Left) return;
 
            var data = new DataObject();
 
            var files = new System.Collections.Specialized.StringCollection();
            foreach (var item in DragFileListBox.SelectedItems)
            {
                files.Add(item.ToString());
            }
            data.SetFileDropList(files);
 
            // start drag & drop operation
            DragFileListBox.DoDragDrop(data, DragDropEffects.All);
        }
 
        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (!string.IsNullOrEmpty(_tempTextFile))
            {
                try
                {
                    File.Delete(_tempTextFile);
                }
                catch { }
            }
        }
    }
}

The mostly used drag & and drop operation from external application onto AutoCAD would be dragging file name, or dragging text string. Here are some explanations about the code and dropping behaviours of AutoCAD.

1. Dragging file name

When dragging file name (single, or multiple), the file name should be stuffed into DataObject with method SetDropFileList(StringCollection), instead of one of the overloaded SetData() methods.

The argument of DragDropEffects used in DoDragDrop() method not only paly the role of showing a different mouse cursor image, but would also result in AutoCAD doing different things at dropping end. For example, when a file name, which is not a plain text/ASCII file, is dropped onto AutoCAD editor, DragDropEffects.Move makes AutoCAD insert a DWG file as block, or as OLE entity, if applicable; however, DragDropEffects.Copy makes AutoCAD open DWG file, and ignore other types of file. Also, regardless DragDropEffects, dropping DWG file onto anywhere of AutoCAD other than editor, AutoCAD would open the drawing file or files. I recommend to use DragDropEffects.All in general to that AutoCAD would do whatever it is designed to do (or not to do) at dropping end and only try other DragDropEffects specific for your special need, if any.

It is worth being pointed out that when dragging a plain text file (typically as *.txt file), AutoCAD will insert the content of the text file as MText.

2. Dragging text string

When text string is filed into DataObject by calling DataObject.SetData(string), or passed to DataObject via its Constructor (new DataObject(string)), AutoCAD receives it and create an MText entity. However, the MText is not created at the location where it is dropped (when mouse' left button releases), instead, it is created at the upper-left corner of current view of AutoCAD editor.

The trick to fix this issue (i.e. let AutoCAD create the MText at where the text string is dropped) is to save the text string into a temporary plain text file, and add this temporary file name to the DataObject by its SetDropFileList(StringCollection) method. That is why you see the extra code that create text file and clean it up when the UI is closed.

Here is the video clip showing drag & drop operation from an external application to AutoCAD;

The next article I will discuss on dragging from AutoCAD and dropping onto modeless form/window of a plugin application in AutoCAD.










No comments:

Post a Comment