.NET

Reply
Valued Contributor
HelloWorlddd
Posts: 87
Registered: ‎05-03-2013
Message 1 of 14 (284 Views)
Accepted Solution

Copy Problems

284 Views, 13 Replies
03-19-2014 09:00 AM

I want to create a command, it could copy the contents of another drawing to the current drawing directly, not XERF, Is there anyone can give me a simple example?
Thanks very much

Hi,

 

You can make the importBlockReference() method return the newly created ObjectId to the calling function from where you move the newly created block reference.

 

 [CommandMethod("TEST")]
public void Tet()
{
ObjectId id = ImportBlockReference("tstrm", @"D:\SourceDwg\sourceDrawing.dwg");
if (id != ObjectId.Null)
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
br.TransformBy(Matrix3d.Displacement(new Vector3d(10, 20, 0)));
tr.Commit();
}
}
}
private ObjectId ImportBlockReference(string blockName, string filenName)
{
if (!File.Exists(filenName))
throw new FileNotFoundException("File not found", filenName);
Database targetDb = HostApplicationServices.WorkingDatabase;
ObjectId owner = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);
using (Database sourceDb = new Database(false, true))
{
sourceDb.ReadDwgFile(filenName, FileShare.ReadWrite, false, "");
using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
if (!bt.Has(blockName))
throw new ArgumentException("Block definition not found", blockName);
ObjectIdCollection ids = new ObjectIdCollection();
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(sourceDb);
foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
{
BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
if (br.OwnerId == mSpaceId)
{
ids.Add(id);
break;
}
}
if (ids.Count == 0)
throw new ArgumentException("Block reference not found", blockName);
IdMapping idMap = new IdMapping();
sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
return idMap[ids[0]].Value;
}
}
}

 

*Expert Elite*
_gile
Posts: 2,125
Registered: ‎04-29-2006
Message 2 of 14 (278 Views)

Re : Copy Problems

03-19-2014 09:35 AM in reply to: HelloWorlddd

Have a look at the Database.WblockCloneObjects() method.

Gilles Chanteau
*Expert Elite*
_gile
Posts: 2,125
Registered: ‎04-29-2006
Message 3 of 14 (253 Views)

Re : Copy Problems

03-20-2014 12:06 AM in reply to: _gile

Here's a little sample

 

        public static ObjectIdCollection ImportModelSpace(string filename)
        {
            if (!File.Exists(filename))
                throw new FileNotFoundException("File not found", filename);

            Database targetDb = HostApplicationServices.WorkingDatabase;
            ObjectId owner = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);
            IdMapping idMap = new IdMapping();

            using (Database sourceDb = new Database())
            {
                sourceDb.ReadDwgFile(filename, FileShare.Read, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    BlockTableRecord mSpace = (BlockTableRecord)tr.GetObject(
                        SymbolUtilityServices.GetBlockModelSpaceId(sourceDb), OpenMode.ForRead);
                    ObjectIdCollection ids = new ObjectIdCollection(mSpace.Cast<ObjectId>().ToArray());
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
                    tr.Commit();
                }
            }
            return new ObjectIdCollection(
                idMap
                .Cast<IdPair>()
                .Where(p => p.IsCloned)
                .Select(p => p.Value)
                .ToArray());
        }

 

Gilles Chanteau
Valued Contributor
HelloWorlddd
Posts: 87
Registered: ‎05-03-2013
Message 4 of 14 (238 Views)

Re : Copy Problems

03-20-2014 07:53 AM in reply to: _gile

I think the code is still a little complicated for me,


Can you help me achieve the following process?  It will be a better way.

 

For example, there is a source drawing which contains a BlockReference called tstrm in the D drive,
Then execute custom command in the new drawing, this target block above will be copied to the new drawings.

Attachment has the source drawings


Extremely grateful

demo.PNG

*Expert Elite*
_gile
Posts: 2,125
Registered: ‎04-29-2006
Message 5 of 14 (233 Views)

Re : Copy Problems

03-20-2014 09:05 AM in reply to: HelloWorlddd

Do you want to add the block reference to the target model space or only import the block definition in the target block table ?

Gilles Chanteau
Valued Contributor
HelloWorlddd
Posts: 87
Registered: ‎05-03-2013
Message 6 of 14 (229 Views)

Re : Copy Problems

03-20-2014 09:23 AM in reply to: _gile

I do not quite understand the difference between these two
But the result I want is equivalent to using Autocad COPY command , just like copy the graphics to a new drawing, the graphics is same with the old one.

 

The new command that I want to get will work as below:

1,Exceute the command,

2,Automatic drawing that graphics at my specified position, in fact this step the program will access the source drawing and then copy that graphics

 

This small command will save some time during copy, just like select target object and so on

*Expert Elite*
_gile
Posts: 2,125
Registered: ‎04-29-2006
Message 7 of 14 (223 Views)

