Need to change color of only one block instead of all the blocks.

Need to change color of only one block instead of all the blocks.

jlobo2
Advocate Advocate
3,689 Views
11 Replies
Message 1 of 12

Need to change color of only one block instead of all the blocks.

jlobo2
Advocate
Advocate

I was going through the forums and came through this link Change All the blocks color.

I was wondering, on how to change the color of just one block?

 

Thank You for your help in advance.

 

I have followed this link and created a block, surrounded by a square of lines.

Now, I need to update the color of one block - per square.

 

 

0 Likes
Accepted solutions (1)
3,690 Views
11 Replies
Replies (11)
Message 2 of 12

_gile
Consultant
Consultant

Hi,

This is related to the basics of AutoCAD blocks behaviour.

If all components in the block definition (BlockTableRecord) have their Color property set to ByBlock, setting the color of a bloc reference will affect the whome reference.

If you set the color of any entity within a block definition to anything but ByBlock this will affect all block references.

You can try this without any code.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 12

jlobo2
Advocate
Advocate

So this is my code below:

 

using (transaction)
{
         // Get the block table from the drawing
         BlockTable blocktable = (BlockTable)transaction.GetObject(acCurDb.BlockTableId, OpenMode.ForRead);

       if (!blocktable.Has(givenPANBLK))
      {
          // Create our new block table record...
           BlockTableRecord blocktablerecord = new BlockTableRecord();
          // ... and set its properties
          blocktablerecord.Name = givenPANBLK;

           // Set the insertion point for the block
          blocktablerecord.Origin = new Point3d(originPt.X, originPt.Y, originPt.Z);

          // Add some lines to the block to form a square  (the entities belong directly to the block)
           DBObjectCollection ents =
                       SquareOfLines(
                                       panelThickness, originPt,  givenLeftHeight, givenRightHeight);
          foreach (Entity ent in ents)
          { blocktablerecord.AppendEntity(ent); }

          
            foreach (Entity ent in entsREW)
            { blocktablerecord.AppendEntity(ent);}
   }

 

 

// Add an attribute definition to the block
//
// PANEL NAME
//
{
       AttributeDefinition acAttDef = new AttributeDefinition();
       acAttDef.Position = new Point3d(originPt.X, originPt.Y, originPt.Z);
       acAttDef.Verifiable = true;
        acAttDef.Prompt = Constants.PANBLK_PROMPT_PANELNAME;
        acAttDef.Tag = Constants.PANBLK_TAG_PANELNAME;
         acAttDef.TextString = "A";
       acAttDef.Height = panelNameTextHeight;
         acAttDef.ColorIndex = 132;
         acAttDef.Layer = Constants.LAYER_PANNAME;
        acAttDef.Invisible = false;
          blocktablerecord.AppendEntity(acAttDef);
}
////
//// and many more Attribute definitions.

 

 

Now, How do I update the color of the lines? which are entities in this case?

0 Likes
Message 4 of 12

_gile
Consultant
Consultant

The lines (and the attribute definitions) are entities.

It looks like you're missing the basics of AutoCAD and, in my opinion, you cannot pretend customizing a software if you do not have a good knowledge about how it natively works.

About defining and referencing blocks, you start from this section.

About using blocks with the API, you should read this section.

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 12

jlobo2
Advocate
Advocate

Thank You for your response and the resources.

 

I guess I am looking for How to access the entities of lines.

 

This is how, I am building the square block of lines.


    {
           Point3d[] pts = {
            new Point3d( givenRefPoint.X,  givenRefPoint.Y,  givenRefPoint.Z),
            new Point3d( givenRefPoint.X,  givenRefPoint.Y + givenLeftHeight, givenRefPoint.Z),
            new Point3d( givenRefPoint.X + givenWidthTop ,  givenRefPoint.Y + givenRightHeight, givenRefPoint.Z),
            new Point3d(givenRefPoint.X + givenWidthBase , givenRefPoint.Y + givenRightHeight, givenRefPoint.Z),
            new Point3d(givenRefPoint.X+ givenWidthBase,givenRefPoint.Y, givenRefPoint.Z)
    };
   

     int max = pts.GetUpperBound(0);

     for (int i = 0; i <= max; i++)
     {
           int j = (i == max ? 0 : i + 1);
           Line ln = new Line(pts[i], pts[j]);
           ln.Thickness = panelThickness;
           ln.Layer = Constants.LAYER_PANBLK; // I understand, I can change to one constant color.
           ents.Add(ln);
      }
}

 

I am looking for a way or resource, on how to access those line entities from the drawing?

Currently, I am accessing it from the BlockTableRecord, but it's changing the color for all the block references.

 

This is what I am currently using:

using (Transaction acTrans = dwgDb.TransactionManager.StartTransaction())
{
             // Access drawing block table
            pBlockTbl = acTrans.GetObject(dwgDb.BlockTableId, OpenMode.ForWrite) as BlockTable;
            // ------------------
           // ------------------
          foreach (ObjectId btrId in pBlockTbl)
          {
               BlockTableRecord btr = (BlockTableRecord)acTrans.GetObject(btrId, OpenMode.ForRead);
               if (!btr.IsLayout)
               {
                     foreach (ObjectId id in btr)
                     {
                           Entity ent = (Entity)acTrans.GetObject(thePANBLKBlockReference, OpenMode.ForWrite);
                           ent.Layer = Constants.LAYER_FINGRD;
                     }
               }
         }

}

 

Thank You for your help in advance.

0 Likes
Message 6 of 12

_gile
Consultant
Consultant
Accepted solution

You can try the following commands.

 

To insert a 'SquareBlock' reference and set its color (the block definition is automatically created if it not already exists in the block table).

        [CommandMethod("INSERTSQUAREBLOCK")]
        public static void InsertSquareBlock()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var pdo = new PromptDistanceOptions("\nSpecify width: ");
            var pdr = ed.GetDistance(pdo);
            if (pdr.Status != PromptStatus.OK)
                return;
            double width = pdr.Value;

            pdo.Message = "\nSpecify height: ";
            pdr = ed.GetDistance(pdo);
            if (pdr.Status != PromptStatus.OK)
                return;
            double height = pdr.Value;

            var ppr = ed.GetPoint("\nInsertion point: ");
            if (ppr.Status != PromptStatus.OK)
                return;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                // create the block if not already in the the block table
                if (!bt.Has("SquareBlock"))
                    CreateSquareBlock(db, tr, bt);
                // insert a new reference at specified point
                var br = new BlockReference(ppr.Value, bt["SquareBlock"]);
                br.ScaleFactors = new Scale3d(width, height, 1.0);
                br.TransformBy(ed.CurrentUserCoordinateSystem);
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                curSpace.AppendEntity(br);
                tr.AddNewlyCreatedDBObject(br, true);
                // change the block reference color
                var colorDialog = new Autodesk.AutoCAD.Windows.ColorDialog();
                colorDialog.IncludeByBlockByLayer = false;
                if (colorDialog.ShowModal().Value)
                {
                    tr.GetObject(br.ObjectId, OpenMode.ForWrite);
                    br.Color = colorDialog.Color;
                }
                tr.Commit();
            }
        }

        // creates a new block definition
        private static void CreateSquareBlock(Database db, Transaction tr, BlockTable bt)
        {
            tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
            var btr = new BlockTableRecord { Name = "SquareBlock" };
            bt.Add(btr);
            tr.AddNewlyCreatedDBObject(btr, true);
            var points = new[]{
                        new Point3d(0.0, 0.0, 0.0),
                        new Point3d(1.0, 0.0, 0.0),
                        new Point3d(1.0, 1.0, 0.0),
                        new Point3d(0.0, 1.0, 0.0) };
            for (int i = 0; i < 4; i++)
            {
                var line = new Line(points[i], points[(i + 1) % 4]);
                line.ColorIndex = 0; // set the line color to ByBlock
                btr.AppendEntity(line);
                tr.AddNewlyCreatedDBObject(line, true);
            }
        }

