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)
当一个开发人员提升计算机系统负荷时,通常会考虑两种方式垂直扩展和水平扩展.选用哪种策略主要依赖于要解决的问题 以及系统资源的限制.在这篇文章中我们将讲述这两种策略并讨论每种策越的优缺点.如果你已经 ...
随机推荐
- error:java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
问题:mysql中id存的是int(10),java代码中的id为long,转不过去 解决:mysql中的int要是需要转到java中的long,需要选择unsigned这个选项,即if(unsign ...
- windows下的react-native 开发环境搭建
本教程用安卓手机作为演示. 首先安装jdk.本教程基于jdk1.8,安装时有一点要特别注意:jdk和jre必须装到不同目录下,否则初始化react-native项目时大概率报tools.jar not ...
- select函数的介绍和使用
我们所使用的I/O模型一共有五种. 分别为阻塞I/O,非阻塞I/O,I/O复用,信号驱动I/O,异步I/O. 所谓I/O复用就是指管理多个I/O文件描述符,一般会使用(select,poll,epol ...
- hadoop2.x源码编译
转载请标明出处: http://blog.csdn.net/zwto1/article/details/50733753: 介绍 本篇主要会涉及以下内容: 学会编译hadoop2.x源码 编译hado ...
- 反射Reflection创建
step one:(找入口) using System.Reflection; //引用需要用到的命名空间 做任何事都要有开始的地方,不例外,反射也要先找到反射的入口,举个栗子: Assembly a ...
- adobe media encoder cc 2015在win10中打开崩溃的解决办法(该方法同样适用于adobe其他产品)
今天就给大家讲讲adobe media encoder cc 2015启动的时候崩溃的问题,先来看看现象.就是这样了,然后我在网上找了很多办法,有的方法已经过时了,也或者因为现在新版本的adobe m ...
- HyperLedger Fabric 1.1 手动部署单机单节点
手动部署单机单节点 之前发布过官方的e2e部署方案,由于环境或是访问权限等各种问题,还是有相当一部分码友无法成功跑起来,故此,本章将来一次纯手动操作的集群部署. 主要需要的步骤如下: 1:环境整理 2 ...
- 剑指Offer-平衡二叉树
package Tree; /** * 平衡二叉树 * 输入一棵二叉树,判断该二叉树是否是平衡二叉树. * 平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法), ...
- 笔记:Spring Cloud Hystrix 封装命令
使用继承的方式来创建Hystrix 命令,不是用注解的方式来使用 Hystrix 创建 HelloGetCommand 对象,继承与 HystrixCommand 并实现 run 方法,示例如下: p ...
- Bitmap的加载与缓存
Android系统中图片一般用Bitmap对象表示,它支持png,jpg等常见格式.通常情况下图片的体积都比较大,单个应用允许使用的内存又是有限的,所以我们需要采取一些手段减少内存占用并提高加载速度. ...