Changing the colour of the contents of an AutoCAD block using .NET
Here's a question that came in to us, recently:
How can I show the AutoCAD color dialog from .NET? I need to allow the user to select a block, show the AutoCAD color dialog and apply the selected color to the contents of the selected block.
A new member of DevTech Americas - Augusto Gonçalves, who's based in our São Paulo office - answered with the following code (which I've modified slightly, mostly to follow this blog's coding conventions). Thanks, Augusto!
By the way, these previous posts may also be useful to those interested in this topic.
Here's the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.Colors;
namespace ColorPicking
{
public class Commands
{
[CommandMethod("CB")]
public void ColorBlock()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// Ask the user to select a block
PromptEntityOptions peo =
new PromptEntityOptions("\nSelect a block:");
peo.AllowNone = false;
peo.SetRejectMessage("\nMust select a block.");
peo.AddAllowedClass(typeof(BlockReference), false);
PromptEntityResult per =
ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
// Open the entity using a transaction
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
try
{
Entity ent =
(Entity)tr.GetObject(
per.ObjectId,
OpenMode.ForRead
);
// Should always be a block reference,
// but let's make sure
BlockReference br = ent as BlockReference;
if (br != null)
{
// Select the new color
ColorDialog cd = new ColorDialog();
cd.IncludeByBlockByLayer = true;
cd.ShowDialog();
// Change the color of the block itself
br.UpgradeOpen();
br.Color = cd.Color;
// Change every entity to be of color ByBlock
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
br.BlockTableRecord,
OpenMode.ForRead
);
// Iterate through the BlockTableRecord contents
foreach (ObjectId id in btr)
{
// Open the entity
Entity ent2 =
(Entity)tr.GetObject(id, OpenMode.ForWrite);
// Change each entity's color to ByBlock
ent2.Color =
Color.FromColorIndex(ColorMethod.ByBlock, 0);
}
}
// Commit if there hasn't been a problem
// (even if no objects changed: it's just quicker)
tr.Commit();
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
// Something went wrong
ed.WriteMessage(e.ToString());
}
}
}
}
}
Here's a quick example of running the CB command on a block inserted from the "Architectural - Imperial" sample block library that ships with AutoCAD.
After launching the CB command selecting our sports car, we can see the colour selection dialog, which allows us to select an AutoCAD colour index, a true color or a standard colour from a color book:
We can then see our block is changed to this colour (well, in fact the block is changed to be this colour and all its contents are all changed to be coloured ByBlock):
This block happens to be a dynamic block, so if we change it to its truck representation, we see the colour has propagated there, also (as the geometry for this view also resides in the block table record, of course):
By the way, for those of you who are confused by my apparently inconsistent use of spelling, please see this previous post. :-)

Subscribe via RSS
I should probably add that this code clearly doesn't deal with nested blocks, but that would be a relatively easy thing to address (should you so wish).
Kean
Posted by: Kean | October 15, 2008 at 09:12 AM
Kean,
I was looking back at some of your posts, and noticed one on F#. It had the pretty green 3d math plotting pictures.
You mentioned that you used the mouse middle click to do something, and that it sometimes needed a "drag" for the handler to kick in.
I believe this is exactly the same problem I've been running into with the snap menu, and the behavior started in Acad 2006, when the CUI system was introduced.
What I do is set mbuttonpan to 1. Then set my side mouse button as middle button.
For the wheel click, I set my mouse driver to run keystroke F11, which brings up the snap menu due to having set F11 to do that in the acad CUI.
Works great, but you must move the mouse after clicking the wheel, or no snap menu.
This messes me up because I type the mnemonic of the snap, the mous stays still while doing so. I end up typing before the snap menu shows and it messes up the input, have to cancel out.
Is there any possibility of ridding the need to move the mouse, for the handler to kick in?
I really like realtime pan on side button, and osnap menu on wheel click, but have abandoned it for mbuttonpan set to 0 for now...
thx
Posted by: James Maeding | October 15, 2008 at 07:51 PM
James,
The form this occurs in has nothing much to do with AutoCAD: it's a modal form thrown up by AutoCAD using DirectX to view a pretty 3D graph. So I suspect the problem I hit is a general Windows programming issue: something to do with window messages coming through from the mouse. Maybe it's the same one you're hitting, maybe not.
Beyond me, I'm afraid - and there's no great need for me to fix this for the demo app I've thrown together - but hopefully you'll manage to work it out.
Kean
Posted by: Kean | October 16, 2008 at 09:48 AM
I NOT A JOB
Posted by: james | October 22, 2008 at 08:58 AM
I HAVE C++ DEMO
Posted by: james | October 22, 2008 at 09:02 AM