cad二次 开发 修改块的颜色_[CAD二次开发]沙场秋点兵——CAD中的块(二)

本文探讨了CAD二次开发中的属性块,详细介绍了属性块如何存储信息,并通过代码示例展示了如何创建和修改属性块。内容包括属性块的构造、属性编辑器的使用,以及封装方法和注册命令来制作属性块的过程。
摘要由CSDN通过智能技术生成

    今天是本篇内容的第二节,在上一节的基础上继续排兵布阵,来扩充在CAD二次开发中可能用到的图块。这一节介绍一下属性块,属性块与普通的图块相比,多了一个字典作为一组属性来存储信息。我们在图纸中看到的这种表格就是一个属性块:

922748988b0ffd63034e26630620ef58.png

    这是一个自控设计中代表一个可燃气体探测器标注信息的图块,其中TAG代表位号,EL是安装标高,JB是接线箱号,MED是检测介质,我们可以在增强属性编辑器中编辑对应的值来标注探测器的信息。这里的属性是一个字典,也就是一组键值对,这里的值属于AttributeDefinition类,它派生自DBText

91ba47efeb96fdefabd6e6ef168f1008.png

    它的构造函数里面:position代表该数值显示的位置;value是数值;tag是标签,即属性的名称;prompt是提示信息,可以再增强属性编辑器中起到提示作用;style是显示值的文字的特性。

    这一节的目标是封装方法并且注册命令,来制作一个类似的属性块,可能代码比较多,限于篇幅,部分代码的解释详见注释。

    首先封装方法,为块表记录添加属性,作为ObjectId的拓展方法,同时需要一个列表存储插入的属性,代码如下:

//为块表记录添加属性public static void AddAttsToBlock(this ObjectId blockId, List atts){    Database db = blockId.Database;//获取数据库对象    //打开块表记录为写的状态    BlockTableRecord btr = (BlockTableRecord)blockId.GetObject(OpenMode.ForWrite);    //遍历属性定义对象列表    foreach (AttributeDefinition att in atts)    {        btr.AppendEntity(att);//为块表记录添加属性        db.TransactionManager.AddNewlyCreatedDBObject(att, true);//事务处理    }    btr.DowngradeOpen();//为了安全,将块表记录的状态改为读}

    老规矩,这里重载方法,使其可以接受很多属性而不需要转换为列表:

public static void AddAttsToBlock(this ObjectId blockId, params AttributeDefinition[] atts){    blockId.AddAttsToBlock(atts.ToList());}

    接下来插入属性块参照的方法,上一节介绍的插入简单块的方法是一个没有返回值的方法,这里因为需要插入属性,所以需要块定义的ObjectId来传递,所以这里以ObjectId为返回类型,返回添加的块参照的Id以便之后的使用:

