明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 918|回复: 3

【转载】将C# class 序列化后存储到AutoCAD实体的XRecord中

[复制链接]
发表于 2024-9-6 11:22:30 | 显示全部楼层 |阅读模式
Serialize a .NET class into an AutoCAD drawing database[size=1.2em]
I would like to serialize my .NET class into an AutoCAD drawing database, so it is saved into the drawing, and I can recreate my class again (deserialize it), when the drawing is reopened. How could I do it?

Solution
You could use the .NET serialization technique to serialize your class into a binary stream and then you can save it in the drawing as a bunch of binary chunks. You could save the ResultBuffer to an object's XData or into an Xrecord.Data of an entity or an item in the Named Objects Dictionary (NOD). DevNote TS2563 tells you what the difference is between using XData and Xrecord. If you are saving it into an XData, then the ResultBuffer needs to start with a registered application name. Here is a sample which shows this:
  1. using System;
  2. using System.Runtime.Serialization;
  3. using System.Runtime.Serialization.Formatters.Binary;
  4. using System.IO;
  5. using System.Security.Permissions;

  6. using Autodesk.AutoCAD.Runtime;
  7. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
  8. using Autodesk.AutoCAD.DatabaseServices;
  9. using Autodesk.AutoCAD.EditorInput;

  10. [assembly: CommandClass(typeof(MyClassSerializer.Commands))]

  11. namespace MyClassSerializer
  12. {
  13.   // We need it to help with deserialization

  14.   public sealed class MyBinder : SerializationBinder
  15.   {
  16.     public override System.Type BindToType(
  17.       string assemblyName,
  18.       string typeName)
  19.     {
  20.       return Type.GetType(string.Format("{0}, {1}",
  21.         typeName, assemblyName));
  22.     }
  23.   }

  24.   // Helper class to write to and from ResultBuffer

  25.   public class MyUtil
  26.   {
  27.     const int kMaxChunkSize = 127;

  28.     public static ResultBuffer StreamToResBuf(
  29.       MemoryStream ms, string appName)
  30.     {
  31.       ResultBuffer resBuf =
  32.         new ResultBuffer(
  33.           new TypedValue(
  34.             (int)DxfCode.ExtendedDataRegAppName, appName));

  35.       for (int i = 0; i < ms.Length; i += kMaxChunkSize)
  36.       {
  37.         int length = (int)Math.Min(ms.Length - i, kMaxChunkSize);
  38.         byte[] datachunk = new byte[length];
  39.         ms.Read(datachunk, 0, length);
  40.         resBuf.Add(
  41.           new TypedValue(
  42.             (int)DxfCode.ExtendedDataBinaryChunk, datachunk));
  43.       }

  44.       return resBuf;
  45.     }

  46.     public static MemoryStream ResBufToStream(ResultBuffer resBuf)
  47.     {
  48.       MemoryStream ms = new MemoryStream();
  49.       TypedValue[] values = resBuf.AsArray();

  50.       // Start from 1 to skip application name

  51.       for (int i = 1; i < values.Length; i++)
  52.       {
  53.         byte[] datachunk = (byte[])values.Value;
  54.         ms.Write(datachunk, 0, datachunk.Length);
  55.       }
  56.       ms.Position = 0;

  57.       return ms;
  58.     }
  59.   }

  60.   [Serializable]
  61.   public abstract class MyBaseClass : ISerializable
  62.   {
  63.     public const string appName = "MyApp";

  64.     public MyBaseClass()
  65.     {
  66.     }

  67.     public static object NewFromResBuf(ResultBuffer resBuf)
  68.     {
  69.       BinaryFormatter bf = new BinaryFormatter();
  70.       bf.Binder = new MyBinder();

  71.       MemoryStream ms = MyUtil.ResBufToStream(resBuf);

  72.       MyBaseClass mbc = (MyBaseClass)bf.Deserialize(ms);

  73.       return mbc;
  74.     }

  75.     public static object NewFromEntity(Entity ent)
  76.     {
  77.       using (
  78.         ResultBuffer resBuf = ent.GetXDataForApplication(appName))
  79.       {
  80.         return NewFromResBuf(resBuf);
  81.       }
  82.     }

  83.     public ResultBuffer SaveToResBuf()
  84.     {
  85.       BinaryFormatter bf = new BinaryFormatter();
  86.       MemoryStream ms = new MemoryStream();
  87.       bf.Serialize(ms, this);
  88.       ms.Position = 0;

  89.       ResultBuffer resBuf = MyUtil.StreamToResBuf(ms, appName);

  90.       return resBuf;
  91.     }

  92.     public void SaveToEntity(Entity ent)
  93.     {
  94.       // Make sure application name is registered
  95.       // If we were to save the ResultBuffer to an Xrecord.Data,
  96.       // then we would not need to have a registered application name

  97.       Transaction tr =
  98.         ent.Database.TransactionManager.TopTransaction;

  99.       RegAppTable regTable =
  100.         (RegAppTable)tr.GetObject(
  101.           ent.Database.RegAppTableId, OpenMode.ForWrite);
  102.       if (!regTable.Has(MyClass.appName))
  103.       {
  104.         RegAppTableRecord app = new RegAppTableRecord();
  105.         app.Name = MyClass.appName;
  106.         regTable.Add(app);
  107.         tr.AddNewlyCreatedDBObject(app, true);
  108.       }

  109.       using (ResultBuffer resBuf = SaveToResBuf())
  110.       {
  111.         ent.XData = resBuf;
  112.       }
  113.     }

  114.     [SecurityPermission(SecurityAction.LinkDemand,
  115.     public abstract void GetObjectData(
  116.       SerializationInfo info, StreamingContext context);
  117.   }

  118.   [Serializable]
  119.   public class MyClass : MyBaseClass
  120.   {
  121.     public string myString;
  122.     public double myDouble;

  123.     public MyClass()
  124.     {
  125.     }

  126.     protected MyClass(
  127.       SerializationInfo info, StreamingContext context)
  128.     {
  129.       if (info == null)
  130.         throw new System.ArgumentNullException("info");

  131.       myString = (string)info.GetValue("MyString", typeof(string));
  132.       myDouble = (double)info.GetValue("MyDouble", typeof(double));
  133.     }

  134.     [SecurityPermission(SecurityAction.LinkDemand,
  135.     public override void GetObjectData(
  136.       SerializationInfo info, StreamingContext context)
  137.     {
  138.       info.AddValue("MyString", myString);
  139.       info.AddValue("MyDouble", myDouble);
  140.     }

  141.     // Just for testing purposes

  142.     public override string ToString()
  143.     {
  144.       return base.ToString() + "," +
  145.         myString + "," + myDouble.ToString();
  146.     }
  147.   }

  148.   public class Commands
  149.   {
  150.     [CommandMethod("SaveClassToEntityXData")]
  151.     static public void SaveClassToEntityXData()
  152.     {
  153.       Database db = acApp.DocumentManager.MdiActiveDocument.Database;
  154.       Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;

  155.       PromptEntityResult per =
  156.         ed.GetEntity("Select entity to save class to:\n");
  157.       if (per.Status != PromptStatus.OK)
  158.         return;

  159.       // Create an object

  160.       MyClass mc = new MyClass();
  161.       mc.myDouble = 1.2345;
  162.       mc.myString = "Some text";

  163.       // Save it to the document

  164.       using (
  165.         Transaction tr = db.TransactionManager.StartTransaction())
  166.       {
  167.         Entity ent =
  168.           (Entity)tr.GetObject(per.ObjectId, OpenMode.ForWrite);

  169.         mc.SaveToEntity(ent);

  170.         tr.Commit();
  171.       }

  172.       // Write some info about the results

  173.       ed.WriteMessage(
  174.         "Content of MyClass we serialized:\n {0} \n", mc.ToString());
  175.     }

  176.     [CommandMethod("GetClassFromEntityXData")]
  177.     static public void GetClassFromEntityXData()
  178.     {
  179.       Database db = acApp.DocumentManager.MdiActiveDocument.Database;
  180.       Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;

  181.       PromptEntityResult per =
  182.         ed.GetEntity("Select entity to get class from:\n");
  183.       if (per.Status != PromptStatus.OK)
  184.         return;

  185.       // Get back the class

  186.       using (
  187.         Transaction tr = db.TransactionManager.StartTransaction())
  188.       {
  189.         Entity ent =
  190.           (Entity)tr.GetObject(per.ObjectId, OpenMode.ForRead);

  191.         MyClass mc = (MyClass)MyClass.NewFromEntity(ent);

  192.         // Write some info about the results

  193.         ed.WriteMessage(
  194.           "Content of MyClass we deserialized:\n {0} \n",
  195.           mc.ToString());

  196.         tr.Commit();
  197.       }
  198.     }
  199.   }
  200. }



Posted at 09:56 AM in .NET, Adam Nagy, AutoCAD | Permalink




 楼主| 发表于 2024-9-6 11:30:15 | 显示全部楼层
本帖最后由 qq1254582201 于 2024-9-6 11:33 编辑

Adding extension dictionary[size=1.2em]
Each AutoCAD object can store a custom data with it. Normally this functionality is used by AutoCAD graphical entities to store non graphical data. For example, an AutoCAD line can store a string or/and a double with it (in its extension dictionary). Below code shows the procedure to add an extension dictionary strong a double and a string


  1. [CommandMethod("AddExtensionDictionary")]
  2. public void AddExtensionDictionary()
  3. {
  4.     Document doc = Application.DocumentManager.MdiActiveDocument;
  5.     Database db = doc.Database;
  6.     Editor ed = doc.Editor;

  7.     PromptEntityResult ers = ed.GetEntity("Select entity to add" +
  8.                                            " extension dictionary ");
  9.     if (ers.Status != PromptStatus.OK)
  10.         return;

  11.     using (Transaction tr = db.TransactionManager.StartTransaction())
  12.     {
  13.         DBObject dbObj = tr.GetObject(ers.ObjectId,
  14.                                                    OpenMode.ForRead);

  15.         ObjectId extId = dbObj.ExtensionDictionary;

  16.         if (extId == ObjectId.Null)
  17.         {
  18.             dbObj.UpgradeOpen();
  19.             dbObj.CreateExtensionDictionary();
  20.             extId = dbObj.ExtensionDictionary;
  21.         }

  22.         //now we will have extId...
  23.         DBDictionary dbExt =
  24.                 (DBDictionary)tr.GetObject(extId, OpenMode.ForRead);

  25.         //if not present add the data
  26.         if (!dbExt.Contains("TEST"))
  27.         {
  28.             dbExt.UpgradeOpen();
  29.             Xrecord xRec = new Xrecord();
  30.             ResultBuffer rb = new ResultBuffer();
  31.             rb.Add(new TypedValue(
  32.                       (int)DxfCode.ExtendedDataAsciiString, "Data"));
  33.             rb.Add(new TypedValue((int)DxfCode.ExtendedDataReal,
  34.                                                               10.2));

  35.             //set the data
  36.             xRec.Data = rb;

  37.             dbExt.SetAt("TEST", xRec);
  38.             tr.AddNewlyCreatedDBObject(xRec, true);
  39.         }
  40.         else
  41.         {
  42.             ed.WriteMessage("entity contains the TEST data\n");
  43.         }


  44.         tr.Commit();
  45.     }

  46. }



Posted at 03:17 AM in .NET, AutoCAD, Virupaksha Aithal | Permalink




 楼主| 发表于 2024-9-6 12:03:39 | 显示全部楼层
本帖最后由 qq1254582201 于 2024-9-6 12:09 编辑

AutoCAD .NET XData: Read Existing XData from Entity/Object
AutoCAD has supported the eXtended Data for long time, back to the ADS era. In the AutoCAD .NET world, those functionalities regarding the XData manipulations and even those extended DXF codes are wrapped nicely into some classes, structs, methods and enums.
However, because of the different syntaxes in the new AutoCAD .NET and the old ADS, even for people coming from the ADS time and using those old ResultBuffer a lot, they may still be confused about some classes, methods, and enum values as far as XData and ResultBuffer are concerned.
Previously, we added various XData types to a single picked AutoCAD entity. In this post, let’s read out those XData with various types and assign them to variables of proper types.

  1. [CommandMethod("ReadXData")]
  2. public static void ReadXData_Method()
  3. {
  4.     const string TestAppName = "XDataAppName1";
  5.     Database db = HostApplicationServices.WorkingDatabase;
  6.     Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
  7.     try
  8.     {
  9.         PromptEntityResult prEntRes = ed.GetEntity("Select an Entity");
  10.         if (prEntRes.Status == PromptStatus.OK)
  11.         {
  12.             using (Transaction tr = db.TransactionManager.StartTransaction())
  13.             {
  14.                 Entity ent = (Entity)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);
  15.                 ResultBuffer rb = ent.GetXDataForApplication(TestAppName);
  16.                 if (rb != null)
  17.                 {
  18.                     TypedValue[] rvArr = rb.AsArray();
  19.                     foreach (TypedValue tv in rvArr)
  20.                     {
  21.                         switch ((DxfCode)tv.TypeCode)
  22.                         {
  23.                             case DxfCode.ExtendedDataRegAppName:
  24.                                 string appName = (string)tv.Value;
  25.                                 ed.WriteMessage("\nXData of appliation name (1001) {0}:", appName);
  26.                                 break;
  27.                             case DxfCode.ExtendedDataAsciiString:
  28.                                 string asciiStr = (string)tv.Value;
  29.                                 ed.WriteMessage("\n\tAscii string (1000): {0}", asciiStr);
  30.                                 break;
  31.                             case DxfCode.ExtendedDataLayerName:
  32.                                 string layerName = (string)tv.Value;
  33.                                 ed.WriteMessage("\n\tLayer name (1003): {0}", layerName);
  34.                                 break;
  35.                             case DxfCode.ExtendedDataBinaryChunk:
  36.                                 Byte[] chunk = tv.Value as Byte[];
  37.                                 string chunkText = Encoding.ASCII.GetString(chunk);
  38.                                 ed.WriteMessage("\n\tBinary chunk (1004): {0}", chunkText);
  39.                                 break;
  40.                             case DxfCode.ExtendedDataHandle:
  41.                                 ed.WriteMessage("\n\tObject handle (1005): {0}", tv.Value);
  42.                                 break;
  43.                             case DxfCode.ExtendedDataXCoordinate:
  44.                                 Point3d pt = (Point3d)tv.Value;
  45.                                 ed.WriteMessage("\n\tPoint (1010): {0}", pt.ToString());
  46.                                 break;
  47.                             case DxfCode.ExtendedDataWorldXCoordinate:
  48.                                 Point3d pt1 = (Point3d)tv.Value;
  49.                                 ed.WriteMessage("\n\tWorld point (1011): {0}", pt1.ToString());
  50.                                 break;
  51.                             case DxfCode.ExtendedDataWorldXDisp:
  52.                                 Point3d pt2 = (Point3d)tv.Value;
  53.                                 ed.WriteMessage("\n\tDisplacement (1012): {0}", pt2.ToString());
  54.                                 break;
  55.                             case DxfCode.ExtendedDataWorldXDir:
  56.                                 Point3d pt3 = (Point3d)tv.Value;
  57.                                 ed.WriteMessage("\n\tDirection (1013): {0}", pt3.ToString());
  58.                                 break;
  59.                             case DxfCode.ExtendedDataControlString:
  60.                                 string ctrStr = (string)tv.Value;
  61.                                 ed.WriteMessage("\n\tControl string (1002): {0}", ctrStr);
  62.                                 break;
  63.                             case DxfCode.ExtendedDataReal:
  64.                                 double realValue = (double)tv.Value;
  65.                                 ed.WriteMessage("\n\tReal (1040): {0}", realValue);
  66.                                 break;
  67.                             case DxfCode.ExtendedDataDist:
  68.                                 double dist = (double)tv.Value;
  69.                                 ed.WriteMessage("\n\tDistance (1041): {0}", dist);
  70.                                 break;
  71.                             case DxfCode.ExtendedDataScale:
  72.                                 double scale = (double)tv.Value;
  73.                                 ed.WriteMessage("\n\tScale (1042): {0}", scale);
  74.                                 break;
  75.                             case DxfCode.ExtendedDataInteger16:
  76.                                 Int16 int16 = (short)tv.Value;
  77.                                 ed.WriteMessage("\n\tInt16 (1070): {0}", int16);
  78.                                 break;
  79.                             case DxfCode.ExtendedDataInteger32:
  80.                                 Int32 int32 = (Int32)tv.Value;
  81.                                 ed.WriteMessage("\n\tInt32 (1071): {0}", int32);
  82.                                 break;
  83.                             default:
  84.                                 ed.WriteMessage("\n\tUnknown XData DXF code.");
  85.                                 break;
  86.                         }
  87.                     }
  88.                 }
  89.                 else
  90.                     ed.WriteMessage("The entity does not have the {0} XData.", TestAppName);
  91.                 tr.Commit();
  92.             }
  93.         }
  94.     }
  95.     catch (System.Exception ex)
  96.     {
  97.         ed.WriteMessage(ex.ToString());
  98.     }
  99. }


Here is he output in the AutoCAD command line window.
Command: ADDXDAta
Select an Entity to attach XDATA:
Command: READXDATA
Select an Entity:
XData of appliation name (1001) XDataAppName1:
Ascii string (1000): String1
Layer name (1003): 0
Binary chunk (1004): BinaryChunk
Object handle (1005): A53
Point (1010): (1.1,2.1,3.1)
World point (1011): (1.2,2.2,3.2)
Displacement (1012): (1.3,2.3,3.3)
Direction (1013): (1.4,2.4,3.4)
Control string (1002): {
Real (1040): 12345.6789
Distance (1041): 25.25
Scale (1042): 0.2
Control string (1002): }
Int16 (1070): 16
Int32 (1071): 32
The code seems simple and straightforward, but there are quite some tips and tricks there.
&#8226; The DBObject.GetXDataForApplication() method can retrieve the XData with the specified application name from a DBObject or Entity.
&#8226; All XData starts with the 1001 (DxfCode.ExtendedDataRegAppName) code.
&#8226; The XData Application Name can be registered through creating a RegAppTableRecord and adding it to the RegAppTable (another kind of AutoCAD symbol table).
&#8226; The ResultBuffer is a list of TypedValue which is a pair of type and value.
&#8226; The DxfCode.ExtendedDataLayerName enum value (with integer 1003) specifies that the value will be a layer name. Whether the layer has to present or not in the current database may need further exploration.
&#8226; The DxfCode.ExtendedDataBinaryChunk enum value (with integer 1004) specifies that the XData value will be some binary chunk. We will address it further in the future.
&#8226; The DxfCode.ExtendedDataHandle enum value (with integer 1005) specifies that the XData value is supposed to be a valid AutoCAD object handle. If it is not a good object handle or the object it references to has been deleted, the Audio command will report an error and the Fix option will set it as NULL or empty.
&#8226; The DxfCode.ExtendedDataXCoordinate enum value (with integer 1010) and the DxfCode.ExtendedDataWorldXCoordinate (with integer 1011) specify that the XData value will be a 3D point.
&#8226; When the two enum values (1010 or 1011) are specified as the XData type, their value objects should be of type Point3d.
&#8226; The DxfCode.ExtendedDataYCoordinate (1020) and the DxfCode.ExtendedDataZCoordinate (1030) enum values are there for other purposes. They should not be used in the TypedValue constructors. Otherwise, exceptions would just occur.
&#8226; The same apply to the ExtendedDataWorldYCoordinate (1021) and the ExtendedDataWorldYCoordinate (1031) enum values.
&#8226; Though the DxfCode.ExtendedDataWorldXDisp (1012) and the DxfCode.ExtendedDataWorldXDir (1013) indicate that the XData value should be a displacement, direction, or a vector, the TypedValue constructor does not accept a Vector3d object! They still only accept the type of Point3d!
&#8226; Once again, the DxfCode.ExtendedDataWorldYDisp(1022)/DxfCode.ExtendedDataWorldZDisp(1032) and DxfCode.ExtendedDataWorldYDir(1023)/DxfCode.ExtendedDataWorldZDir(1033) are there for other purposes. They should not be used in the TypedValue constructors. Otherwise, exceptions would just occur.
&#8226; The DxfCode.ExtendedDataControlString indicates that the XData value can be either "{" or “}” and the two symbols must be balanced in the whole XData group. They can be nested.
&#8226; The DxfCode.ExtendedDataReal (1040), DxfCode.ExtendedDataDist(1041), DxfCode.ExtendedDataScale, (1042), DxfCode.ExtendedDataInteger16 (1070) and DxfCode.ExtendedDataInteger32 (1071) are straightforward as their names suggest.   
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides project wizards in C#, VB.NET and CLI/Managed C++, and various item wizards such as Event Handlers, Command/LispFunction Definers, and Entity/Draw Jiggers in both C# and VB.NET, to help program AutoCAD addins.



 楼主| 发表于 2024-9-6 12:11:02 | 显示全部楼层
本帖最后由 qq1254582201 于 2024-9-6 15:12 编辑

AutoCAD .NET XData: Add New XData to Entity/Object
AutoCAD has supported the eXtended Data for long time, back to the ADS era. In the AutoCAD .NET world, those functionalities regarding the XData manipulations and even those extended DXF codes are wrapped nicely into some classes, structs, methods and enums.
However, because of the different syntaxes in the new AutoCAD .NET and the old ADS, even for people coming from the ADS time and using those old ResultBuffer a lot, they may still be confused about some classes, methods, and enum values as far as XData and ResultBuffer are concerned.
From this post on, let’s look at some aspects about using XData in AutoCAD .NET. Particularly, in this post, let’s add various XData types to a single picked AutoCAD entity. Here is the code and command.

  1. [CommandMethod("AddXData")]
  2. public static void AddXData_Method()
  3. {
  4.     const string TestAppName = "XDataAppName1";
  5.     Database db = HostApplicationServices.WorkingDatabase;
  6.     Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  7.     try
  8.     {
  9.         PromptEntityResult prEntRes = ed.GetEntity("Select an Entity to attach XDATA");
  10.         if (prEntRes.Status == PromptStatus.OK)
  11.         {
  12.             using (Transaction tr = db.TransactionManager.StartTransaction())
  13.             {
  14.                 RegAppTable regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
  15.                 if (!regAppTable.Has(TestAppName))
  16.                 {
  17.                     using (RegAppTableRecord regAppRecord = new RegAppTableRecord())
  18.                     {
  19.                         regAppRecord.Name = TestAppName;
  20.                         regAppTable.UpgradeOpen();
  21.                         regAppTable.Add(regAppRecord);
  22.                         regAppTable.DowngradeOpen();
  23.                         tr.AddNewlyCreatedDBObject(regAppRecord, true);
  24.                     }
  25.                 }
  26.                 Entity ent = (Entity)tr.GetObject(prEntRes.ObjectId, OpenMode.ForWrite);
  27.                 ent.XData = new ResultBuffer
  28.                             (
  29.                                 new TypedValue((int)DxfCode.ExtendedDataRegAppName, TestAppName),   //1001
  30.                                 new TypedValue((int)DxfCode.ExtendedDataAsciiString, "String1"),    //1000
  31.                                 new TypedValue((int)DxfCode.ExtendedDataLayerName, "0"),            //1003
  32.                                 new TypedValue((int)DxfCode.ExtendedDataBinaryChunk, Encoding.ASCII.GetBytes("BinaryChunk")), //1004
  33.                                 new TypedValue((int)DxfCode.ExtendedDataHandle, ent.Handle),        //1005
  34.                                 new TypedValue((int)DxfCode.ExtendedDataXCoordinate, new Point3d(1.1, 2.1, 3.1)), //1010
  35.                                 //new TypedValue((int)DxfCode.ExtendedDataYCoordinate, 2.1),          //1020
  36.                                 //new TypedValue((int)DxfCode.ExtendedDataZCoordinate, 3.1),          //1030
  37.                                 new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, new Point3d(1.2, 2.2, 3.2)), //1011
  38.                                 //new TypedValue((int)DxfCode.ExtendedDataWorldYCoordinate, 2.2),   //1021
  39.                                 //new TypedValue((int)DxfCode.ExtendedDataWorldZCoordinate, 3.2),   //1031
  40.                                 new TypedValue((int)DxfCode.ExtendedDataWorldXDisp, new Point3d(1.3, 2.3, 3.3)), //1012
  41.                                 //new TypedValue((int)DxfCode.ExtendedDataWorldYDisp, 2.3),           //1022
  42.                                 //new TypedValue((int)DxfCode.ExtendedDataWorldZDisp, 3.3),           //1032
  43.                                 new TypedValue((int)DxfCode.ExtendedDataWorldXDir, new Point3d(1.4, 2.4, 3.4)), //1013
  44.                                 //new TypedValue((int)DxfCode.ExtendedDataWorldYDir, 2.4),            //1023
  45.                                 //new TypedValue((int)DxfCode.ExtendedDataWorldZDir, 3.4),            //1033
  46.                                 new TypedValue((int)DxfCode.ExtendedDataControlString, "{"),        //1002
  47.                                 new TypedValue((int)DxfCode.ExtendedDataReal, 12345.6789),          //1040
  48.                                 new TypedValue((int)DxfCode.ExtendedDataDist, 25.25),               //1041
  49.                                 new TypedValue((int)DxfCode.ExtendedDataScale, 0.2),                //1042
  50.                                 new TypedValue((int)DxfCode.ExtendedDataControlString, "}"),        //1002
  51.                                 new TypedValue((int)DxfCode.ExtendedDataInteger16, 16),             //1070
  52.                                 new TypedValue((int)DxfCode.ExtendedDataInteger32, 32)              //1071
  53.                             );
  54.                 tr.Commit();
  55.             }
  56.         }
  57.     }
  58.     catch (System.Exception ex)
  59.     {
  60.         ed.WriteMessage(ex.ToString());
  61.     }
  62. }



After the command is run and an entity is selected in AutoCAD, the various XData will be added to the entity successfully. If the ArxDbg tool has been loaded, we can use it to check the XData on the entity.
Here is what the ArxDbgSnoopEnts will tell us about the XData of the entity.

The code seems simple and straightforward, but there are quite some tips and tricks there.
&#8226; The XData has to be started with the 1001 (DxfCode.ExtendedDataRegAppName) code.
&#8226; The XData Application Name has to be registered beforehand.
&#8226; The XData Application Name can be registered through creating a RegAppTableRecord and adding it to the RegAppTable (another kind of AutoCAD symbol table).
&#8226; The RegAppTable had better be opened for READ first to check the existence of the RegAppTableRecord.
&#8226; If the RegAppTableRecord does not exist in the RegAppTable, it can be upgraded to WRITE through the UpgradeOpen() call.
&#8226; The UpgradeOpen() had better be balanced with the DowngradeOpen() call though not necessary if the object/entity is closed right after the modification.
&#8226; The Entity.XData property can be used to retrieve all the XData associated with the entity if any or to set some XData to it.
&#8226; The XData property is inherited from the DBObject actually indicating that all AutoCAD database resident objects having graphics or not such as layers and line types all can have XData.
&#8226; The ResultBuffer is a list of TypedValue which is a pair of type and value.
&#8226; The first element of the ResultBuffer has to be the registered XData application name with the integer 1001 or the enum value DxfCode.ExtendedDataRegAppName.
&#8226; The DxfCode.ExtendedDataLayerName enum value (with integer 1003) specifies that the value will be a layer name. Whether the layer has to present or not in the current database may need further exploration.
&#8226; The DxfCode.ExtendedDataBinaryChunk enum value (with integer 1004) specifies that the XData value will be some binary chunk. We will address it further in the future.
&#8226; The DxfCode.ExtendedDataHandle enum value (with integer 1005) specifies that the XData value is supposed to be a valid AutoCAD object handle. If it is not a good object handle or the object it references to has been deleted, the Audio command will report an error and the Fix option will set it as NULL or empty.
&#8226; The DxfCode.ExtendedDataXCoordinate enum value (with integer 1010) and the DxfCode.ExtendedDataWorldXCoordinate (with integer 1011) specify that the XData value will be a 3D point.
&#8226; When the two enum values (1010 or 1011) are specified as the XData type, their value objects should be of type Point3d.
&#8226; The DxfCode.ExtendedDataYCoordinate (1020) and the DxfCode.ExtendedDataZCoordinate (1030) enum values are there for other purposes. They should not be used in the TypedValue constructors. Otherwise, exceptions would just occur.
&#8226; The same apply to the ExtendedDataWorldYCoordinate (1021) and the ExtendedDataWorldYCoordinate (1031) enum values.
&#8226; Though the DxfCode.ExtendedDataWorldXDisp (1012) and the DxfCode.ExtendedDataWorldXDir (1013) indicate that the XData value should be a displacement, direction, or a vector, the TypedValue constructor does not accept a Vector3d object! They still only accept the type of Point3d!
&#8226; Once again, the DxfCode.ExtendedDataWorldYDisp(1022)/DxfCode.ExtendedDataWorldZDisp(1032) and DxfCode.ExtendedDataWorldYDir(1023)/DxfCode.ExtendedDataWorldZDir(1033) are there for other purposes. They should not be used in the TypedValue constructors. Otherwise, exceptions would just occur.
&#8226; The DxfCode.ExtendedDataControlString indicates that the XData value can be either "{" or “}” and the two symbols must be balanced in the whole XData group. They can be nested.
&#8226; The DxfCode.ExtendedDataReal (1040), DxfCode.ExtendedDataDist(1041), DxfCode.ExtendedDataScale, (1042), DxfCode.ExtendedDataInteger16 (1070) and DxfCode.ExtendedDataInteger32 (1071) are straightforward as their names suggest.            
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard)provides project wizards in C#, VB.NET and CLI/Managed C++, and various item wizards such as Event Handlers, Command/LispFunction Definers, and Entity/Draw Jiggers in both C# and VB.NET, to help program AutoCAD addins.



您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-22 20:23 , Processed in 0.186384 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表