cad.net 关于动态块的处理

动态块名

测试版本: Acad2008

BlockReference.IsDynamicBlock 是用来判断是否是动态块的.
当频繁使用的时候,会出现报错: eInvalidObjectId错误. System.AccessViolationException的异常
img

但是你要获取动态块名称的时候,直接读就好了,不需要判断它是不是动态块的.
可能的原因之一是: 块参照的Z比例为0或许不等比缩放就会令动态块变成普通块,那么导致判断动态块失效.

namespace JoinBox
{
    public static partial class BlockHelper
    {
        /// <summary>
        /// 动态块真实块名获取
        /// </summary>
        /// <param name="brRec">块参照</param>
        /// <returns>成功返回:块的真实名称,失败返回:null</returns>
        // 1.块的Z比例是0就会令动态块变成普通块,那么导致判断动态块失效
        // 2.brRec.IsDynamicBlock 如果是动态块这句会报错:eInvalidObjectId
        //   重复空格执行上次报这个错误,应该在所有GetObject位置写.Dispose();
        public static string GetBlockName(this BlockReference brRec)
        {
            string blockName = string.Empty;
            if (brRec.DynamicBlockTableRecord.IsOk())
            {
                // 动态块表记录可以获取 动态块名 也可以获取 普通块名
                var btRec = brRec.DynamicBlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord;
                blockName = btRec.Name;
                btRec.Dispose();
            }
            return blockName;
        }
    }
    public static partial class EntityEdit
    {
        /// <summary>
        /// id有效,未被删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static bool IsOk(this ObjectId id)
        {
            return !id.IsNull && id.IsValid && !id.IsErased && !id.IsEffectivelyErased && id.IsResident;
        }
    }
}

动态块过滤器

如果要构造选择集,那么把过滤器写成以下形式就好了.这可以令普通块和动态块都受惠~

#if !HC2020
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.EditorInput;
#endif
using System.Collections.Generic;

namespace JoinBox
{
    public static class SsgetFilterEx
    {
        ///https://blog.csdn.net/yxp_xa/article/details/72229202?tdsourcetag=s_pcqq_aiomsg
        /// <summary>
        /// 转义通配符,加入过滤器必须转义
        /// </summary>
        /// <param name="blockName">块名</param>
        /// <returns></returns>
        static string BlockNameEscape(string blockName)
        {
            return blockName.Replace("#", "`#").Replace("@", "`@");
        }

        //https://www.cnblogs.com/edata/p/6797362.html
        /// <summary>
        /// 通过块信息,设置动态块过滤器或普通块过滤器
        /// </summary>
        /// <param name="baseId">块的图元id</param>
        /// <returns>过滤器</returns>
        public static SelectionFilter GetBlockSelectionFilter(this Transaction tr, ObjectId baseId)
        {
            //选择集过滤器
            var list = new List<TypedValue>();
            var brRec = tr.GetObject(baseId, OpenMode.ForRead) as BlockReference;
            string blockName = BlockNameEscape(brRec.GetBlockName());

            list.Add(new TypedValue((int)DxfCode.Start, "INSERT"));  //是块

            //当前布局名称(视口内为模型)
            string layoutName = CadSystem.GetMouseSpace();
            list.Add(new TypedValue((int)DxfCode.LayoutName, layoutName));//是同一个空间 "*Model_Space"

            //动态块过滤器{动态块名,真实名称(匿名块不提供)}
            list.Add(new TypedValue((int)DxfCode.BlockName, $"`*U*,{blockName}"));
            return new SelectionFilter(list.ToArray());
        }
    }
    public static partial class CadSystem
    {
        /// <summary>
        /// 当前布局名称(视口内为模型)
        /// </summary>
        /// <returns>模型或布局名称</returns>
        public static string GetMouseSpace()
        {
            //获得当前布局名称
            string layoutName = LayoutManager.Current.CurrentLayout;//切换当前布局要锁文档
            if (SpatialPoint() == CadSystem.SpatialPosition.Viewport)
                layoutName = "Model";
            return layoutName;
        }
    }
}

如果你仍然会报 eInvalidObjectId 错误,我在频繁重复空格执行上次命令时候报这个错误,这个时候应该在所有GetObject开启的东西最后 .Dispose();

动态块参数

/// <summary>
/// 更改动态块拉伸参数
/// </summary>
/// <param name="ent">动态块参照的图元</param>
/// <param name="name">动作参数名</param>
/// <param name="value">动作参数值</param>
private static void ChangDynamicBlockValue(Entity ent,string name,string valueStr)
{
    if (ent is BlockReference br && br.IsDynamicBlock)//如果是动态块
    {
        br.UpgradeOpen();
        var props = br.DynamicBlockReferencePropertyCollection; //动态块属性集
        foreach (DynamicBlockReferenceProperty item in props)
        {
            if (item.PropertyName.Contains(name))//参数名:可见性/距离之类的
                 item.Value = valueStr;//参数值
        }
       br.DowngradeOpen();
    }
}

动态块未能解决的问题

怎么用纯代码的方式新建一个动态块.
edata思路:
1:弄一个空的dxf
2:构造一个有动态块的块定义
3:删除后的
弄三个自己比较.

可见性名称

例如:我需要找到"可见性"被改名之后的参数名才能设置参数值,不然缺失参数名则无法操作(因为不能枚举字符串),
发现是301组码下面:

代码参考:cad.net 句柄遍历数据库

(完)

posted @ 2020-02-27 12:17  惊惊  阅读(2204)  评论(1编辑  收藏  举报