To change the color of an already inserted block reference.

        [CommandMethod("CHANGESQUAREBLOCKCOLOR")]
        public static void ChangeSquareBlockColor()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var options = new PromptEntityOptions("\nSelect a square block: ");
            options.SetRejectMessage("\nSelected object is not a block.");
            options.AddAllowedClass(typeof(BlockReference), true);
            var result = ed.GetEntity(options);
            if (result.Status != PromptStatus.OK)
                return;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var br = (BlockReference)tr.GetObject(result.ObjectId, OpenMode.ForRead);
                if (br.Name != "SquareBlock")
                {
                    ed.WriteMessage("\nSelected block is not a 'SquareBlock'");
                    return;
                }
                var colorDialog = new Autodesk.AutoCAD.Windows.ColorDialog();
                colorDialog.IncludeByBlockByLayer = false;
                if (colorDialog.ShowModal().Value)
                {
                    tr.GetObject(br.ObjectId, OpenMode.ForWrite);
                    br.Color = colorDialog.Color;
                }
                    tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 12

dgorsman
Consultant
Consultant

Yes, that changes all the block references - that's how they work.  One definition, many references, so you don't have to manage the references individually.  If you want to change them individually that means having separate definitions or finding another solution such as groups, which have their own problems. 

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


0 Likes
Message 8 of 12

