EaBIM一直以来积极响应国家“十二五”推进建筑业信息化的号召,对建筑领域的信息技术开展深入技术交流和探讨!致力于打造“BIM-建筑师-生态技术”三位一体综合资源交流共享平台,希望为BIM与可持续设计理念及技术的普及做出微小的贡献!!!

萧闫子 发表于 2014-1-8 15:50:16

[资料] 创建和编辑AutoCAD实体(一) 打开和关闭对象

Open and Close Objects 打开和关闭对象Whether you are working with objects such as lines, circles and polyline or a symbol table and its records, you need to open the object for read or write. When querying an object you want to open the object for read, but if you are going to make changes to the object you will want to open it for write.不论是使用直线、圆和多段线这样的对象还是使用符号表及符号表记录,我们都需要以读或写的方式打开这些对象。当查询一个对象时要以读的方式打开对象;如果要对一个对象进行修改,就要以写的方式打开对象。Topics in this section本节主题:·         Work with ObjectIds 使用对象标志ObjectId·         Use Transactions with the Transaction Manager 使用事务管理器管理事务·         Open and Close Objects without the Transaction Manager 不使用事务管理器打开和关闭对象·         Upgrade and Downgrade Open Objects升级打开对象与降级打开对象1、Work with ObjectIds使用对象标志ObjectIdEach object contained with in the Database object is assigned several unique ids. The unique ways you can access objects are:Database对象中包含的每个对象都被赋予了几种唯一的标志。可以用来访问对象的唯一方式有:·         Entity handle 通过实体句柄;·         ObjectId通过ObjectId;·         Instance pointer 通过实例指针;The most common method is to access an object by its Object Id. Object Ids work well if your projects utilize both COM interop and the managed .NET API. If you create custom AutoLISP functions, you may need to work with entity handles.最常用方法是通过ObjectId访问对象。ObjectId标志在项目同时使用COM互操作和托管.NET API的情况下都能很好地工作。如果创建自定义AutoLISP函数,就需要使用实体句柄来访问对象。Handles are persistent between AutoCAD sessions, so they are the best way of accessing objects if you need to export drawing information to an external file which might later need to be used to update the drawing. The ObjectId of an object in a database exists only while the database is loaded into memory. Once the database is closed, the Object Ids assigned to an object no longer exist and maybe different the next time the database is opened.句柄存在于AutoCAD会话之间,因此,如果我们需要将图形信息导出到一个外部文件,以便随后用于更新图形,这时使用实体句柄访问对象是最好的方式。存在于数据库中的对象ObjectId只在数据库加载到内存中时才存在。一旦数据库关闭,赋予对象的ObjectId就不存在了,并且下次打开数据库时可能为该对象赋予了一个不同的ObjectId。Obtain an Object Id获取对象的ObjectId
As you work with objects, you will need to obtain an Object Id first before you can open the object to query or edit it. An Object Id is assigned to an existing object in the database when the drawing file is opened, and new objects are assigned Object Ids when they are first created. An Object ID is commonly obtained for an existing object in the database by:与对象打交道,需要在打开对象对其进行查询或编辑前先获得该对象的ObjectId。图形文件打开时,数据库中已存在对象就被赋予一个ObjectId,新对象在第一次创建时被赋予ObjectId。数据库中已存在对象的ObjectId通常通过下列方式获得:·         Using a member property of the Database object, such as Clayer which retrieves the Object ID for the current layer 使用Database对象的成员属性,如Clayer属性用来提取当前图层的ObjectId;·         Iterating a symbol table, such as the Layer symbol table 遍历符号表,如图层符号表;Open an Object 打开对象
Once an Object Id is obtained, the GetObject function is used to open the object assigned the given Object Id. An object can be opened in one of the following modes:一旦得到ObjectId,就可以使用GetObject函数打开已知ObjectId的对象。打开对象的方式可以使用下列之一:·         Read. Opens an object for read. 以读的方式打开对象;·         Write. Opens an object for write if it is not already open. 对还没打开的对象以写的方式打开;·         Notify. Opens an object for notification when it is closed, open for read, or open for write, but not when it is already open for notify. For more information on notifications, see Use Events. 以通知方式打开对象,用于当对象已经关闭、已经以读的方式打开或已经以写的方式打开时,但已经以通知方式打开了时就不必了。更多关于通知的内容,见使用事件一章。You should open an object in the mode that is best for the situation in which the object will be accessed. Opening an object for write introduces additional overhead than you might need due to the creation of undo records. If you are unsure if the object you are opening is the one you want to work with, you should open it for read and then use the UpgradeOpen function to change from read to write mode. For more information on using the UpgradeOpen function, see Upgrade and Downgrade Open Objects.我们应以对访问对象所处情境最好的方式打开对象。以写的方式打开对象会产生比你可能需要的还多的额外开销,原因是这时会创建撤销记录。如果不能确定正要打开的对象就是你要使用的,应该以读的方式打开,然后使用UpgrateOpen方法将读模式修改为写模式。关于使用UpgrateOpen方法的更多内容,请见升级打开对象与降级打开对象一节。Both the GetObject and Open functions return an object. When working with some programming languages, you will need to cast the returned value based on the variable the value is being assigned to. If you are using VB.NET, you do not need to worry about casting the returned value as it is done for you. The following examples show obtaining the LayerTableRecord for Layer Zero of the current database:GetObject方法和Open方法都返回一个对象。使用某些编程言语时,我们可能需要释放掉基于已赋值变量的返回值。如果使用VB.NET,我们就不必考虑释放返回值的问题,因为VB.NET为我们做了这件事。下面的例子演示获取当前数据库的Zero层的LayerTableRecord记录:VB.NETThe following example manually disposes of the transaction after it is no longer needed.下例在不再需要时手工处置事务(释放内存)。Dim acCurDb As Document = Application.DocumentManager.MdiActiveDocument.DatabaseDim acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()Dim acLyrTblRec As LayerTableRecordacLyrTblRec = acTrans.GetObject(acCurDb.LayerZero, OpenMode.ForRead)acTrans.Dispose()The following example uses the Using statement to dispose of the transaction after it is no longer needed. The Using statement is the preferred coding style.下例在不再需要时使用Using语句处置事务(释放内存)。Using语句是优先选用的编码方式。Dim acCurDb As Document = Application.DocumentManager.MdiActiveDocument.DatabaseUsing acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()    Dim acLyrTblRec As LayerTableRecord    acLyrTblRec = acTrans.GetObject(acCurDb.LayerZero, OpenMode.ForRead)End UsingC#The following example manually disposes of the transaction after it is no longer needed.下例在不再需要时手工处置事务(释放内存)。Document acCurDb = Application.DocumentManager.MdiActiveDocument.Database;Transaction acTrans = acCurDb.TransactionManager.StartTransaction();LayerTableRecord acLyrTblRec;acLyrTblRec = acTrans.GetObject(acCurDb.LayerZero,                              OpenMode.ForRead) as LayerTableRecord;acTrans.Dispose();The following example uses the Using statement to dispose of the transaction after it is no longer needed. The Using statement is the preferred coding style.下例在不再需要时使用Using语句处置事务(释放内存)。Using语句是优先选用的编码方式。Document acCurDb = Application.DocumentManager.MdiActiveDocument.Database;using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()){    LayerTableRecord acLyrTblRec;    acLyrTblRec = acTrans.GetObject(acCurDb.LayerZero,                                    OpenMode.ForRead) as LayerTableRecord;}

