AutoCAD中的扩展字典及扩展记录(C#)
在学习CAD扩展记录的过程中,遇到了一些问题,也积累了一些经验,现在给大家分享一些我的学习心得。在学习扩展字典之前需要读者了解cad的组码,也就是DxfCode。感兴趣的也可以了解一下扩展数据的相关内容(后面有时间也会分享一下,因为扩展数据、扩展字典和DxfCode组码之间有密切的关系)。
一个CAD对象只能拥有一个扩展字典,而扩展字典下面可以包含多个扩展记录。打个比方,可以这么理解,如果扩展字典相当于excel文件,那么一个扩展记录就相当于excel中的一个表单sheet对象,扩展记录中存储的数据就相当于表单sheet中的数据。
使用扩展记录可以向对象中保存一些属性数据,以便后续提取之用,这是很有用的。比如说可以向一个多段线(代表一根管线,或是其他)中存储一些施工方面的数据信息,例如施工标段、桩号范围、施工完成时间等,以后再打开图的时候,就知道这段管线是哪个施工单位施工的,什么时间完成的等等,便于查看和统计。CAD程序自身的属性对话框是无法记录这些信息的。
向对象添加扩展记录一般分为三个步骤:
1 将添加的数据构成一个类
2 编写扩展方法,包括扩展记录的添加、读取、删除、修改
3 调用扩展方法进行操作
界面如下:

下面列出主要的代码
1 将需要添加的数据构成一个类,主要包括施工标段、信息、桩号、完成时间等属性
public class XDataClass
{
public string BiaoDuan { get; set; }//施工标段
public string Information { get; set; }//附加到对象上的信息
public double StationStart { get; set; }//起始桩号
public double StationEnd { get; set; }//终止桩号
public double Length { get; private set; }//长度
public DateTime OverTime { get; set; }//完成时间
public string XRecordName { get; set; } //扩展记录名称
public XDataClass() { }
public XDataClass(string xrecordName)
{
XRecordName = xrecordName;
}
/// <summary>
/// 将扩展数据实体类转化成typevaluelist类型
/// </summary>
/// <param name="xdataClass"></param>
/// <returns></returns>
public static TypedValueList ClassToTypeValueList(XDataClass xdataClass)
{
TypedValueList tvList = new TypedValueList
{
{DxfCode.Text, xdataClass.BiaoDuan },
{DxfCode.Text, xdataClass.Information },
{DxfCode .Real ,xdataClass.StationStart },
{DxfCode.Real ,xdataClass .StationEnd },
{DxfCode.Text ,xdataClass .OverTime .ToString ("d") },
{DxfCode.Text ,xdataClass.XRecordName },
};
return tvList;
}
/// <summary>
/// 将typevaluelist类型的数据转换成实体类
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public static XDataClass TypeValueListToClass(TypedValueList list)
{
XDataClass xdataClass = new XDataClass()
{
BiaoDuan = list[].Value.ToString(),
Information = list[].Value.ToString(),
StationStart = Convert.ToDouble(list[].Value),
StationEnd = Convert.ToDouble(list[].Value),
OverTime = Convert.ToDateTime(list[].Value),
XRecordName = list[].Value.ToString(),
Length = Math.Abs(Convert.ToDouble(list[].Value) - Convert.ToDouble(list[].Value))
};
return xdataClass;
}
}
2 编写扩展方法,包括扩展记录的添加、读取、删除、修改
#region 对象的扩展记录的添加、删除、修改
/// <summary>
/// 添加扩展记录,如果没有扩展字典,那就创建扩展字典
/// </summary>
/// <param name="objId">对象的objectid</param>
/// <param name="xRecordSearchKey">扩展记录名称</param>
/// <param name="values">扩展记录的内容</param>
/// <returns></returns>
public static bool AddXRecordToObj(this ObjectId objId, string xRecordSearchKey, TypedValueList values)
{
//添加扩展记录之前,先创建对象的扩展字典
DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开
if (obj.ExtensionDictionary.IsNull)//如果对象无扩展字典,那就给创建
{
obj.UpgradeOpen();//切换对象为写的状态
obj.CreateExtensionDictionary();//为对象创建扩展字典,一个对象只能拥有一个扩展字典
obj.DowngradeOpen();//将对象切换为读的状态
}
//打开对象的扩展字典
DBDictionary dict = obj.ExtensionDictionary.GetObject(OpenMode.ForRead) as DBDictionary;
//如果扩展字典中已包含指定的扩展记录对象
if (dict.Contains(xRecordSearchKey))
{
return false;//如果包含有指定的扩展记录,那就退出
}
else //若没有包含扩展记录,则创建一个
{
Xrecord xrec = new Xrecord();//为对象创建一个扩展记录
xrec.Data = values;//指定扩展记录的内容,这里用到了自定义类型转换,TypedValueList-->ResultBuffer
dict.UpgradeOpen();//将扩展字典切换为写的状态,以便添加一个扩展记录
ObjectId xrecId = dict.SetAt(xRecordSearchKey, xrec);//在扩展字典中加入新建的扩展记录,并指定它的搜索关键字
objId.Database.TransactionManager.AddNewlyCreatedDBObject(xrec, true);
dict.DowngradeOpen();//将扩展字典切换为读的状态
return true;
}
} /// <summary>
/// 用于替换扩展字典中的整个一条扩展记录
/// </summary>
/// <param name="objId">对象id</param>
/// <param name="xRecordSearchKey">扩展记录的名称</param>
/// <param name="values">扩展记录的内容</param>
public static bool ModObjXrecord(this ObjectId objId, string xRecordSearchKey, TypedValueList values)
{
DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典id
if (dictId.IsNull)
{
return false;//若对象没有扩展字典,则返回
}
//如果对象有扩展字典,则以读的方式打开
DBDictionary dict = dictId.GetObject(OpenMode.ForRead) as DBDictionary;
if (!dict.Contains(xRecordSearchKey))
{
return false;//如果扩展字典中没有包含指定关键字的扩展记录,则返回 ;
}
ObjectId xrecordId = dict.GetAt(xRecordSearchKey);//获取扩展记录的id
Xrecord xrecord = xrecordId.GetObject(OpenMode.ForWrite) as Xrecord;
xrecord.Data = values;//覆盖原来的数据,因为values有了新的指向
xrecord.DowngradeOpen();//将扩展记录切换为读的状态
return true;
} /// <summary>
/// 获取对象的扩展字典中的扩展记录
/// </summary>
/// <param name="objId">对象的id</param>
/// <param name="xRecordSearchKey">扩展记录名称</param>
/// <returns></returns>
public static TypedValueList GetObjXrecord(this ObjectId objId, string xRecordSearchKey)
{
DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典的id
if (dictId.IsNull)
{
//MessageBox.Show("没有扩展字典");
return null;//若对象没有扩展字典,则返回null
}
DBDictionary dict = dictId.GetObject(OpenMode.ForRead) as DBDictionary;//获取对象的扩展字典
if (!dict.Contains(xRecordSearchKey))
{
return null;//如果扩展字典中没有包含指定关键字的扩展记录,则返回null;
}
//先要获取对象的扩展字典或图形中的有名对象字典,然后才能在字典中获取要查询的扩展记录
ObjectId xrecordId = dict.GetAt(xRecordSearchKey);//获取扩展记录对象的id
Xrecord xrecord = xrecordId.GetObject(OpenMode.ForRead) as Xrecord;//根据id获取扩展记录对象
TypedValueList values = xrecord.Data;
return values;//values 数组应该是有先后顺序的
} /// <summary>
///用于删除对象扩展字典中的指定的扩展记录
/// </summary>
/// <param name="objId">对象id</param>
/// <param name="xRecordSearchKey"> 扩展记录名称</param>
public static bool DelObjXrecord(this ObjectId objId, string xRecordSearchKey)
{
DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典id
if (dictId.IsNull)
{
return false;//若对象没有扩展字典,则返回
}
//如果对象有扩展字典,则以读的方式打开
DBDictionary dict = dictId.GetObject(OpenMode.ForRead) as DBDictionary;
if (dict.Contains(xRecordSearchKey))//如果扩展字典中包含指定关键字的扩展记录,则删除;
{
dict.UpgradeOpen();//切换为写的状态
dict.Remove(xRecordSearchKey);//删除扩展记录
dict.DowngradeOpen();//切换为读的状态
}
return true;
} /// <summary>
/// 删除对象的扩展字典下的所有的扩展记录
/// 2018年4月7日09:44:12
/// </summary>
/// <param name="objId"></param>
public static bool DelObjAllXrecords(this ObjectId objId)
{
DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典id
if (dictId.IsNull)
{
return false;//若对象没有扩展字典,则返回
}
//如果对象有扩展字典,则以读的方式打开
DBDictionary dict = dictId.GetObject(OpenMode.ForWrite) as DBDictionary;
//获取扩展字典下的所有扩展记录名称集合 Keys
List<string> listKeys = new List<string>();
foreach (var item in dict)//获取扩展字典中的所有条目,也就是所有的扩展记录的key
{
listKeys.Add(item.Key);
}
foreach (var key in listKeys)//根据key,删除扩展字典中的每一个条目(也就是扩展记录)
{
dict.Remove(key);
}
dict.DowngradeOpen();//切换为读的状态
return true;
} /// <summary>
/// 删除对象的扩展字典,因为每个对象只能拥有一个扩展字典,所以给定对象的objectID就好了
/// 2018年4月7日09:17:44
/// </summary>
/// <param name="objId"></param>
public static bool DeleteObjExtensionDictionary(this ObjectId objId)
{
DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典的ID
if (dictId.IsNull)
{
return false; //没有扩展字典
}
//有扩展字典 obj.UpgradeOpen();//切换对象为写的状态
162 objId.DelObjAllXrecords(); //调用上面的方法,在删除扩展字典之前要先删除扩展记录
obj.ReleaseExtensionDictionary();//移除对象的扩展字典,一个对象只能拥有一个扩展字典
obj.DowngradeOpen();//将对象切换为读的状态
return true;
}
#endregion
3调用扩展方法
a 添加扩展记录
//btn 添加扩展记录
XDataClass PipeXdataClass = new XDataClass(Enum_XRcordName.pipe_whlkx.ToString());
ObjectId selectedObjId = ObjectId.Null;
private void btnAddXData_Click(object sender, EventArgs e)
{
if (CheckValue() == false)
{
return;
}
_instance.Hide();
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityResult entityResult = ed.GetEntity("\n请选择一个多段线对象");//单个拾取对象
if (entityResult.Status != PromptStatus.OK)
{
_instance.Show();
return;
}
GetDataFromControls(PipeXdataClass);//私有函数,将控件中的数据填充到实体类中
//获取对象的ID
ObjectId objId = entityResult.ObjectId;
bool result = false;
using (DocumentLock docLock = doc.LockDocument())
using (Transaction trans = db.TransactionManager.StartTransaction())
{
//将xdataCalss类型的数据转换成一个typevalue型的列表
TypedValueList values = XDataClass.ClassToTypeValueList(PipeXdataClass);
result = objId.AddXRecordToObj(PipeXdataClass.XRecordName, values);
trans.Commit();
}
if (result)
{
ed.WriteMessage("\n对象的扩展数据添加成功!");
}
else
{
ed.WriteMessage("\n对象已经有扩展数据");
}
_instance.Show();
}
b 读取扩展记录
//btn 读取扩展记录
private void btnReadXData_Click(object sender, EventArgs e)
{
_instance.Hide();
ClearContent();//清空控件中的内容
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
//开始事务处理
using (DocumentLock docLock = doc.LockDocument())
using (Transaction trans = db.TransactionManager.StartTransaction())
{
PromptEntityResult entityResult = ed.GetEntity("\n请选择一个对象");//拾取单个对象
if (entityResult.Status != PromptStatus.OK)
{
ed.WriteMessage("\n取消了选择");
_instance.Show();
return;
}
//获取对象的ID
ObjectId objId = entityResult.ObjectId;
TypedValueList list = objId.GetObjXrecord(PipeXdataClass.XRecordName);
if (list is null)
{
ed.WriteMessage("\n该对象没有扩展记录");
_instance.Show();
return;
}
if (list.Count <= )
{
ed.WriteMessage("\n有扩展记录,但是记录为空");
_instance.Show();
return;
}
else
{
PipeXdataClass = XDataClass.TypeValueListToClass(list);
SetDataToControls(PipeXdataClass);//向控件中填充数据
ed.WriteMessage("\n对象扩展数据读取成功");
selectedObjId = objId;
}
}
_instance.Show();
}
c 删除扩展记录
//btn 删除
private void btnDeleteXData_Click(object sender, EventArgs e)
{
_instance.Hide();
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
//开始事务处理
using (DocumentLock docLock = doc.LockDocument())
using (Transaction trans = db.TransactionManager.StartTransaction())
{
PromptSelectionResult ss1 = ed.GetSelection();//框选对象
if (ss1.Status != PromptStatus.OK)
{
ed.WriteMessage("\n取消了选择");
_instance.Show();
return;
}
//获取对象的ID
List<ObjectId> listObjIds = ss1.Value.GetObjectIds().ToList();
int count = ;
listObjIds.ForEach(objId =>
{
if (objId.DeleteObjExtensionDictionary())
{
ed.WriteMessage("\n删除成功");
count++;
}
});
//ObjectId objId = entityResult.ObjectId;
//2018年4月7日09:50:35,经验证,必须先删除扩展字典下的所有的扩展记录,才能删除对象的扩展字典
//否则会出现错误:eContainerNotEmpty ,容器不为空
//objId.DelObjAllXrecords();
//objId.DeleteObjExtensionDictionary();
trans.Commit();
ed.WriteMessage("\n操作完成,总共删除{0}个扩展记录", count);
}
_instance.Show();
}
修改扩展记录可以自己写一下,比较简单。
下面给出一张图关于扩展字典和扩展记录的示意图,便于理解之间的关系。

AutoCAD中的扩展字典及扩展记录(C#)的更多相关文章
- 在 Windows Azure 网站中进行纵向扩展和横向扩展
编辑人员注释:本文章由 Windows Azure 网站团队的项目经理 Byron Tardif 撰写. 当您开始一个新的 Web 项目,或者刚刚开始开发一般的网站和应用程序时,您可能希望从小处着手. ...
- Memcache服务器端+Redis服务器端+PHP Memcache扩展+PHP Memcached扩展+PHP Redis扩展+MemAdmin Memcache管理工具+一些概念(更新中)
Memcache和Redis因为操作简单,是我们常用的服务器数据缓存系统,以下文字仅作备忘记录,部份转载至网络. 一.定义 1.Memcache Memcache是一个高性能的分布式的内存对象缓存系统 ...
- 学习PHP中的高精度计时器HRTime扩展
不知道大家还记得在学校的时候体育测试时老师带的秒表吗?当枪声想起时,我们开始跑步,这时秒表启动,当我们跑过终点后,老师会按下按扭记录我们的成绩,这就是一个典型的定时器的应用.今天我们要学习的内容其实就 ...
- 如何去掉drwxr-xr-x@中的@符号Linux文件扩展信息
如何去掉drwxr-xr-x@中的@符号Linux文件扩展信息ls -lart drwxrwxrwx@ 10 rlanffy staff 340B 3 6 2015 files-rwxrwxrwx@ ...
- Shell编程-03-Shell中的特殊变量和扩展变量
目录 特殊变量 变量扩展 特殊变量 在Shell中的特殊变量主要分别两种位置参数变量.状态变量两种. 位置参数变量 Shell中的位置参数变量主要是指$0.$1.$#等,主要用于从命令 ...
- 八、collection系列-----计数器、有序字典、默认字典、可命名元组、双向队列、单向队列一.计数器(对字典的扩展)
一.计数器(对字典的扩展) 有如下一个字典: dic = {'k1':123,'k2':123,'k3':12} 统计12出现的次数,123出现的次数 1.统计出现次数 >>> ...
- PHP中DirectIO直操作文件扩展的使用
关于 PHP 的文件操作,我们也将是通过一系列的文章来进行学习.今天我们先学习的是一个很少人使用过,甚至很多人根本不知道的扩展,它与我们日常的文件操作有些许的不同.不过这些差别并不是我们肉眼所能直观看 ...
- PHP中非常好玩的Calendar扩展学习
为什么说这个 Calendar 扩展很好玩呢?因为你基本用不到它!这个扩展是一套关于日期历法的扩展,但是对于我们来说,它没有农历的相关操作,所以对于我们中国人来说这个扩展并没有什么实际的作用.不过这并 ...
- 理解水平扩展和垂直扩展 (转载 http://yunjiechao-163-com.iteye.com/blog/2126981)
当一个开发人员提升计算机系统负荷时,通常会考虑两种方式垂直扩展和水平扩展.选用哪种策略主要依赖于要解决的问题 以及系统资源的限制.在这篇文章中我们将讲述这两种策略并讨论每种策越的优缺点.如果你已经 ...
随机推荐
- 文件导出也可以这么写【js+blob】
文件导出在软件开发中是个比较常用的功能,基本原理也很简单: 浏览器向后台发送一个Get请求 后台处理程序接收到请求后,经过处理,返回二进制文件流 浏览器接收到二进制文件流后提示下载文件 调用的js方法 ...
- Nancy启用跨站攻击防护(CSRF)
什么是CSRF(跨站攻击) 可能很多人已经对CSRF有所了解,就简单的介绍下: CSRF全程是 Cross-Site Request Forgery .大概意思就是在登录用户不知情的情况下,由一个网站 ...
- createjs绘制扇形的方法
扇形由三段线条组成,两条直线和一条弧线,直线可以用createjs中的lineTo函数画出,弧线用Graphics.arc函数来画. 一.关于createjs中的Graphics.Arc API Gr ...
- 详解apply
先谈this 关于this的指向就不细说了,网上有无数博客以及you don't kown js这类书讲的已经很详细了这里就不炒冷饭了. 举几个简单的例子 function foo() { conso ...
- MySQL多数据源笔记5-ShardingJDBC实战
Sharding-JDBC集分库分表.读写分离.分布式主键.柔性事务和数据治理与一身,提供一站式的解决分布式关系型数据库的解决方案. 从2.x版本开始,Sharding-JDBC正式将包名.Maven ...
- 【Unity与23种设计模式】适配器模式(Adapter)
GoF中定义: "将一个类的接口转换成为客户端期待的类接口.适配器模式让原本接口不兼容的类能一起合作." 适配器模式与装饰模式有一定的相似之处 两者都是在着手解决C#不能多继承的问 ...
- 在 Scale Up 中使用 Health Check - 每天5分钟玩转 Docker 容器技术(145)
对于多副本应用,当执行 Scale Up 操作时,新副本会作为 backend 被添加到 Service 的负责均衡中,与已有副本一起处理客户的请求.考虑到应用启动通常都需要一个准备阶段,比如加载缓存 ...
- 【转载】Perl中的引用
为什么使用引用? 在perl4中,hash表中的value字段只能是scalar,而不能是list,这对于有些情况是很不方便的,比如有下面的数据: Chicago, USAFrankfurt, Ger ...
- BiLstm与CRF实现命名实体标注
众所周知,通过Bilstm已经可以实现分词或命名实体标注了,同样地单独的CRF也可以很好的实现.既然LSTM都已经可以预测了,为啥要搞一个LSTM+CRF的hybrid model? 因为单独LSTM ...
- linux-2.6.18源码分析笔记---信号
一.相关数据结构及其位置(大致浏览即可,介绍流程时再来仔细看) 1.1 进程描述符struct task_struct所在目录:include\linux\sched.h 关注task_struct中 ...