结果缓存——ResultBuffer

  结果缓存即 Autodesk.AutoCAD.DatabaseServices.ResultBuffer 类型,使用 ResultBuffer 对象时需要提供一个数据对,每个数据对包含一个数据类型描述和一个值,这些数据对是 Autodesk.AutoCAD.DatabaseServices.TypedValue 类的实例。

  TypedValue.TypeCode 属性是一个16位整型数据,它指明 TypedValue.Value 属性的数据类型,可接受的 TypeCode 值取决于 ResultBuffer 实例的使用范围,例如,适用于扩展记录定义的 TypeCode 值就不适合于 XData。而Autodesk.AutoCAD.DatabaseServices.DxfCode 枚举类型定义的码值则描述了 ResultBuffer 可能的数据类型。

  TypedValue.Value 属性是一个 System.Object 的实例,它可以包含任何类型的数据;但是,Value 的数据必须符合由 TypeCode 指明的类型。

  创建 ResultBuffer 方法有两种:

  一种是使用构造函数创建,即在声明 ResultBuffer 时将一个 TypedValue 作用参数传给 ResultBuffer:

ResultBuffer  resBuf = new ResultBuffer(new TypedValue((int)DxfCode.Text, "我的扩展数据"));

  另一种是使用 ResultBuffer.Add() 方法来添加 TypedValue,可以添加多个TypedValue,但总数据大小不能超过128K:

ResultBuffer resBuf = new ResultBuffer ();
resBuf.Add(new TypedValue ((int)DxfCode.Text, "我的扩展数据"));
resBuf.Add(new TypedValue ((int)DxfCode.Real, 20.0));
resBuf.Add(new TypedValue((int)DxfCode.Int32, ));

扩展数据——XData

  AutoCAD 数据库对象都可以灵活的添加一定数量的自定义数据,供开发者使用,这些数据的含义由开发者自行解释,AutoCAD 只维护这些数据而不管其具体的含义,这些数据被称为扩展数据(XData),扩展数据以结果缓存形式附加在实体上,因此,能够有效的利用存储空间,对于添加轻量的数据非常方便的。

  可以通过实体 DBObject 类及其派生类的 XData 属性获取或设置扩展数据。实体的扩展数据由应用程序创建, 附着在实体的扩展数据可以包含一个或多个组。每一组均以一个互不相同的注册应用程序名开头,扩展数据 XData 所支持的TypedValue.TypeCode 属性值(DXF 组码)只能采用 1000~1071 之间的组码值,不同组码对应不同类型的信息,各个组码的说明如下表所示:

DXF 组码值  扩展数据内容
1000~1009

字符串 (最多不超过 255 个字
符)

1001  Xdata 的应用程序名
1002  Xdata 的控制字符串
1003 图层名
1004 二进制数据
1005 数据库对象句柄
1010~1059  浮点数
1010,1020,1030  三维点(x, y , z)
1011,1021,1031  三维空间位置
1012,1022,1032  三维空间距离
1013,1023,1033  三维空间方向
1040  Xdata 中的浮点数
1041  Xdata 中的距离值
1042 Xdata 中的比例系数
1060~1070  16 位整数
1071  32 位整数

  由于每个数据库对象可以附加多个应用程序的数据,所以在 ResultBuffer 中,应用程序名是每段扩展数据的第一个数据,其后的结果缓冲数据都归此应用程序名所有。(也可以使用其他的特殊标识作为第一个数据,总之目的是为了便于区分,方便后期查询此扩展数据)

  AutoCAD 将注册的应用程序名称保存于数据库中的 RegAppTable 表中,在使用之前,必须首先检测是否已经存在 RegAppTable 表中,如果没有则需要注册,也就是创建一个 RegAppTableRecord 表记录, 注册程序的名字最长可达 31 个字符,以下代码完成 RegAppTableRecord 表记录的创建:

RegAppTable appTbl = trans.GetObject(db.RegAppTableId, OpenMode.ForWrite) as RegAppTable ;
if (!appTbl.Has("MyAppName"))
{
  RegAppTableRecord appTblRcd = new RegAppTableRecord();
  appTblRcd.Name ="MyAppName";
  appTbl.Add(appTblRcd);
  trans.AddNewlyCreatedDBObject(appTblRcd, true);
}

  

  添加扩展数据到数据库对象上,首先需要获取数据注册应用程序名,然后通过 DBObject 类及其派生类的 XData 属性设置扩展数据,如以下代码所示:

public void AddXData()
{
  Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  ed.WriteMessage("添加扩充数据 XDATA\n");
  PromptEntityOptions entOps = new PromptEntityOptions("选择实体对象");
  PromptEntityResult entRes;
  entRes = ed.GetEntity(entOps);
  if (entRes.Status != PromptStatus.OK)
  {
    ed.WriteMessage("选择对象失败,退出");
    return;
  }
  ObjectId objId = entRes.ObjectId;
  Database db = HostApplicationServices.WorkingDatabase;
  using (Transaction trans = db.TransactionManager.StartTransaction())
  {
    Entity ent = trans.GetObject(objId, OpenMode.ForWrite) as Entity ;
    ent.ColorIndex =;
    RegAppTable appTbl = trans.GetObject(db.RegAppTableId, OpenMode.ForWrite) as RegAppTable ;
    if (!appTbl.Has("MyAppName"))
    {
      RegAppTableRecord appTblRcd = new
      RegAppTableRecord();
      appTblRcd.Name ="MyAppName";
      appTbl.Add(appTblRcd);
      trans.AddNewlyCreatedDBObject(appTblRcd, true);
    }
    ResultBuffer resBuf = new ResultBuffer();
    resBuf.Add(new TypedValue(, "我的扩展数据应用程序"));
    resBuf.Add(new TypedValue(, "作者:王"));
    ent.XData = resBuf;
    trans.Commit();
  }
}

  从指定的对象返回所附着的扩展数据也需要通过 DBObject 类及其派生类的XData 属性,返回的结果为 ResultBuffer,可以用.AsArray()方法将其转换为一个TypedValue[]数组,或者借助遍历器 IEnumerator(在 System.Collections 命名空间中),同时根据 DXF 的组码值判断所添加的数据,这些数据的含义由开发者自行解释。

  使用自带方法转为数组:

TypedValue[] tvs = rb.AsArray();

  使用IEnumerator遍历:

public void GETXDATA()
{
  Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  ed.WriteMessage("获取扩充数据 XDATA\n");
  PromptEntityOptions entOps = new PromptEntityOptions("选择实体对象");
  PromptEntityResult entRes = ed.GetEntity(pr);
  if (entRes.Status != PromptStatus.OK)
  {
    ed.WriteMessage("选择对象失败,退出");
    return;
  }
  Database db = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database;
  using (Transaction tr = db.TransactionManager.StartTransaction())
  {
    Entity ent = (Entity)tr.GetObject(res.ObjectId, OpenMode.ForRead);
    ResultBuffer resBuf = ent.XData;
    if (resBuf ! = null)
    {
      IEnumerator iter = resBuf.GetEnumerator();
      while (iter.MoveNext())
      {
        TypedValue tmpVal = (TypedValue)iter.Current;
        ed.WriteMessage(tmpVal.TypeCode.ToString() + ":");
        ed.WriteMessage(tmpVal.Value.ToString() +"\n");
      }
    }
  }
}

  也可以将扩展数据读取到更常用的List<T>中,参考代码如下:

public List<System.Object> GetXDataList(Entity ent)
{
  Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
  List<System.Object> objs = new List<System.Object>();
  Database db = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database;
  using (Transaction trans = db.TransactionManager.StartTransaction())
  {
    ent = (Entity)trans.GetObject(ent.ObjectId, OpenMode.ForRead);
    ResultBuffer resBuf = ent.XData;
    if (resBuf != null)
    {
      System.Collections.IEnumerator itor = resBuf.GetEnumerator();
      while (itor.MoveNext())
      {
        TypedValue tmpVal = (TypedValue)itor.Current;
        objs.Add(tmpVal.Value);
}
    }
    trans.Commit();
  }
  return objs;
}

  要注意的是,XData是比较特殊的,给实体添加扩展数据,是这样的:

ResultBuffer rb = new ResultBuffer(
  new TypedValue[]{
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"abc"),
new TypedValue((int)DxfCode.ExtendedDataAsciiString,"")
});
line.XData = rb;

  但是这里虽然是用等号赋值的,但是它并不一定会覆盖旧的扩展数据,一个实体,只有一个XData属性,但是里面可以记录多个不同应用程序名的扩展数据。

  每次用“=”给实体的XData赋值时,如果XData里还没有这个应用程序的扩展数据,那么新赋的这些值,会被添加到原有的XData结尾去,比如上面已经给line对象添加了应用程序“abc”的扩展数据,这个时候读取line的XData,其内容应该是这样的:

new TypedValue[]{
new TypedValue((int)DxfCode.ExtendedDataRegAppName,"abc"),
new TypedValue((int)DxfCode.ExtendedDataAsciiString,"")
}

  这时候,再给line添加一个新的应用程序"lc"的扩展数据:

ResultBuffer rb1 = new ResultBuffer(
new TypedValue[]{
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"lc"),
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,"")
});
line.XData = rb1;

  此时,如果再读取line的XData,那么结果就会是:

new TypedValue[]{
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"abc"),
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,""),
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"lc"),
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,"")
}

  这样的话,那如果同一个实体如果有多个应用程序的扩展数据,那我怎么取其中某一个应用程序的扩展数据呢?

  答案是使用:GetXDataForApplication方法,该方法的参数就是应用程序名,比如:

ResultBuffer res = line.GetXDataForApplication("abc");

这样取到的结果就是:
new TypedValue[]{
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"abc"),
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,"")
}

  如果要修改扩展数据,只需要对XData重新赋值就行,比如现在我们修改应用程序abc的扩展数据:

line.XData = new ResultBuffer(
new TypedValue[]{
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"abc"),
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,""),
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,"")
}); //对XData重新赋值时,如果XData里已经有了abc的扩展数据,那么会把原有的abc的扩展数据替换掉,如果现在还没有abc的扩展数据,那么就会在XData结尾处添加上新的扩展数据。

  如果要删除扩展数据,操作方式如下:

//删除应用程序abc的扩展数据,只需要进行一个这样的赋值,新值里只添加一个应用程序名,不添加其他值,这样XData中,原有的abc的扩展数据就会被删除
line.XData = new ResultBuffer(
  new TypedValue[]{
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"abc")
});

  注意:尽量不要直接删除已经在RegAppTable里注册的应用程序名,如果图纸上的实体上添加了此应用程序的扩展数据,那么扩展数据中对应的应用程序名会被删掉,但它下面对应的其他数据值并不会被删除,有可能会引发问题,例如:

//删除应用程序abc在RegAppTable里的记录
RegAppTable rat = (RegAppTable)trans.GetObject(db.RegAppTableId, OpenMode.ForWrite);
if (!rat.Has("abc"))
{
  RegAppTableRecord ratr = (RegAppTableRecord)rat["abc"].GetObject(OpenMode.ForWrite);
  ratr.Erase();
} //这时,读取line的XData,其内容会是这样(假设我们上一步,没有删除line中abc的扩展数据)
new TypedValue[]{
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,""),
  new TypedValue((int)DxfCode.ExtendedDataRegAppName,"lc"),
  new TypedValue((int)DxfCode.ExtendedDataAsciiString,"")
}

  所以,个人认为,在删除RegAppTable中的已注册的应用程序名时,应先用过滤选择器选择出添加了此应用程序扩展数据的实体,然后将它们的扩展数据删除,然后再去删除RegAppTable中的应用程序注册信息。

