Author Topic: Block-Functions (Select, Explode, etc.)  (Read 3569 times)

0 Members and 1 Guest are viewing this topic.

klahie

  • Guest
Block-Functions (Select, Explode, etc.)
« on: April 16, 2012, 06:10:32 AM »
Hi community!

I have a C#-WPF-Application. In this application there is a list of blocks in my drawing. When I click one of these blocks in the listbox I have several button-functions.
 
One of them:
Select the in the list selected block in the drawing.
 
Another:
Explode the in the list selected block.
 
I found several topics with Selection, but none of them worked for me. I'm looking for a selection via ObjectId or blockname of a single block, in the most cases the selectionfilter needs an array(?).
And I'm absolutly helpless with block-explosion.
 
I'm really new to Autocad and C#-Addin-programming.
 
Thanks in advance!
Greets
Klaus

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block-Functions (Select, Explode, etc.)
« Reply #1 on: April 16, 2012, 08:06:36 AM »
Are you databinding your list of blocks? If you are and you should be, then just create a struct of ObjectId and whatever your using in your list now. Create a List<new struct>, Databind that, and then you can always get an ObjectId from your current selection in the list.

Oh, and welcome to the Swamp!.
Revit 2019, AMEP 2019 64bit Win 10

klahie

  • Guest
Re: Block-Functions (Select, Explode, etc.)
« Reply #2 on: April 16, 2012, 08:23:32 AM »
I have no problem with getting the objectid of the item which is selected in the list, but how do I select this item in my autocad drawing by objectid or the name of this item?

Greets
Klaus

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block-Functions (Select, Explode, etc.)
« Reply #3 on: April 16, 2012, 02:33:05 PM »
By ObjectId.  The preferred method is using the ObjectId inside of a Transaction.  Inside of a transaction you can use the Transactions GetObject() method to get the DBObject.

The BlockRecordRecord or block definition is located in the BlockTable of the database.  The BlockReferences or actual blocks seen in the drawing are located in the ModelSpace record of the BlockTable.

See here for block code examples - http://www.theswamp.org/index.php?topic=31859.msg373455#msg373455
Revit 2019, AMEP 2019 64bit Win 10

klahie

  • Guest
Re: Block-Functions (Select, Explode, etc.)
« Reply #4 on: April 16, 2012, 02:44:07 PM »
My code looks like this at the moment:

Code: [Select]
public void selectBlock(string blockName)
{
   BlockTableRecord btr = null;
   Editor ed = doc.Editor;
   using (tr = db.TransactionManager.StartTransaction())
   {
      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
      foreach (ObjectId objId in bt)
      {
         btr = (BlockTableRecord)tr.GetObject(objId, OpenMode.ForWrite);

         if (blockName == btr.Name)
         {
            TypedValue[] tvs = new TypedValue[] {
               new TypedValue(
                  (int)DxfCode.Operator,
                  "<or"
               ),
               new TypedValue (
                  (int)DxfCode.BlockName,
                  btr.Name
               ),
               new TypedValue(
                  (int)DxfCode.Operator,
                  "or>"
               )
            };

            SelectionFilter sf = new SelectionFilter(tvs);
            PromptSelectionResult psr = ed.SelectAll(sf);
            ed.WriteMessage("\nFound {0} entit{1}.", psr.Value.Count, (psr.Value.Count == 1 ? "y" : "ies"));
         }
      }
   }
}

This is the selection filter mechanism like it is explained at Kean Walmsleys Autocad Blog (Through the Interface).

The editor-message shows up that AutoCAD finds one entity. But this entity isn't selected!?
 
But Kean Walmsley also writes in his blog: " This simply tells you how many entities met the selection criteria - it doesn't leave them selected for use by further commands.".

How do I leave it selected for use by further commands?

But if you mean that I should select by objectid, its fine for me too. I'm searching the easiest way to get this working.  ;-)

Many thanks!
Klaus

EDIT: Oh, I've overlooked your link. I'll be back after reading!  ;-)
EDIT1: Okay, I should have seen this attribute-extraction routine some weeks earlier, that would have made my work definitely easier...
« Last Edit: April 16, 2012, 02:52:10 PM by klahie »

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block-Functions (Select, Explode, etc.)
« Reply #5 on: April 16, 2012, 04:03:36 PM »
If you're trying to just get all the references in the dwg to each block definition then when you open the BlockTableRecord just use the GetBlockReferenceIds method and that will give you an ObjectIdCollection of all the Objectids of the BlockReferences in the drawing.

