本文章的目的是,在预先不知道一个块是否有可见性选项的前提下,拿到它的可见性属性和列表。
由于这几天突然有此需求,所以查找相应的方法,发现.net没有提供直接的api,且未找到可靠的方法。
一、错误方法
1. 通过名称判断
飞诗跟我说我通过判断PropertyName是否包含"可见性"来判断,并且跟我说这个"可见性"是不能改的,是固定的。
但是经过我的测试,块的可见性名字在块编辑界面可以通过特性栏来修改。 
2. 通过PropertyTypeCode和GetAllowedValues来判断
我们知道DynamicBlockReferenceProperty有一个PropertyTypeCode属性和GetAllowedValues方法,code==5时代表类型是string,有下拉列表时GetAllowedValues可以拿到一个字符串集合。
我还想过通过夹点来辅助判断,因为可见性会使动态块增加一个夹点(点击出现下拉列表那个),这个夹点的属性HotGripInvokesRightClick==true(默认为false),那么这样做是否完全可靠呢?
答案是否定的,因为在动态块里面还有一个叫作"查询"的东西
这个查询的propertyCode同样==5,并且GetAllowedValues同样会拿到一个字符串列表,且同样会增加一个和可见性一模一样的夹点,无法区分出是查询还是可见性。
二、可靠方法
在我觉得反正没什么人用这个查询,就使用上述第二种方法凑合一下的时候。
水友 @执着 给我提供了一段 Lee Mac 的lisp代码,可以通过块表记录的扩展字典和组码来获取到。
经过我的一番尝试和测试,最终使用c#实现,代码如下。
/// <summary>
/// 获取块可见性信息
/// </summary>
/// <param name="btr">块表记录</param>
/// <returns>可见性信息</returns>
public static BlockVisibilityInfo GetVisibilityInfo(this BlockTableRecord btr)
{
var info = new BlockVisibilityInfo();
if (btr.IsDynamicBlock && btr.ExtensionDictionary.IsOk())
{
var dict = btr.GetXDictionary();
if (dict.Contains("ACAD_ENHANCEDBLOCK"))
{
var idEnhancedBlock = dict.GetAt("ACAD_ENHANCEDBLOCK");
var enhancedBlockTypedValues = Env.EntGet(idEnhancedBlock);
var parm = enhancedBlockTypedValues.FirstOrDefault(e =>
e.TypeCode == 360 && e.Value is ObjectId id && id.IsOk() &&
id.ObjectClass.DxfName == "BLOCKVISIBILITYPARAMETER")
.Value;
if (parm is ObjectId parmId)
{
info.Has = true;
var parmTypedValues = Env.EntGet(parmId);
info.PropertyName = parmTypedValues.FirstOrDefault(e => e.TypeCode == 301)
.Value?.ToString() ?? "";
info.AllowedValues = parmTypedValues.Where(e => e.TypeCode == 303)
.Select(e => e.Value?.ToString() ?? "")
.Where(e => !string.IsNullOrWhiteSpace(e))
.ToList();
}
}
}
return info;
}
/// <summary>
/// 块可见性信息
/// </summary>
public class BlockVisibilityInfo
{
/// <summary>
/// 有无可见性
/// </summary>
public bool Has { get; set; }
/// <summary>
/// 属性名
/// </summary>
public string PropertyName { get; set; } = "";
/// <summary>
/// 允许值
/// </summary>
public List<string> AllowedValues { get; set; } = [];
}
上述代码已提交至IFoxCad v0.9分支
具体流程为:
- 获取动态块的原块表记录
- 判断块表记录是否有扩展字典
- 判断扩展字典里是否有
key为"ACAD_ENHANCEDBLOCK"的项,拿到对应的ObjectId1 - 对
ObjectId1进行entget,拿到组码列表1 - 遍历组码列表1中所有组码为360的
ObjectId,判断是否有dxfName为"BLOCKVISIBILITYPARAMETER"的ObjectId2(只会有一个或没有) - 如果能找到
ObjectId2那么说明此动态块有可见性列表 - 对
ObjectId2再次进行entget,拿到组码列表2 - 遍历组码列表2,301组码对应的值为可见性的名字(
PropertyName),303组码(可能有多个)对应的值为允许值(GetAllowedValues)
EntGet如果不知道如何使用,参考下面以前发过的文章。
评论