2、Use Transactions with the Transaction Manager使用事务管理器管理事务Transactions are used to group multiple operations on multiple objects together as a single operation. Transactions are started and managed through the Transaction Manager. Once a transaction is started, you can then use the GetObject function to open an object.事务用来将对多个对象的多个操作编组为单个操作。事务通过事务管理器启动和管理。启动事务之后,我们就可以用GetObject方法打开对象。As you work with objects opened with GetObject, the Transaction manager keeps track of the changes that are being made to the object. Any new objects that you create and add to the database should be added to a transaction as well with the AddNewlyCreatedDBObject function. Once the objects have been edited or added to the database, you can save the changes made to the database and close all the open objects with the Commit function on the Transaction object created with the Transaction Manager. Once you are finished with a transaction, call the Dispose function close the transaction.当我们使用由GetObject打开的对象时,事务管理器会跟踪对该对象的修改。创建及添加到数据库的任何新对象也应同时调用AddNewlyCreatedDBObject方法将其添加到事务。对象编辑完并添加到数据库后,可以使用由事务管理器创建的事务对象的Commit方法保存对数据库的修改并关闭所有打开的对象。事务处理完毕后,调用Dispose方法关闭事务。Topics in this section本小节主题:·         Start a New Transaction and Open an Object 启动新事务并打开对象·         Commit and Rollback Changes 提交与回滚修改·         Nest Transactions 嵌套事务
2.1、Start a New Transaction and Open an Object启动新事务并打开对象The Transaction Manager is accessed from the TransactionManager property of the current database. Once a reference to the Transaction Manager is made, you use the StartTransaction method to start a new transaction. StartTransaction creates an instance of a Transaction object and allows you to open objects with the GetObject method.事务管理器从当前数据库的TransactionManager属性访问。一旦建立对事务管理器的引用,我们就可以使用StartTransaction方法启动一个新事务。StartTransaction方法创建一个Transaction对象的实例,并允许我们使用GetObject方法打开对象。All open objects opened during a transaction are closed at the end of the transaction. To end a transaction, call the Dispose method of a transaction object. If you use the Using and End Using keywords to indicate the start and end of a transaction, you do not need to call the Dispose method.在事务期间打开的所有对象在事务结束时都会被关闭。要结束事务,需调用事务对象的Dispose方法。如果使用了Using和End Using关键字来表示事务的开始和结束,就不需要调用Dispose方法。Prior to disposing of a transaction, you should commit any changes made with the Commit method. If the changes are not committed before a transaction is disposed, any changes made are rolled back to the state their were in prior to the start of the transaction. For more information on committing or rolling back changes made in a transaction, see Commit and Rollback Changes.在关闭事务之前,应使用Commit方法提交所作的任何修改。在关闭事务前如果修改没有被提交,那么可以将任何修改回滚到事务启动之前的状态。更多内容见下一小节。More than one transaction can be started. The number of active transactions can be retrieved with the NumberOfActiveTransactions property of the TransactionManager object while the top most or latest transaction can be retrieved with the TopTransaction property.可以启动不止一个事务。活动事务的个数可以用TransactionManager对象的NumberOfActiveTransactions属性获得,最上面的或者说最新的事务可以用TopTransaction属性获得。Transactions can be nested one inside of another in order to rollback some of the changes made during the execution of a routine. For more information on working with multiple transactions or nesting transactions, seeNest Transactions.在程序执行过程中,为了回滚所作的部分修改,可以将一个事务嵌套在另一个事务中。更多关于使用多个事务及嵌套事务的内容,见嵌套事务。Query objects 查询对象
The following example demonstrates how to open and read objects within using a transaction. You use the GetObject method to first open the BlockTable and then the Model space record.下面的示例演示怎样使用事务打开并读取对象。该示例中,使用GetObject方法先打开了BlockTable,然后打开了模型空间记录。VB.NETImports Autodesk.AutoCAD.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServices<CommandMethod("OpenTransactionManager")> _Public Sub OpenTransactionManager()'' Get the current document and databaseDim acDoc As Document = Application.DocumentManager.MdiActiveDocumentDim acCurDb As Database = acDoc.Database'' Start a transactionUsing acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()      '' Open the Block table for read      Dim acBlkTbl As BlockTable      acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)      '' Open the Block table record Model space for read      Dim acBlkTblRec As BlockTableRecord      acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _                                    OpenMode.ForRead)      '' Step through the Block table record      For Each acObjId As ObjectId In acBlkTblRec          acDoc.Editor.WriteMessage(vbLf & "DXF name: " & acObjId.ObjectClass().DxfName)          acDoc.Editor.WriteMessage(vbLf & "ObjectID: " & acObjId.ToString())          acDoc.Editor.WriteMessage(vbLf & "Handle: " & acObjId.Handle.ToString())          acDoc.Editor.WriteMessage(vbLf)      Next      '' Dispose of the transactionEnd UsingEnd SubC#using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;public static void OpenTransactionManager(){// Get the current document and database//获取当前文档及数据库Document acDoc = Application.DocumentManager.MdiActiveDocument;Database acCurDb = acDoc.Database;// Start a transaction启动事务using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()){      // Open the Block table for read以读的方式打开块表      BlockTable acBlkTbl;      acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,                                 OpenMode.ForRead) as BlockTable;      // Open the Block table record Model space for read      //以读的方式打开块表中的模型空间记录      BlockTableRecord acBlkTblRec;      acBlkTblRec = acTrans.GetObject(acBlkTbl,                                    OpenMode.ForRead) as BlockTableRecord;      // Step through the Block table record遍历块表记录      foreach (ObjectId asObjId in acBlkTblRec)      {          acDoc.Editor.WriteMessage("\nDXF name: " + asObjId.ObjectClass.DxfName);          acDoc.Editor.WriteMessage("\nObjectID: " + asObjId.ToString());          acDoc.Editor.WriteMessage("\nHandle: " + asObjId.Handle.ToString());          acDoc.Editor.WriteMessage("\n");      }      // Dispose of the transaction关闭事务}}
Add a new object to the database 向数据库添加新对象
The following example demonstrates how to add a circle object to the database with in a transaction. You use the GetObject method to first open the BlockTable for read and then the Model space record for write. After Model space is opened for write, you use the AppendEntity and AddNewlyCreatedDBObject function to append the new Circle object to Model space as well as the transaction.下例演示使用事务向数据库添加一个圆。用GetObject方法先以读的方式打开BlockTable块表,然后以写的方式打开模型空间记录。以写的方式打开模型空间后,就可以使用AppendEntity方法和AddNewlyCreatedDBObject方法向模型空间添加一个新的圆对象并同时将操作添加到事务。VB.NETImports Autodesk.AutoCAD.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServicesImports Autodesk.AutoCAD.Geometry<CommandMethod("AddNewCircleTransaction")> _Public Sub AddNewCircleTransaction()'' Get the current document and databaseDim acDoc As Document = Application.DocumentManager.MdiActiveDocumentDim acCurDb As Database = acDoc.Database'' Start a transactionUsing acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()      '' Open the Block table for read      Dim acBlkTbl As BlockTable      acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)      '' Open the Block table record Model space for write      Dim acBlkTblRec As BlockTableRecord      acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _                                    OpenMode.ForWrite)      '' Create a circle with a radius of 3 at 5,5      Dim acCirc As Circle = New Circle()      acCirc.Center = New Point3d(5, 5, 0)      acCirc.Radius = 3      '' Add the new object to Model space and the transaction      acBlkTblRec.AppendEntity(acCirc)      acTrans.AddNewlyCreatedDBObject(acCirc, True)      '' Commit the changes and dispose of the transaction      acTrans.Commit()End UsingEnd SubC#using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.Geometry;public static void AddNewCircleTransaction(){// Get the current document and database//获取当前文档及数据库Document acDoc = Application.DocumentManager.MdiActiveDocument;Database acCurDb = acDoc.Database;// Start a transaction启动事务using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()){      // Open the Block table for read以读的方式打开BlockTable块表      BlockTable acBlkTbl;      acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,                                 OpenMode.ForRead) as BlockTable;      // Open the Block table record Model space for write      //以写的方式打开模型空间记录      BlockTableRecord acBlkTblRec;      acBlkTblRec = acTrans.GetObject(acBlkTbl,                                    OpenMode.ForWrite) as BlockTableRecord;      // Create a circle with a radius of 3 at 5,5      //以半径3圆心5,5画圆      Circle acCirc = new Circle();      acCirc.Center = new Point3d(5, 5, 0);      acCirc.Radius = 3;      // Add the new object to Model space and the transaction      //将新对象添加到模型空间及事务      acBlkTblRec.AppendEntity(acCirc);      acTrans.AddNewlyCreatedDBObject(acCirc, true);      // Commit the changes and dispose of the transaction      //提交修改并关闭事务      acTrans.Commit();}}2.2、Commit and Rollback Changes提交与回滚修改When using transactions, you are able to decide when changes to objects are saved to the drawing database. You use the Commit method to save the changes made to the objects opened within a transaction. If your program encounters an error you can rollback any changes made within a transaction with the Abort method.使用了事务,我们就能决定什么时候将对对象所作的修改保存到图形数据库去。我们使用Commit方法保存对事务中打开的对象所作的修改。如果程序出错,我们可以使用Abort方法回滚事务中所作的修改。If Commit is not called before Dispose is called, all changes made within the transaction are rolled back. Whether Commit or Abort are called, you need to call Dispose to signal the end of the transaction. If the transaction object is started with the Using statement, you do not have to call Dispose.如果调用Dispose前没有调用Commit,则回滚事务这所作的全部修改。不管调用了Commit方法抑或Abort方法,我们都要电影Dispose方法发出结束事务的信号。(当然啦,)如果是使用Using语句启动的事务对象,就不必调用Dispose方法了。VB.NET'' Commit the changes made within the transaction<transaction>.Commit()'' Abort the transaction and rollback to the previous state<transaction>.Abort()C#// Commit the changes made within the transaction//提交事务内所作修改<transaction>.Commit();// Abort the transaction and rollback to the previous state//终止事务并回滚到之前的状态<transaction>.Abort();