norman.yuan
Mentor
Mentor

Let's make it clear: you want to change something's color inside of a BlockReference, but not the block definition (BlockTableRecord), so the other BlockReferences of the same block definition would not be affected. Therefore, the code you showed in your post on how the block is built is irrelevant: you cannot change entitiy's color in a BlockTableRecord without affecting all BlockReferences of the block definition.

 

You may want to describe in which context you want a BlockReferece change its color partially: do you want the change be permanently, or just temporarily (as you said in the other post: when the block reference is selected/highlighted)?

 

If you want the change to be permanent, you would something quite similar as AutoCAD's dynamic block: define a new BlockTableRecord (you can copy from the original BlockTableRecord, and give it a different name, or even an anonymous block name), and then change entity's color inside the new block; once the new blocktablerecord is created, you simply change the BlockReference in interest to reference this new BlockTableRecord. 

 

If you only want the change to be temporary (say, you want to make the change when the blockreference is selected, besides AutoCAD's default highlight, you want also do your own hightlight on part of the block reference). IN this case, you may want to look into HighlightOverrule (which you may or may not be able to easily overrule how the BlockReference is highlighted prtially, but worth a look, IMO); or you can use Transient Graphics to draw the entities in block reference (according to its blocktablerecord, of course) whatever way you want.

 

Or, you may simply define your block as dynamic block with 2 squares stacking one on top of another, one is int the default color and another is in different/highlight color. Then you set 2 Visibility states to show each square. Now you can use your code to set the block reference's Visibility state accordingly when needed.

 

All I suggested here are quite advanced topics in AutoCAD .NET API programming, it may need quite a bit study to get you there.

 

When posting question, it would be better not only ask a simple question, but also provide more detailed context of why you ask the question, what scenario/user case the question is raised and possible answer could apply.

 

 

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 9 of 12

jlobo2
Advocate
Advocate

Thank You for your response.

I want to achieve the following. See attached pic.

 

Also, there are many blocks in the drawing file, but I just need to update the one's that are selected.

Currently, I am struggling with, how to update the color of the lines(representing the square.) 

I can update the attribute definition colors, but not the lines.

 

Any help regarding that would be greatly appreciated.

Thank you for your help and suggestions in advance.

0 Likes
Message 10 of 12

jlobo2
Advocate
Advocate

Gilles, Thank You for your response. Your responses have been of great help.

 

I missed setting the color ByBlock - I am setting them ByLayer.

 

I want to achieve the following. See attached pic.

 

Also, there are many blocks in the drawing file, but I just need to update the one's that are selected.

Currently, I am struggling with, how to update the color of the lines(representing the square.) 

I can update the attribute definition colors, but not the lines.

 

Any help regarding that would be greatly appreciated.

Thank you for your help and suggestions in advance.

0 Likes
Message 11 of 12

_gile
Consultant
Consultant

As I and some other said many times before, any change to entities in the block definition will affect all the inserted references (this does not apply to the attribute definitions*).

So, one more time, the only way to set the color of some entities differntly in different block references is to set the color of these entities to ByBlock in the block definition so that forcing the color of each block reference will affect the color of these entities.

This is the way used in the snippet I posted. you can try them ans study them to understand how they work.

 

* Attribute definitions are used like templates to create the attribute references. Attribute references are linked to a block reference but they are separated entities. This is why you can edit them independantly in each block reference.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 12

jlobo2
Advocate
Advocate

Ok,

 

Thank You for your help Gilles.

0 Likes