public static ObjectId InsertBlockReference(this ObjectId spaceId, string layer, string blockName, Point3d position, Scale3d scale, double rotateAngle){    ObjectId blockRefId;//存储要插入的块参照的Id    Database db = spaceId.Database;//获取数据库对象    //以读的方式打开块表    BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);    //如果没有blockName表示的块,则程序返回    if (!bt.Has(blockName)) return ObjectId.Null;    //以写的方式打开空间(模型空间或图纸空间)    BlockTableRecord space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);    //创建一个块参照并设置插入点    BlockReference br = new BlockReference(position, bt[blockName]);    br.ScaleFactors = scale;//设置块参照的缩放比例    br.Layer = layer;//设置块参照的层名    br.Rotation = rotateAngle;//设置块参照的旋转角度    ObjectId btrId = bt[blockName];//获取块表记录的Id    //打开块表记录    BlockTableRecord record = (BlockTableRecord)btrId.GetObject(OpenMode.ForRead);    //添加可缩放性支持    if (record.Annotative == AnnotativeStates.True)    {        ObjectContextCollection contextCollection = db.ObjectContextManager.GetContextCollection("ACDB_ANNOTATIONSCALES");        ObjectContexts.AddContext(br, contextCollection.GetContext("1:1"));    }    blockRefId = space.AppendEntity(br);//在空间中加入创建的块参照    db.TransactionManager.AddNewlyCreatedDBObject(br, true);//通知事务处理加入创建的块参照    space.DowngradeOpen();//为了安全,将块表状态改为读    return blockRefId;//返回添加的块参照的Id}

    重载上面的方法,使之可以接受除以上信息外的属性键值对:

public static ObjectId InsertBlockReference(this ObjectId spaceId, string layer, string blockName, Point3d position, Scale3d scale, double rotateAngle, Dictionary<string, string> attNameValues){    Database db = spaceId.Database;//获取数据库对象    //以读的方式打开块表    BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);    //如果没有blockName表示的块,则程序返回    if (!bt.Has(blockName)) return ObjectId.Null;    //以写的方式打开空间(模型空间或图纸空间)    BlockTableRecord space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);    ObjectId btrId = bt[blockName];//获取块表记录的Id    //打开块表记录    BlockTableRecord record = (BlockTableRecord)btrId.GetObject(OpenMode.ForRead);    //创建一个块参照并设置插入点    BlockReference br = new BlockReference(position, bt[blockName]);    br.ScaleFactors = scale;//设置块参照的缩放比例    br.Layer = layer;//设置块参照的层名    br.Rotation = rotateAngle;//设置块参照的旋转角度    space.AppendEntity(br);//为了安全,将块表状态改为读     //判断块表记录是否包含属性定义    if (record.HasAttributeDefinitions)    {        //若包含属性定义,则遍历属性定义        foreach (ObjectId id in record)        {            //检查是否是属性定义            AttributeDefinition attDef = id.GetObject(OpenMode.ForRead) as AttributeDefinition;            if (attDef != null)            {                //创建一个新的属性对象                AttributeReference attribute = new AttributeReference();                //从属性定义获得属性对象的对象特性                attribute.SetAttributeFromBlock(attDef, br.BlockTransform);                //设置属性对象的其它特性                attribute.Position = attDef.Position.TransformBy(br.BlockTransform);                attribute.Rotation = attDef.Rotation;                attribute.AdjustAlignment(db);                //判断是否包含指定的属性名称                if (attNameValues.ContainsKey(attDef.Tag.ToUpper()))                {                    //设置属性值                    attribute.TextString = attNameValues[attDef.Tag.ToUpper()].ToString();                }                //向块参照添加属性对象                br.AttributeCollection.AppendAttribute(attribute);                db.TransactionManager.AddNewlyCreatedDBObject(attribute, true);            }        }    }    db.TransactionManager.AddNewlyCreatedDBObject(br, true);    return br.ObjectId;//返回添加的块参照的Id}

    这里我们还需要一个方法,用于修改属性块中的属性:

public static void UpdateAttributesInBlock(this ObjectId blockRefId, Dictionary<string, string> attNameValues){    //获取块参照对象    BlockReference blockRef = blockRefId.GetObject(OpenMode.ForRead) as BlockReference;    if (blockRef != null)    {        //遍历块参照中的属性        foreach (ObjectId id in blockRef.AttributeCollection)        {            //获取属性            AttributeReference attref = id.GetObject(OpenMode.ForRead) as AttributeReference;            //判断是否包含指定的属性名称            if (attNameValues.ContainsKey(attref.Tag.ToUpper()))            {                attref.UpgradeOpen();//切换属性对象为写的状态                //设置属性值                attref.TextString = attNameValues[attref.Tag.ToUpper()].ToString();                attref.DowngradeOpen();//为了安全,将属性对象的状态改为读            }        }    }}

    接下来注册命令,开始先绘制块定义:

public ObjectId MakeInfoTable(){    ObjectId blockId;//用于储存ObjectId    Database db = HostApplicationServices.WorkingDatabase;//数据库    //事务处理,用于绘制图形并且添加其到块定义中    using (Transaction trans = db.TransactionManager.StartTransaction())    {        //绘制图形        Point3d pt1 = new Point3d(50, 0, 0);        Point3d pt2 = new Point3d(50, 20, 0);        Point3d pt3 = new Point3d(0, 20, 0);        Point3d pt4 = new Point3d(-7.5, 15, 0);        Point3d pt5 = new Point3d(8.5, 0, 0);        Point3d pt6 = new Point3d(8.5, 20, 0);        Point3d pt7 = new Point3d(0, 15, 0);        Line line1 = new Line(Point3d.Origin, pt1);        Line line2 = new Line(pt1, pt2);        Line line3 = new Line(pt2, pt3);        Line line4 = new Line(pt3, Point3d.Origin);        Line line5 = new Line(pt4, pt7);        Line line6 = new Line(pt5, pt6);        Line line7 = new Line(pt7, new Point3d(50, 15, 0));        Line line8 = new Line(new Point3d(0, 10, 0), new Point3d(50, 10, 0));        Line line9 = new Line(new Point3d(0, 5, 0), new Point3d(50, 5, 0));        DBText dBText1 = new DBText();        dBText1.Position = new Point3d(2, 15.5, 0);        dBText1.Height = 2.5;        dBText1.TextString = "TAG";        DBText dBText2 = new DBText();        dBText2.Position = new Point3d(2, 10.5, 0);        dBText2.Height = 2.5;        dBText2.TextString = "EL";        DBText dBText3 = new DBText();        dBText3.Position = new Point3d(2, 5.5, 0);        dBText3.Height = 2.5;        dBText3.TextString = "JB";        DBText dBText4 = new DBText();        dBText4.Position = new Point3d(2, 0.5, 0);        dBText4.Height = 2.5;        dBText4.TextString = "MED";        line1.Color = Color.FromColorIndex(ColorMethod.ByColor, 2);        //添加        blockId = db.AddBlockTableRecord("InfoTable", line1, line2, line3, line4, line5, line6, line7, line8, line9, dBText1, dBText2, dBText3, dBText4);        trans.Commit();    }    return blockId;}

将块定义加入到模型空间:

[CommandMethod("AddInfoTable")]public void AddInfoTable(){    Database db = HostApplicationServices.WorkingDatabase;    ObjectId blockId = MakeInfoTable();    using (Transaction trans = db.TransactionManager.StartTransaction())    {        //表示探测器的编号        AttributeDefinition attNum = new AttributeDefinition(Point3d.Origin, "1", "INFONUM", "图纸中的序号", ObjectId.Null);        //设置属性定义的通用样式        SetStyleForAtt(attNum, false);        //设置属性的对齐点        attNum.AlignmentPoint = new Point3d(-6, 15, 0);        //表示探测器位号的属性定义        AttributeDefinition attTag = new AttributeDefinition(Point3d.Origin, "1", "INFOTAG", "仪表位号", ObjectId.Null);        SetStyleForAtt(attTag, false);        attTag.AlignmentPoint = new Point3d(10, 15.5, 0);        //表示探测器标高的属性定义        AttributeDefinition attHeight = new AttributeDefinition(Point3d.Origin, "500", "INFOHEIGHT", "仪表标高", ObjectId.Null);        SetStyleForAtt(attHeight, false);        attHeight.AlignmentPoint = new Point3d(10, 10.5, 0);        //表示探测器检测介质的属性定义        AttributeDefinition attType = new AttributeDefinition(Point3d.Origin, "可燃气体", "INFOMEDIUM", "检测器检测介质", ObjectId.Null);        SetStyleForAtt(attType, false);        attType.AlignmentPoint = new Point3d(10, 0.5, 0);        //表示探测器所在接线箱的定义        AttributeDefinition attJB = new AttributeDefinition(Point3d.Origin, "0", "INFOJBOX", "检测器进的接线箱", ObjectId.Null);        SetStyleForAtt(attJB, false);        attJB.AlignmentPoint = new Point3d(10, 5.5, 0);        blockId.AddAttsToBlock(attNum, attTag, attHeight, attType, attJB);        trans.Commit();    }}

    设置字体属性:

private void SetStyleForAtt(AttributeDefinition att, bool invisible){    att.Height = 2.5;//属性文字的高度    //属性文字的水平对齐方式为左对齐    att.HorizontalMode = TextHorizontalMode.TextLeft;    //属性文字的垂直对齐方式为底部对齐    att.VerticalMode = TextVerticalMode.TextBottom;    att.Invisible = invisible; //属性文字的可见性}

    插入属性块参照:

[CommandMethod("InsertInfoTable")]public void InsertInfoTable(){    Database db = HostApplicationServices.WorkingDatabase;    ObjectId spaceId = db.CurrentSpaceId;//获取当前空间(模型空间或图纸空间)    using (Transaction trans = db.TransactionManager.StartTransaction())    {        Dictionary<string, string> atts = new Dictionary<string, string>();        //属性        atts.Add("NUM", "1");        //插入块参照        spaceId.InsertBlockReference("0", "InfoTable", new Point3d(100, 0, 0), new Scale3d(1), 0, atts);        //提交事务处理        trans.Commit();    }}

    代码执行效果如下面的视频所示:

    好了,这一节的内容就是这样,代码比较多,但是最后插入块参照的命令代码缺比较简洁明确,这刚好体现了面向对象编程代码的复用性,下一节继续介绍有关图块的内容,如果有建议或是批评指教,欢迎在公众号内留言,谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值