Re : Copy Problems

03-20-2014 10:16 AM in reply to: HelloWorlddd

First, IMO, if you want to make autoCAD customization, especially with a as sophisticated technology as .NET, you must, above all, master the autoCAD basics as the difference between a block definition (BlockTableRecord) and an insertion of this definition (BlockReference).

 

The AutoCAD COPY command do not allow to copy a graphic object between different drawing (either between two spaces). This can be done with the Windows clipboard technology (Copy/Paste commands) which is tolerate by AutoCAD.

The "AutoCAD way" to do what you describe is using the DesignCenter to import the block definition from another drawing and insert a reference of this block in the model space or elsewhere. This can be done programmatically using the WblockCloneObjects() method as shown upper.

 

You can find a method to import a block definition from an external drawing in this recent thread (reply #7):

http://forums.autodesk.com/t5/NET/How-to-include-extension-dictionary-in-block-inserted-using/td-p/4...

Gilles Chanteau
Valued Contributor
HelloWorlddd
Posts: 87
Registered: ‎05-03-2013
Message 8 of 14 (181 Views)

Re : Copy Problems

03-23-2014 05:56 AM in reply to: _gile

Thank you very much, I have a learn about WBlockCloneObjects() method in the AutoCAD Developer Guide, it works well.

but I am not very unstudand about your ImportBlock() method, this one has some problem.
Can you fix my code? Just let it work,

 

For example:
filePath=@"D:\SourceDwg\sourceDrawing.dwg"
BlockName="tstrm"
The Block will be import at origin

 

The above attachment has the drawing.

Blow is code,

using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

[assembly: CommandClass(typeof(AutocadCommandCollection.test6))]


namespace AutocadCommandCollection
{

    class test6
    {

        [CommandMethod("test6")]


        public static void CopyFrom()
        {
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database acCurDb = acDoc.Database;

            using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
            {
                BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
                ObjectId Id = ImportBlock(@"D:\SourceDwg\sourceDrawing.dwg", "tstrm");
                BlockTableRecord btr = (BlockTableRecord)acTrans.GetObject(Id, OpenMode.ForRead);
                acBlkTbl.Add(btr);
                acTrans.AddNewlyCreatedDBObject(btr, true);

                acTrans.Commit();
            }
        }




        private static ObjectId ImportBlock(string fileName, string blockName)
        {
            if (!File.Exists(fileName))
                throw new FileNotFoundException("File not found", fileName);

            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database targetDb = acDoc.Database;
            ObjectId owner = targetDb.BlockTableId;

            using (Database sourceDb = new Database())
            {
                sourceDb.ReadDwgFile(fileName, System.IO.FileShare.Read, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartOpenCloseTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blockName))
                        return ObjectId.Null;

                    ObjectId id = bt[blockName];
                    ObjectIdCollection ids = new ObjectIdCollection();
                    ids.Add(id);
                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
                    return idMap[id].IsCloned ? idMap[id].Value : ObjectId.Null;
                }
            }
        }

    }

}

 

 

Valued Contributor
HelloWorlddd
Posts: 87
Registered: ‎05-03-2013
Message 9 of 14 (174 Views)

Re : Copy Problems

03-23-2014 06:45 AM in reply to: HelloWorlddd

I think I finally find the new block after run the code above, the block is existing int the BlockTable or maybe, I can find it throuht the Insert Block drop down list of the Insert Menu.

But It doesn't show as same as the old one after insert manully, I just want Insert the Block in the new drawing, It will be same with the old one.

Can you help me? Very thanks

Picture.PNG

*Expert Elite*
_gile
Posts: 2,125
Registered: ‎04-29-2006
Message 10 of 14 (161 Views)

Re : Copy Problems

03-23-2014 12:21 PM in reply to: HelloWorlddd
        private void ImportBlockReference(string blockName, string filenName)
        {
            if (!File.Exists(filenName))
                throw new FileNotFoundException("File not found", filenName);

            Database targetDb = HostApplicationServices.WorkingDatabase;
            ObjectId owner = SymbolUtilityServices.GetBlockModelSpaceId(targetDb);

            using (Database sourceDb = new Database(false, true))
            {
                sourceDb.ReadDwgFile(filenName, FileShare.ReadWrite, false, "");
                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blockName))
                        throw new ArgumentException("Block definition not found", blockName);

                    ObjectIdCollection ids = new ObjectIdCollection();

                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                    ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(sourceDb);
                    foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                        if (br.OwnerId == mSpaceId)
                        {
                            ids.Add(id);
                            break;
                        }
                    }

                    if (ids.Count == 0)
                        throw new ArgumentException("Block reference not found", blockName);

                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(ids, owner, idMap, DuplicateRecordCloning.Ignore, false);
                }
            }
        }

 

Gilles Chanteau
Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.