Hello folks,
everytime I have to deal with blocks, blockreferences and blocktablerecords in the process of modifying a given document I get confused.
I regularly have to find blocks via selectionsets, modify those blocks (delete, change content whatever) or add new ones in case none exist.
My common problem is that I add blocks or modify them, but Autocad won't show the changes until I do a regen.
Because of the complexity of our drawings I need to keep away from regen, but update single blocks when they change. I do this by setting (entity).RecordGraphicsModified(true) during a transaction.
Can somebody please explain in short the connections between "blocks", "blocktablerecords", "blockreferences", how I best use each to do the things I described. I know this might sound really stupid, but I never found something in a written form that would clear up my mind, and I keep confusing the terms.
Thanks in advance!
Joachim
Is your problem updating a block after changing one of its attributes?
You're not entirely clear about that, so feel free to explain further and/or
include some code showing the specific problems you have.
Okay, I will give an example then.
In a given drawing, a block could exist to give some extra information. The block contains text and a few solids.
I start with doing a selection on all inserts with a certain name.
Dim filterLegend() As TypedValue = {New TypedValue(DxfCode.BlockName, LEGENDBLOCK), New TypedValue(DxfCode.Start, "INSERT")}
Dim selFilterLegend As SelectionFilter = New SelectionFilter(filterLegend)
Dim promptResultLegend As PromptSelectionResult = ed.SelectAll(selFilterLegend)
In case I find a block, I have to change its contents and update it.
Should none exist, I need to add the block to the drawing.
As I said, Autocad doesn't like the way I do things, so it doesn't update the drawing. And I do not want to do a complete regen of the drawing, just change and update the contents of this single block or add it and then show it.
Hope this shows better what my intentions are. It's a matter of understanding the basic steps I have to take when dealing with blocks. Just a little list of the steps would be enough for me.
Joachim
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; namespace Namespace1 { public static Class Class1 { /// Shows how to modify a block definition, and /// force all insertions of the block to update /// to reflect the changes to the block. /// This code depends on the existence of a /// block named "TEST". [CommandMethod( "UPDATEBLOCKSAMPLE" )] public static void UpdateBlocks() { Database db = HostApplicationServices.WorkingDatabase; Document doc = Application.DocumentManager.MdiActiveDocument; // Do this *before* starting the transaction where // the changes will occur: doc.TransactionManager.EnableGraphicsFlush( true ); // Start a transaction: using( Transaction tr = doc.TransactionManager.StartTransaction() ) { // Open the block table: BlockTable bt = (BlockTable) db.BlockTableId.GetObject( OpenMode.ForRead ); // Get the ObjectId of the block's BlockTableRecord: ObjectId idBtr = bt["TEST"]; // Open the BlockTableRecord for write: BlockTableRecord btr = (BlockTableRecord) idBtr.GetObject( OpenMode.ForWrite ); // Add a circle to the block's definition: Circle circle = new Circle( new Point3d( 0, 0, 0 ), Vector3d.ZAxis, 10.0 ); btr.AppendEntity( circle ); tr.AddNewlyCreatedDBObject( circle, true ); // Get the ObjectIds of all insertions of the block: ObjectIdCollection ids = btr.GetBlockReferenceIds( true, true ); // Iterate through the ids: foreach( ObjectId id in ids ) { // open each BlocReference for write and call its // RecordGraphicsModified() method. Note the use of // the overload of GetObject() that allows objects on // locked layers to be opened for write: BlockReference blkref = (BlockReference) id.GetObject( OpenMode.ForWrite, false, true ); // Indicate that the block reference's graphics have changed: blkref.RecordGraphicsModified( true ); } // Tell the transaction manager to flush all changes // to the display: doc.TransactionManager.QueueForGraphicsFlush(); doc.TransactionManager.FlushGraphics(); doc.Editor.UpdateScreen(); tr.Commit(); } } } }