翻译并引自Kean's blog的两篇文章:
http://through-the-interface.typepad.com/through_the_interface/2006/08/import_blocks_f.html.
http://through-the-interface.typepad.com/through_the_interface/2006/08/breaking_it_dow.html
我们将使用一个中介“side database”-先把dwg读取在内存中,而不是直接导入Autocad编辑器,之后再将“块”导入到我们的正在运行的编辑器(Autocad文件数据库的结构,请参看相关资料)。
下面使C#代码,其中的注释说明了每条的功用。之后,我们也将关键语句,进行分析。
using System; using Autodesk.AutoCAD; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using System.Collections.Generic; namespace BlockImport { public class BlockImportClass { [CommandMethod("IB")] public void ImportBlocks() { DocumentCollection dm = Application.DocumentManager; Editor ed = dm.MdiActiveDocument.Editor; Database destDb = dm.MdiActiveDocument.Database; Database sourceDb = new Database(false, true); PromptResult sourceFileName; try { // Get name of DWG from which to copy blocks sourceFileName = ed.GetString(" Enter the name of the source drawing: "); // Read the DWG into a side database sourceDb.ReadDwgFile(sourceFileName.StringResult, System.IO.FileShare.Read, true, ""); // Create a variable to store the list of block identifiers ObjectIdCollection blockIds = new ObjectIdCollection(); Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager; using (Transaction myT = tm.StartTransaction()) { // Open the block table BlockTable bt = (BlockTable)tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false); // Check each block in the block table foreach (ObjectId btrId in bt) { BlockTableRecord btr = (BlockTableRecord)tm.GetObject(btrId, OpenMode.ForRead, false); // Only add named & non-layout blocks to the copy list if (!btr.IsAnonymous && !btr.IsLayout) blockIds.Add(btrId); btr.Dispose(); } } // Copy blocks from source to destination database IdMapping mapping = new IdMapping(); sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false); ed.WriteMessage(" Copied " + blockIds.Count.ToString() + " block definitions from " + sourceFileName.StringResult + " to the current drawing."); } catch(Autodesk.AutoCAD.Runtime.Exception ex) { ed.WriteMessage(" Error during copy: " + ex.Message); } sourceDb.Dispose(); } } }
首先,Line21,我们声明并举例了一个Database对象,这样就会在内存中开辟一定空间(也就是我们说的side database),这个空间对于我们是可以进入的,对于Autocad编辑器是不可以的。其中,第1个参数(buildDefaultDrawing)要设置为false,如果设置为true,则函数不会反馈错误,因此你不知道程序发生了什么。在下面两种情况中,你才会把buildDefaultDrawing设置为true:
1.你自己创造一个dwg文件,而不是从其他地方读取来;
2.从其他地方读取来,而且dwg文件的版本在R12及之前。
(版本对照如下:
AC1.50 = R2.05
AC1002 = R2.6
AC1004 = R9
AC1006 = R10
AC1009 = R11/R12
AC1012 = R13
AC1014 = R14
AC1015 = 2000/2000i/2002
AC1018 = 2004/2005/2006
AC1021 = 2007
)
下一步,Line26,27,我们要求用户输入想要引入的文件地址。这里我们没有检查用户是否输入内容或者输入的内容是否存在,是因为接下来的ReadDwgFile()方法在不能读取文件时,会抛出一个error;
接下来,Line29,30,将文件内容读取到side database.并且我们在Line35,我们创造一个块集合(同样,请参考Autocad文件数据库的结构);
下面的最为关键,Line40 tm.StartTransaction() 才是与CAD编辑器交互的接口。其中,运用循环将有名字或者未布局的块收集起来,看代码就不过多解释了。这个函数WblockCloneObjects()中最后一个参数,REPLACE则擦除之前的内容覆盖写,如果设为IGNORE,则续写。