2.3、Nest Transactions嵌套事务Transactions can be nested one inside another. You might have an outer transaction to undo all the changes made by your routine and inner transactions to undo just portions of the changes made. When you work with nested transactions, you start with a top transaction which is also the outer most transaction.一个事务可以嵌套在另一个事务里。我们可能用外层事务撤销程序所作的所有修改,而用内层事务只撤销部分修改。使用嵌套事务时,我们启动一个顶层事务,也称之为最外层事务。As you start new transactions, they are added into the previous transaction. Nested transactions must be committed or aborted in the opposite order in which they are created. So if you have three transactions, you must close the third or innermost one before the second and finally the first. If you abort the first transaction, the changes made by all three transactions is undone.启动的新事物会被添加进前一个事务里。必须按与创建相反的顺序提交或终止嵌套事务。因此,如果有三个事务,我们必须先关闭第三个或最内层那个,然后是第二个,最后是第一个。如果终止第一个事务,那么三个事务所作的所有修改就都被撤销了。The following illustration shows how transactions appear when nested.下图显示了事务嵌套的情形。                           http://hi.csdn.net/attachment/201107/18/0_1310948204HXgL.gifUse nested transactions to create and modify objects 使用嵌套事务创建及修改对象
The following example demonstrates using three transactions to create a Circle and Line object, and then change their colors. The color of the circle is changed in the second and third transaction, but since the third transaction is aborted only the changes made in the first and second transactions are saved to the database. Additionally, the number of active transactions is printed in the Command Line window as they are created and closed.下面这个例子演示使用三个事务创建一个圆和一条直线,然后改变它们的颜色。圆的颜色在第二个和第三个事务中修改,不过,由于终止了第三个事务,因此只有第一个和第二个事务中所作的修改被保存到数据库了。另外,创建和关闭事务时,在命令行窗口显示了活动事务的个数。VB.NETImports Autodesk.AutoCAD.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServicesImports Autodesk.AutoCAD.GeometryImports Autodesk.AutoCAD.EditorInput<CommandMethod("NestedTransactions")> _Public Sub NestedTransactions()'' Get the current document and databaseDim acDoc As Document = Application.DocumentManager.MdiActiveDocumentDim acCurDb As Database = acDoc.Database'' Create a reference to the Transaction ManagerDim acTransMgr As Autodesk.AutoCAD.DatabaseServices.TransactionManageracTransMgr = acCurDb.TransactionManager'' Create a new transactionUsing acTrans1 As Transaction = acTransMgr.StartTransaction()      '' Print the current number of active transactions      acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _                              acTransMgr.NumberOfActiveTransactions.ToString())      '' Open the Block table for read      Dim acBlkTbl As BlockTable      acBlkTbl = acTrans1.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)      '' Open the Block table record Model space for write      Dim acBlkTblRec As BlockTableRecord      acBlkTblRec = acTrans1.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _                                       OpenMode.ForWrite)      '' Create a circle with a radius of 3 at 5,5      Dim acCirc As Circle = New Circle()      acCirc.Center = New Point3d(5, 5, 0)      acCirc.Radius = 3      '' Add the new object to Model space and the transaction      acBlkTblRec.AppendEntity(acCirc)      acTrans1.AddNewlyCreatedDBObject(acCirc, True)      '' Create the second transaction      Using acTrans2 As Transaction = acTransMgr.StartTransaction()          acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _                                    acTransMgr.NumberOfActiveTransactions.ToString())          '' Change the circle's color          acCirc.ColorIndex = 5          '' Get the object that was added to Transaction 1 and set it to the color 5          Dim acLine As Line = New Line(New Point3d(2, 5, 0), New Point3d(10, 7, 0))          acLine.ColorIndex = 3          '' Add the new object to Model space and the transaction          acBlkTblRec.AppendEntity(acLine)          acTrans2.AddNewlyCreatedDBObject(acLine, True)          '' Create the third transaction          Using acTrans3 As Transaction = acTransMgr.StartTransaction()            acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _                                        acTransMgr.NumberOfActiveTransactions.ToString())            '' Change the circle's color            acCirc.ColorIndex = 3            '' Update the display of the drawing            acDoc.Editor.WriteMessage(vbLf)            acDoc.Editor.Regen()            '' Request to keep or discard the changes in the third transaction            Dim pKeyOpts As PromptKeywordOptions = New PromptKeywordOptions("")            pKeyOpts.Message = vbLf & "Keep color change "            pKeyOpts.Keywords.Add("Yes")            pKeyOpts.Keywords.Add("No")            pKeyOpts.Keywords.Default = "No"            pKeyOpts.AllowNone = True            Dim pKeyRes As PromptResult = acDoc.Editor.GetKeywords(pKeyOpts)            If pKeyRes.StringResult = "No" Then                  '' Discard the changes in transaction 3                  acTrans3.Abort()            Else                  '' Save the changes in transaction 3                  acTrans3.Commit()            End If            '' Dispose the transaction          End Using          acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _                                    acTransMgr.NumberOfActiveTransactions.ToString())          '' Keep the changes to transaction 2          acTrans2.Commit()      End Using      acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _                              acTransMgr.NumberOfActiveTransactions.ToString())      '' Keep the changes to transaction 1      acTrans1.Commit()End UsingEnd SubC#using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.EditorInput;public static void NestedTransactions(){// Get the current document and database//获取当前文档和数据库Document acDoc = Application.DocumentManager.MdiActiveDocument;Database acCurDb = acDoc.Database;// Create a reference to the Transaction Manager//创建对事务管理器的引用Autodesk.AutoCAD.DatabaseServices.TransactionManager acTransMgr;acTransMgr = acCurDb.TransactionManager;// Create a new transaction新建事务using (Transaction acTrans1 = acTransMgr.StartTransaction()){      // Print the current number of active transactions      //打印当前活动事务的个数      acDoc.Editor.WriteMessage("\nNumber of transactions active: " +                              acTransMgr.NumberOfActiveTransactions.ToString());      // Open the Block table for read      //以读的方式打开BlockTable块表      BlockTable acBlkTbl;      acBlkTbl = acTrans1.GetObject(acCurDb.BlockTableId,                                    OpenMode.ForRead) as BlockTable;      // Open the Block table record Model space for write      //以写的方式打开块表的模型空间记录      BlockTableRecord acBlkTblRec;      acBlkTblRec = acTrans1.GetObject(acBlkTbl,                                       OpenMode.ForWrite) as BlockTableRecord;      // Create a circle with a radius of 3 at 5,5      //创建半径2圆心5,5的圆      Circle acCirc = new Circle();      acCirc.Center = new Point3d(5, 5, 0);      acCirc.Radius = 3;      // Add the new object to Model space and the transaction      //添加新对象到模型空间并添加事务      acBlkTblRec.AppendEntity(acCirc);      acTrans1.AddNewlyCreatedDBObject(acCirc, true);      // Create the second transaction      //创建第二个事务      using (Transaction acTrans2 = acTransMgr.StartTransaction())      {          acDoc.Editor.WriteMessage("\nNumber of transactions active: " +                                    acTransMgr.NumberOfActiveTransactions.ToString());          // Change the circle's color修改圆的颜色          acCirc.ColorIndex = 5;          // Get the object that was added to Transaction 1 and set it to the color 5          //获取添加到事务1的那个对象并设置其颜色为5(Blue蓝色)          Line acLine = new Line(new Point3d(2, 5, 0), new Point3d(10, 7, 0));          acLine.ColorIndex = 3;          // Add the new object to Model space and the transaction          //添加新对象到模型空间并添加事务          acBlkTblRec.AppendEntity(acLine);          acTrans2.AddNewlyCreatedDBObject(acLine, true);          // Create the third transaction          //创建第三个事务          using (Transaction acTrans3 = acTransMgr.StartTransaction())          {            acDoc.Editor.WriteMessage("\nNumber of transactions active: " +                                        acTransMgr.NumberOfActiveTransactions.ToString());            // Change the circle's color修改圆的颜色            acCirc.ColorIndex = 3;            // Update the display of the drawing更新图形显示            acDoc.Editor.WriteMessage("\n");            acDoc.Editor.Regen();            // Request to keep or discard the changes in the third transaction            //询问保持还是取消第三个事务中的修改            PromptKeywordOptions pKeyOpts = new PromptKeywordOptions("");            pKeyOpts.Message = "\nKeep color change ";            pKeyOpts.Keywords.Add("Yes");            pKeyOpts.Keywords.Add("No");            pKeyOpts.Keywords.Default = "No";            pKeyOpts.AllowNone = true;            PromptResult pKeyRes = acDoc.Editor.GetKeywords(pKeyOpts);            if (pKeyRes.StringResult == "No")            {                  // Discard the changes in transaction 3                  //取消事务3中的修改                  acTrans3.Abort();            }            else            {                  // Save the changes in transaction 3                  //保存事务3中的修改                  acTrans3.Commit();            }            // Dispose the transaction关闭事务3          }          acDoc.Editor.WriteMessage("\nNumber of transactions active: " +                                    acTransMgr.NumberOfActiveTransactions.ToString());          // Keep the changes to transaction 2保留事务2中的修改          acTrans2.Commit();      }      acDoc.Editor.WriteMessage("\nNumber of transactions active: " +                              acTransMgr.NumberOfActiveTransactions.ToString());      // Keep the changes to transaction 1保留事务1中的修改      acTrans1.Commit();}}3、Open and Close Objects without the Transaction Manager不使用事务管理器打开和关闭对象Transactions make it easier to open and work with multiple objects, but they are not the only way to open and edit objects. Other than using a transaction, you can open and close objects using the Open and Close methods. You still need to obtain an object id to use the Open method. Like the GetObject method used with transactions, you need to specify an open mode and the return value is an object. If you make changes to an object after you opened it with the Open method, you can use the Cancel method to rollback all the changes made since it was opened. Cancel must be called on each object in which you want to rollback.事务使得打开和使用多个对象变得容易多了,不过这并不是打开和编辑对象的唯一方式。除了使用事务外,我们还可以使用Open方法和Close方法打开和关闭对象。使用Open方法仍然需要先获取对象标志ObjectId,就像使用事务时的GetObject方法一样,我们需要指定打开模式并返回一个对象。使用Open方法打开对象后如果对这个对象进行了修改,我们可以使用Cancel方法回滚对象打开以来的所有修改。当要回滚时,必须对每个对象都调用Cancel方法。Note Objects must be paired with an open and close operation. If you use the Open method on an object, you must close it using either the Close or Cancel method. Failure to close the object will lead to read access violations and cause AutoCAD to become unstable.注意:打开对象和关闭对象的操作必须成对出现。如果我们对一个对象使用了Open方法,就必须使用Close方法或Cancel方法关闭它。关闭对象失败会导致读取违例并导致AutoCAD不稳定。If you need to work with a single object, using the Open and Close methods can reduce the number of lines of code that you might otherwise have to write compared to working with the Transaction Manager. However, using transactions is the recommended way of opening and closing objects.如果我们只使用一个对象,和使用事务管理器相比,使用Open方法及Close方法能减少编写代码的行数。不过,还是推荐使用事务来打开和关闭对象。Warning You should not use the Open and Close methods when using transactions, as objects might not get opened or closed properly by the Transaction Manager which could cause AutoCAD to crash.警告:使用事务时不能使用Open和Close方法,事务管理器不能正确打开和关闭对象会导致AutoCAD崩溃。Query objects 查询对象
The following example demonstrates how to open and close objects without using a transaction and the GetObject method. To see the same example using the Transaction Manager, see Start a New Transaction and Open an Object.下面的示例演示不使用事务及GetObject方法怎样打开和关闭对象。可以和前面一节使用事务管理器的例子比较一下。VB.NETImports Autodesk.AutoCAD.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServices<CommandMethod("OpenCloseObjectId")> _Public Sub OpenCloseObjectId()'' Get the current document and databaseDim acDoc As Document = Application.DocumentManager.MdiActiveDocumentDim acCurDb As Database = acDoc.Database'' Open the Block table for readDim acBlkTbl As BlockTableacBlkTbl = acCurDb.BlockTableId.Open(OpenMode.ForRead)'' Open the Block table record Model space for readDim acBlkTblRec As BlockTableRecordacBlkTblRec = acBlkTbl(BlockTableRecord.ModelSpace).Open(OpenMode.ForRead)'' Step through the Block table recordFor Each acObjId As ObjectId In acBlkTblRec      acDoc.Editor.WriteMessage(vbLf & "DXF name: " & acObjId.ObjectClass().DxfName)      acDoc.Editor.WriteMessage(vbLf & "ObjectID: " & acObjId.ToString())      acDoc.Editor.WriteMessage(vbLf & "Handle: " & acObjId.Handle.ToString())      acDoc.Editor.WriteMessage(vbLf)Next'' Close the Block table recordacBlkTblRec.Close()acBlkTblRec.Dispose()'' Close the Block tableacBlkTbl.Close()acBlkTbl.Dispose()End SubC#using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;public static void OpenCloseObjectId(){// Get the current document and database//获取当前文档及数据库Document acDoc = Application.DocumentManager.MdiActiveDocument;Database acCurDb = acDoc.Database;// Open the Block table for read以读的方式打开块表BlockTable acBlkTbl;acBlkTbl = acCurDb.BlockTableId.Open(OpenMode.ForRead) as BlockTable;   // Open the Block table record Model space for read//以读的方式打开模型空间记录BlockTableRecord acBlkTblRec;acBlkTblRec = acBlkTbl.Open(OpenMode.ForRead) as BlockTableRecord;// Step through the Block table record遍历块表记录foreach (ObjectId acObjId in acBlkTblRec){      acDoc.Editor.WriteMessage("\nDXF name: " + acObjId.ObjectClass.DxfName);      acDoc.Editor.WriteMessage("\nObjectID: " + acObjId.ToString());      acDoc.Editor.WriteMessage("\nHandle: " + acObjId.Handle.ToString());      acDoc.Editor.WriteMessage("\n");}// Close the Block table record关闭块表记录acBlkTblRec.Close();acBlkTblRec.Dispose();// Close the Block table关闭块表acBlkTbl.Close();acBlkTbl.Dispose();}Add a new object to the database 向数据库添加新对象
This example demonstrates how to create a new object and append it to Model space without using the Transaction manager. To see the same example using the Transaction manager, see Start a New Transaction and Open an Object.本例演示不使用事务管理器怎样创建新对象并添加到模型空间。可以和前面一节使用事务管理器的例子比较一下。
VB.NETImports Autodesk.AutoCAD.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServicesImports Autodesk.AutoCAD.Geometry<CommandMethod("AddNewCircleOpenClose")> _Public Sub AddNewCircleOpenClose()'' Get the current document and databaseDim acDoc As Document = Application.DocumentManager.MdiActiveDocumentDim acCurDb As Database = acDoc.Database'' Open the Block table for readDim acBlkTbl As BlockTableacBlkTbl = acCurDb.BlockTableId.Open(OpenMode.ForRead)'' Open the Block table record Model space for writeDim acBlkTblRec As BlockTableRecordacBlkTblRec = acBlkTbl(BlockTableRecord.ModelSpace).Open(OpenMode.ForWrite)'' Create a circle with a radius of 3 at 5,5Dim acCirc As Circle = New Circle()acCirc.Center = New Point3d(5, 5, 0)acCirc.Radius = 3'' Add the new object to Model space and the transactionacBlkTblRec.AppendEntity(acCirc)'' Close the circle objectacCirc.Close()acCirc.Dispose()'' Close the Block table recordacBlkTblRec.Close()acBlkTblRec.Dispose()'' Close the Block tableacBlkTbl.Close()acBlkTbl.Dispose()End SubC#using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.Geometry;public static void AddNewCircleOpenClose(){// Get the current document and database//获取当前文档及数据库Document acDoc = Application.DocumentManager.MdiActiveDocument;Database acCurDb = acDoc.Database;// Open the Block table for read以读的方式打开块表BlockTable acBlkTbl;acBlkTbl = acCurDb.BlockTableId.Open(OpenMode.ForRead) as BlockTable;// Open the Block table record Model space for write//以写的方式打开模型空间记录BlockTableRecord acBlkTblRec;acBlkTblRec = acBlkTbl.Open(OpenMode.ForWrite)                  as BlockTableRecord;// Create a circle with a radius of 3 at 5,5//创建园,半径3、圆心5,5Circle acCirc = new Circle();acCirc.Center = new Point3d(5, 5, 0);acCirc.Radius = 3;// Add the new object to Model space and the transaction//将新对象添加到模型空间及事务acBlkTblRec.AppendEntity(acCirc);// Close the circle object关闭对象园acCirc.Close();acCirc.Dispose();// Close the Block table record关闭块表记录acBlkTblRec.Close();acBlkTblRec.Dispose();// Close the Block table关闭块表acBlkTbl.Close();acBlkTbl.Dispose();}4、Upgrade and Downgrade Open Objects升级打开对象与降级打开对象Once an object is opened using either the GetObject or Open methods, you can change the current open mode of an object with the UpgradeOpen and DowngradeOpen methods. The UpgradeOpen method changes an object open for read to write mode, while DowngradeOpen changes an object open for write to read mode. You do not need to pair a call to DowngradeOpen with each UpgradeOpen call, since closing of an object or disposing of a transaction will sufficiently cleanup the open state of an entity.使用GetObject方法或Open方法打开一个对象后,我们可以使用UpgradeOpen方法与DowngradeOpen方法改变对象当前的打开模式。UpgradeOpen方法将对象的打开模式由读变为写,DowngradeOpen方法将对象的打开模式由写变为读。没有必要为每个UpgradeOpen调用配上一个DowngradeOpen调用,因为对象或事务的关闭更能清除实体的打开状态。When you go to open an object, open the object in the mode that you will use the object in. Do not just open an object for write when you might only need to query an object. It is more efficient to open an object for read and query the object’s properties than it is to open the object for write and query the object’s properties.试图打开一个对象时,想怎么使用对象就以相应的模式打开这个对象。当只是查询一个对象时不要以写的模式打开。以读的方式打开对象并查询其属性比以写的方式打开对象并查询其属性效率高得多。Opening an object for write causes undo filing to start for the object. Undo filing is used to track changes to an object, so any changes made can be rolled back. If you are uncertain if you need to modify an object, it is best to open an object for read and then upgrade it for write. This will help to reduce the overhead of your program.以写的方式打开对象会启动该对象的撤销队列登记。撤销队列登记用来跟踪对象的修改,这样所做的任何修改都能被回滚。如果不能确定是否需要修改对象,最好以读的方式打开对象,然后再升级为写模式。这样做能帮助减少程序开销。An example of when you might use UpgradeOpen is when you might be querying objects to see if they match a specific condition, and if the condition is met then you would upgrade the object from read to write mode to make modifications to it.关于何时使用UpgradeOpen方法的一个例子是,当想查询对象看是否满足某个指定条件,并且如果满足条件就将对象的打开模式由读升级为写并对其进行修改时。Open Notifications 以通知方式打开
Similarly, if an object is open for notify and you receive a notification, you use UpgradeFromNotify to upgrade the object for write. Then you would use DowngradeToNotify to downgrade the object back to notify. UpgradeFromNotify and DowngradeFromNotify are reserved for use in methods that are intended to be used by an object to change its own open status so that it can safely modify itself.类似的情形,如果以通知的方式打开对象并接受到一个通知,可以用UpgradeFromNotify方法将对象打开方式升级为写,然后还可以用DowngradeFromNotify方法将对象打开方式降级为通知方式。UpgradeFromNotify和DowngradeFromNotify是为了对象试图修改自己的打开状态以便安全地修改自己的那些方法而保留的。VB.NETImports Autodesk.AutoCAD.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServices<CommandMethod("FreezeDoorLayer")> _Public Sub FreezeDoorLayer()'' Get the current document and databaseDim acDoc As Document = Application.DocumentManager.MdiActiveDocumentDim acCurDb As Database = acDoc.Database'' Start a transactionUsing acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()      '' Open the Layer table for read      Dim acLyrTbl As LayerTable      acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead)      '' Step through each layer and update those that start with 'Door'      For Each acObjId As ObjectId In acLyrTbl          '' Open the Layer table record for read          Dim acLyrTblRec As LayerTableRecord          acLyrTblRec = acTrans.GetObject(acObjId, OpenMode.ForRead)          '' Check to see if the layer's name starts with 'Door'          If (acLyrTblRec.Name.StartsWith("Door", _                                          StringComparison.OrdinalIgnoreCase) = True) Then            '' Check to see if the layer is current, if so then do not freeze it            If acLyrTblRec.ObjectId <> acCurDb.Clayer Then                  '' Change from read to write mode                  acLyrTblRec.UpgradeOpen()                  '' Freeze the layer                  acLyrTblRec.IsFrozen = True            End If          End If      Next      '' Commit the changes and dispose of the transaction      acTrans.Commit()End UsingEnd SubC#using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;public static void FreezeDoorLayer(){// Get the current document and database//获取当前文档及数据库Document acDoc = Application.DocumentManager.MdiActiveDocument;Database acCurDb = acDoc.Database;// Start a transaction启动事务using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()){      // Open the Layer table for read以读的方式打开图层表      LayerTable acLyrTbl;      acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,                                 OpenMode.ForRead) as LayerTable;      // Step through each layer and update those that start with 'Door'      //遍历图层并将图层名以‘Door’开头的图层升级为写打开方式;      foreach (ObjectId acObjId in acLyrTbl)      {          // Open the Layer table record for read以读打开图层表记录          LayerTableRecord acLyrTblRec;          acLyrTblRec = acTrans.GetObject(acObjId,                                          OpenMode.ForRead) as LayerTableRecord;          // Check to see if the layer's name starts with 'Door'          //检查图层名是否以‘Door’开头          if (acLyrTblRec.Name.StartsWith("Door",                                          StringComparison.OrdinalIgnoreCase) == true)          {            // Check to see if the layer is current, if so then do not freeze it            //检查是否为当前层,是则不冻结            if (acLyrTblRec.ObjectId != acCurDb.Clayer)            {                  // Change from read to write mode升级打开方式                  acLyrTblRec.UpgradeOpen();                  // Freeze the layer冻结图层                  acLyrTblRec.IsFrozen = true;            }          }      }      // Commit the changes and dispose of the transaction      //提交修改并关闭事务      acTrans.Commit();}}
页: [1]
查看完整版本: [资料] 创建和编辑AutoCAD实体(一) 打开和关闭对象