AutoCAD.NET二次开发:扩展数据之XData的更多相关文章

  1. Java学习-039-源码 jar 包的二次开发扩展实例(源码修改)

    最近在使用已有的一些 jar 包时,发现有些 jar 包中的一些方法无法满足自己的一些需求,例如返回固定的格式,字符串处理等等,因而需要对原有 jar 文件中对应的 class 文件进行二次开发扩展, ...

  2. TFS二次开发的数据统计以PBI、Bug、Sprint等为例(一)

    TFS二次开发的数据统计以PBI.Bug.Sprint等为例(一) 在TFS二次开发中,我们可能会根据某一些情况对各个项目的PBI.BUG等工作项进行统计.在本文中将大略讲解如果进行这些数据统计. 一 ...

  3. 利用C#进行AUTOCAD的二次开发

    众所周知,对AutoCAD进行二次开发用到的主要工具有:ObjectArx,VBA,VLisp.但它们的优缺点是显而易见的:ObjectArx功能强大,编程效率高,但它的缺点是编程者必须掌握VC++, ...

  4. TFS二次开发系列:七、TFS二次开发的数据统计以PBI、Bug、Sprint等为例(一)

    在TFS二次开发中,我们可能会根据某一些情况对各个项目的PBI.BUG等工作项进行统计.在本文中将大略讲解如果进行这些数据统计. 一:连接TFS服务器,并且得到之后需要使用到的类方法. /// < ...

  5. AutoCAD .NET二次开发(四)

    在CAD中,属性信息一般是以注记的形式存在,但当属性数据内容较多时,显示就成了问题.扩展属性(Xdata)可以解决这一问题,比如南方Cass中就利用了这一点.我们经常用Lisp来读取操作扩展属性. 查 ...

  6. C# 超级狗 二次开发 读写数据 激活验证 存储数据库连接字符串

    本文主要讲解如果使用C#语言来对超级狗进行二次开发,如果仅仅是做个激活的功能,可以参照另一篇博客,地址:http://www.cnblogs.com/dathlin/p/8487842.html 如果 ...

  7. AutoCAD .NET二次开发(一)

    其他话不多说,直接进入主题,既然是二次开发,当然是用CAD平台已经封装好了很多类,我们需要熟悉和使用它们.常用的AutoCAD .NET API的四个主要DLL文件是: 名称 作用 备注 AcDbMg ...

  8. Revit二开---Schemachema扩展数据

    一.什么是Schema        Schema是Revit扩展数据的技术关键词,revit到这里,需要对Revit二开基础有一定了解. 二.Schema架构        建立revit扩展数据第 ...

  9. AutoCAD.NET二次开发:创建自定义菜单(AcCui)

    从CAD2007之后,Autodesk提供了一个新的程序集AcCui.dll,使用这个程序集,我们可以方便地做一些界面方面的操作,比如创建自定义菜单. 下面介绍一下菜单的创建过程: 1.在项目中添加引 ...

随机推荐

  1. ConcurrentDictionary和Dictionary

    http://stackoverflow.com/questions/6739193/is-the-concurrentdictionary-thread-safe-to-the-point-that ...

  2. C++中变量自动初始化的问题

    C++中有一些变量在如果没有赋初值会被编译器自动赋值为0,但有的变量又不会这样,而得到一个随机数,下面具体讨论一下: 首先看一下C++中的几个存储区:1.栈区:由编译器自动分配释放 ,存放函数的参数值 ...

  3. oracle索引,索引的建立、修改、删除

    索引,索引的建立.修改.删除 2007-10-05 13:29 来源: 作者: 网友评论 0 条 浏览次数 2986 索引索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和 ...

  4. Codeforces 4538 (状态压缩dp)Little Pony and Harmony Chest

    Little Pony and Harmony Chest 经典状态压缩dp #include <cstdio> #include <cstring> #include < ...

  5. public,protected,friendly,private的访问权限

    请说出作用域public,private,protected,以及不写时的区别 这四个作用域的可见范围如下表所示. 说明:如果在修饰的元素上面没有写任何访问修饰符,则表示friendly. 作用域   ...

  6. Linux find xargs rm .orig

    /********************************************************************* * Linux find xargs rm .orig * ...

  7. LeetCode Single Number II 单元素2

    题意:给一个序列,其中只有1个元素只出现1次,其他的都一定出现3次.问这个出现一次的元素是多少? 思路: (1)全部元素拆成二进制,那么每个位上的1的个数应该是3的倍数,如果不是3的倍数,则ans的这 ...

  8. Android Dialog使用举例

    在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,在我们使用Android的过程中,我归纳了一 ...

  9. 数据库语言(一):SQL语法实例整理

    数据库系统以一些语句作为输入,并返回一些输出,例如sql查询总是返回一张表,我们定义:具有相同格式的记录的集合是一张表. 考虑大学数据库系统: SQL中的数据类型: char(n) 字符串长度为n   ...

  10. <三>面向对象分析之UML核心元素之参与者

    一:版型        --->在UML里有一个概念叫版型.有些书里也称类型,构造型.        --->这个概念是对一个UML元素基础定义的扩展.在同一个元素基础定义的基础上赋予特别 ...