Monday, January 13, 2025

Determine Object Source When Using COPYCLIP[BASE]/PASTECLIP[ORIG] (Ctrl+C/Ctrl+V)

When using AutoCAD, users can use a standard Windows OS operation to copy/paste entities in the same drawing or across different drawings. The copy/paste operation can be done by simply pressing Ctrl+C/Ctrl+V (as users do with almost all Windows applications); or by entering command "COPYCLIP/COPYBASE" and then "PASTECLIP/PASTEORIG" at AutoCAD's command line; or by right-clicking in AutoCAD's editor and in the content menu, select "Clipboard".

There is an interesting question posted in AutoCAD .NET API forum, asking how to tell the objects being COPY/PASTE-ed are originated from the same drawing, or from different drawing (of course the different drawing has to be open in an AutoCAD session (but source and destination drawings are not necessarily be in the same AutoCAD session).

In order to answer this question, we need to understand how the COPY/PASTE commands work: 

1. When COPYCLIP[BASE] command executes, AutoCAD Wblocks the selected entities and saves it as a DWG file with a name like "A$Cxxxxxxxx.Dwg". The saving location is the location defined in "Temporary Drawing File Lcoation" of the current user profile. Then the temporary file name is somehow stored in Windows Clipboard (this is my guess!). Each time the Ctrl+C pressed, previous temporary file is erased and a new one is created and the Clipboard is updated.

2. When PASTECLIP[ORIG] command executes, AutoCAD locates the temporary file according to the file information in the Clipboard and import its content into the destination drawing (insert as a block, or WblockCloneObject()?). Also, even the source drawing is closed after Ctrl+C is pressed, the "copied" objects can still be pasted to drawings in running AutoCAD sessions. In fact, even AutoCAD session is closed, and opened again, the "copied" objects can still be pasted, as long as the Windows Clipboard has not been updated by pressing Ctrl+C in AutoCAD session, or other Windows applications.

Since the source data is saved as temporary drawing file, thus the source objects can be "pasted" to the same drawing, other drawing (in the same or different AutoCAD session).

Now back to the question of how to know the source objects are originated from which drawing. Now that we know Ctrl+C merely Wblock selected entities to a external drawing file, we can manage to know capture the source document/database information when the Wblocking occurs and make it available when Ctrl+V is pressed. 

Following code shows my attempt of telling where the source entities are originated before them being pasted:

using Autodesk.AutoCAD.DatabaseServices.Filters;
using DriveCadWithCode2025.AutoCADUtilities;
 
[assemblyCommandClass(typeof(AcadMicsTests.MyCommands))]
 
namespace AcadMicsTests
{
    public class MyCommands 
    {
        #region Determine COPY/PASTE source file
 
        private static IntPtr _copySourceDoc = IntPtr.Zero;
        private static bool _isCopyClip = false;
 
        [CommandMethod("HandlePaste")]
        public static void GetDataInClipboard()
        {
            foreach (Document dwg in CadApp.DocumentManager)
            {
                var db = dwg.Database;
 
                db.WblockNotice += Db_WblockNotice;
                dwg.CommandWillStart += Dwg_CommandWillStart;
                dwg.CommandEnded += Dwg_CommandEnded;
            }
 
            CadApp.DocumentManager.DocumentCreated += (oe) =>
            {
                var dwg = e.Document;
                var db = dwg.Database;
 
                db.WblockNotice += Db_WblockNotice;
                dwg.CommandWillStart += Dwg_CommandWillStart;
                dwg.CommandEnded += Dwg_CommandEnded;
            };
        }
 
        private static void Db_WblockNotice(object senderWblockNoticeEventArgs e)
        {
            if (_isCopyClip)
            {
                _copySourceDoc = CadApp.DocumentManager.MdiActiveDocument.UnmanagedObject;
            }
        }
 
        private static void Dwg_CommandEnded(object senderCommandEventArgs e)
        {
            if (e.GlobalCommandName.ToUpper().Contains("COPYCLIP") ||
                e.GlobalCommandName.ToUpper().Contains("COPYBASE"))
            {
                _isCopyClip = false;
            }
        }
 
        private static void Dwg_CommandWillStart(object senderCommandEventArgs e)
        {
            if (e.GlobalCommandName.ToUpper().Contains("COPYCLIP") ||
                e.GlobalCommandName.ToUpper().Contains("COPYBASE"))
            {
                _isCopyClip = true;
            }
            else if (e.GlobalCommandName.ToUpper().Contains("PASTECLIP") ||
                e.GlobalCommandName.ToUpper().Contains("PASTEORIG"))
            {
                var sourceFile = "";
                foreach (Document dwg in CadApp.DocumentManager)
                {
                    if (dwg.UnmanagedObject == _copySourceDoc)
                    {
                        sourceFile = dwg.Name;
                        break;
                    }
                }
 
                CadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage(
                    $"\nYou are to paste objects copied from:\n{sourceFile}...\n");
            }
        }
 
        #endregion
    }
}

One thing to pay attention here. As explained, Ctrl+C exports the selected entities as a temporary drawing file linked to Windows Clipboard, which can be pasted to an open drawing in any running AutoCAD session. So, if the copied source is pasted to a different AutoCAD session, my code will not be able to tell where the source is from. Here my focus is to explain how Ctrl+C/Ctrl+V works in AutoCAD under the hood, and based on the understanding, I show that it is not too difficult to tell which file is the source of the copying, assuming the COPY/PASTE is operated in the same AutoCAD session.

I am no sure what the practical use of knowing which drawing file name is the copy source. Considering a drawing file can be renamed as many different file names while their contents remain the same, if knowing where the copy source is from is very critical, relying on file name might not be a good choice. It might be better to intercept into the COPYCLIP/BASE command (when command started and/or when selection is made) and add flags to the selected entities (XData, for example) before the COPYCLIP/BASE command does the WBlock to generate the temporary drawing. Then after pasting the source into a drawing, we can use code to check up the flag... Not sure if it is doable, just a thought. But one just want to casually know if a copy source is from the same drawing or from different open drawing in the AutoCAD session, the code here just does that. With minor modification by handling DocumentLockModeChanged event, the pasting can be vetoed if the copy source is not from the desired drawing (the same drawing or the different drawing).

See video clip below and pay attention to the command line when copied source is pasted:







No comments:

Followers

About Me

My photo
After graduating from university, I worked as civil engineer for more than 10 years. It was AutoCAD use that led me to the path of computer programming. Although I now do more generic business software development, such as enterprise system, timesheet, billing, web services..., AutoCAD related programming is always interesting me and I still get AutoCAD programming tasks assigned to me from time to time. So, AutoCAD goes, I go.