.NET

Reply
New Member
Posts: 2
Registered: ‎04-18-2013
Message 1 of 4 (524 Views)
Accepted Solution

Iterating block (block in a block) in C#

524 Views, 3 Replies
04-18-2013 02:24 AM

Hi everyone,

 

I'm a french dude so sorry if my English isn't well enough.

 

I'm new with AutoCAD (2012) and I'm trying to create a commandmethod which allow to select and see what's in the block selected.

I already looked some forums but they used the database instead of the promptselection.

 

- http://forums.autodesk.com/t5/NET/simple-example-of-iterating-a-collection-eg-blocks/td-p/2553278

- http://forums.autodesk.com/t5/NET/How-to-iterate-through-items-of-a-block-reference-in-Dotnet/m-p/...

 

This is my code:

 

    

   [CommandMethod("SelectBlock")]

        public void SelectBlock()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Database db = HostApplicationServices.WorkingDatabase;
            Transaction tr = db.TransactionManager.StartTransaction();

           try
            {
                PromptSelectionOptions opts = new PromptSelectionOptions();
                opts.MessageForAdding = "Select block references:";
                PromptSelectionResult res = ed.GetSelection(opts);

                if (res.Status != PromptStatus.OK){return;}

                 SelectionSet selSet = res.Value;
                 ObjectId[] ids = selSet.GetObjectIds();

                 foreach (ObjectId blkId in ids)
                    {
                   if (blkId != null)
                   {
                       // Open the Block table record Model space for read
                       BlockTableRecord acBlkTblRec = tr.GetObject(blkId, OpenMode.ForRead) as BlockTableRecord;
                        //acBlkTblRec is still null

// Step through the Block table record
if (acBlkTblRec != null) { foreach (ObjectId asObjId in acBlkTblRec) { Entity e = (Entity)tr.GetObject(asObjId, OpenMode.ForRead); ed.WriteMessage(e.ToString()); } } } } tr.Commit(); } catch (Autodesk.AutoCAD.Runtime.Exception ex) { ed.WriteMessage(("Exception: " + ex.Message)); } finally { tr.Dispose(); } } } }

 Everything is fine until the bold line. In fact, I find the block selected (it contains 4 blocks) and go inside the first foreach, but when I instantiate my BlockTableRecord, acBlkTblRec stay "null" and the second foreach is ignored. Do you have any idea about what happended ?

 

I use AutoCad 2012 and Visual Studio 2010.

 

Thank you in advance for your precious help :cathappy:

 

Max

 

 

 

 

Valued Contributor
Posts: 51
Registered: ‎02-25-2010
Message 2 of 4 (519 Views)

Re: Iterating block (block in a block) in C#

04-18-2013 02:46 AM in reply to: maxime.didaoui

Hi

1. Not if (blkId != null), should be:

if ( !blkid.IsErased )

2. Not BlockTableRecord acBlkTblRec = tr.GetObject(blkId, OpenMode.ForRead) as BlockTableRecord; should be:

BlockReference blRef = tr.GetObject( blkId, OpenMode.ForRead ) as BlockReference;

if( blRef != null )

{

...

}

 

or

 

Entity ent = tr.GetObject(blkId, OpenMode.ForRead) as Entity;

if( ent.GetType() == typeof( BlockReference ) )

{

BlockReference blRef = ent as BlockReference;

...

//Now you can open BlockTableRecord:

BlockTableRecord acBlkTblRec = tr.GetObject( blRef.BlockTableRecord, OpenMode.ForRead ) as BlockTableRecord

}

*Expert Elite*
Posts: 1,975
Registered: ‎04-29-2006
Message 3 of 4 (491 Views)

Re : Iterating block (block in a block) in C#

04-18-2013 05:49 AM in reply to: maxime.didaoui

Salut,

 

Il semble que tu ne connaisse pas bien la différence entre une définition de bloc (BlockTableRecord) et une référence de bloc (BlockReference).

Une définition de bloc est un objet "non graphique" stocké dans la table des blocs (BlockTable) qui est une sorte de collection d'entités (les espaces objet et papier sont aussi de type BlockTableRecord).

Une référence de bloc est une représentation géométrique (entité graphique) d'une définition de bloc. Elle est insérée dans un espace objet ou papier ou dans une autre définition de bloc (un objet de type BlockTableRecord).

 

Quand on sélectionne un bloc dans le dessin, c'est une référence de bloc qu'on sélectionne et on peut pas accéder directement aux entités composant ce bloc. On n'y accède que par la définition du bloc.

 

        [CommandMethod("SelectBlock")]

        public void SelectBlock()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                // A selection filter to select only block references
                SelectionFilter filter = new SelectionFilter(
                    new TypedValue[1] { new TypedValue(0, "INSERT") });

                PromptSelectionOptions opts = new PromptSelectionOptions();
                opts.MessageForAdding = "Select block references:";
                PromptSelectionResult res = ed.GetSelection(opts);

                if (res.Status != PromptStatus.OK) { return; }

                SelectionSet selSet = res.Value;
                ObjectId[] ids = selSet.GetObjectIds();

                foreach (ObjectId blkId in ids)
                {
                    if (blkId != null)
                    {
                        // Open the Block reference for read (no need for type checking because as the selection filter did it)
                        BlockReference acBlkRef = (BlockReference)tr.GetObject(blkId, OpenMode.ForRead) as BlockReference;

                        // Open the Block table record of the selected reference for read
                        BlockTableRecord acBlkTblRec =
                            (BlockTableRecord)tr.GetObject(acBlkRef.BlockTableRecord, OpenMode.ForRead);

                        // Step through the Block table record
                        ed.WriteMessage("\n\n{0}", acBlkRef.Name);
                        foreach (ObjectId asObjId in acBlkTblRec)
                        {
                            Entity e = (Entity)tr.GetObject(asObjId, OpenMode.ForRead);
                            ed.WriteMessage("\n{0}", e);
                        }
                    }
                }
                tr.Commit();
            }
        }

 

Gilles Chanteau
New Member
Posts: 2
Registered: ‎04-18-2013
Message 4 of 4 (433 Views)

Re : Iterating block (block in a block) in C#

05-02-2013 06:55 AM in reply to: _gile

Salut Gile,

 

Merci pour cette réponse détaillée, je pense avoir maintenant saisi la différence, et ça marche à merveille.

 

Je vais continuer de me documenter là dessus.

 

And I would like to thank you too fsztuczny, it works now.

 

Maxime

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Welcome to the new Autodesk Community!
If this is your first visit, click here to get started and make the most of the Community. Let us know what you think of the new experience in the Community Feedback Forum.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community