Also, its better practice to open each object as ReadOnly and when your ready to write to the Database use the method UpgradeOpen() on the objects that need writing.

Keep your BlockTableRecord declaration for btr inside your using statement. Since you're using the transaction to open it, the transaction is going to close it when you leave the using statement and if you try to use it could crash AutoCAD.
« Last Edit: April 16, 2012, 04:10:35 PM by MexicanCustard »
Revit 2019, AMEP 2019 64bit Win 10

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block-Functions (Select, Explode, etc.)
« Reply #6 on: April 16, 2012, 04:23:26 PM »
Code: [Select]
public void SelectBlock(string blockName)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                ObjectIdCollection ids;
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                foreach (ObjectId objId in bt)
                {
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(objId, OpenMode.ForRead);
                    if (btr.Name == blockName)
                    {
                        ids = btr.GetBlockReferenceIds(true, false);
                        ed.WriteMessage("\nFound {0} entit{1}", ids.Count, (ids.Count == 1 ? "y" : "ies"));
                    }
                }

            }
        }
Revit 2019, AMEP 2019 64bit Win 10

klahie

  • Guest
Re: Block-Functions (Select, Explode, etc.)
« Reply #7 on: April 16, 2012, 05:21:29 PM »
Okay, and how do I select this ObjectIdCollection in my drawing?

Something like
Code: [Select]
ed.SetImpliedSelections(ids);?

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block-Functions (Select, Explode, etc.)
« Reply #8 on: April 17, 2012, 07:41:12 AM »
When you say "select", what are you wanting to do with them?
Revit 2019, AMEP 2019 64bit Win 10

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block-Functions (Select, Explode, etc.)
« Reply #9 on: April 17, 2012, 08:23:00 AM »
Are you trying to 'highlight' or create a selectionSet of the BlockReferences that BlockTableRecord names are selected in your ListBox?

klahie

  • Guest
Re: Block-Functions (Select, Explode, etc.)
« Reply #10 on: April 17, 2012, 08:51:53 AM »
Got the selection working. This was what I wanted to do:

Code: [Select]
public void selectBlock2(string blockName)
{
Database db = HostApplicationServices.WorkingDatabase;
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
TypedValue[] tvs = new TypedValue[] {
new TypedValue(0, "INSERT"),
new TypedValue(2, blockName)
};
SelectionFilter sf = new SelectionFilter(tvs);
PromptSelectionResult psr = ed.SelectAll(sf);
if (psr.Status == PromptStatus.OK)
{
    ed.SetImpliedSelection(psr.Value.GetObjectIds());
}
}

But the block-explosion is still not working. I tried it like this:
Code: [Select]
public void explodeBlock(string blockName)
{
   Editor ed = doc.Editor;
   using (tr = db.TransactionManager.StartTransaction())
   {
      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false, true);
      if (bt.Has(blockName)) {
         ObjectId btrid = bt[blockName];
         if (!btrid.IsEffectivelyErased) {
            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrid, OpenMode.ForRead, false, true);

            ObjectIdCollection brefIds = btr.GetBlockReferenceIds(true, false);

            foreach (ObjectId objid in brefIds) {
               BlockReference br = (BlockReference)tr.GetObject(objid, OpenMode.ForWrite);
               br.ExplodeToOwnerSpace();
            }
         }
      }
   }
}

The last function I should implement is a Copy/Paste-Block function. For paste there should be a cursor to set the insertpoint for the block (like the usual insert in AutoCAD). How complex would this be?

Greets
Klaus

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block-Functions (Select, Explode, etc.)
« Reply #11 on: April 17, 2012, 10:29:04 AM »
Looks like your missing tr.Commit() at the end of your using statement.

For the Copy/Paste part search for WblockCloneObjects or DeepCloneObjects in these forums.
Revit 2019, AMEP 2019 64bit Win 10

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Block-Functions (Select, Explode, etc.)
« Reply #12 on: April 17, 2012, 08:49:20 PM »
Quote
Code - C#: [Select]
  1. public void explodeBlock(string blockName)
  2. {
  3.    Editor ed = doc.Editor;
  4.    using (tr = db.TransactionManager.StartTransaction())
  5.    {
  6.  
  7. //>>>>>>>>>>>>

The variables named doc and db appear to be declared in an outer scope here
... while the selectBlock2 method declares them in it's scope.
This difference can lead to difficulty debugging code ... especially  (as in this case) the reader does not have ALL the code.

I haven't looked at the functionality of the code.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.