Author Topic: Prevent Block Explode  (Read 10073 times)

0 Members and 1 Guest are viewing this topic.

Jeff H

  • Needs a day job
  • Posts: 6150
Prevent Block Explode
« on: December 13, 2010, 05:25:03 PM »
I threw this idea out to someone at Autodesk fourms and decided to code real quick  http://forums.autodesk.com/t5/NET/how-top-revent-a-block-from-explode-using-vb-net/td-p/2850744

The basic idea was setting the blocks explodable property to false. That cadMeUp suggested

And I think the only way to change that is through the block editor so added a event handler for CommandEnded and check for "BCLOSE" and if so change explodable property back to false.

Code: [Select]
   [CommandMethod("BlockBlock2")]
         public void BlockBlock2()
         {
            Application.DocumentManager.MdiActiveDocument.CommandEnded += new CommandEventHandler(blkEdClosed);
           blockNames.Add("C");
         }
       

         static void blkEdClosed(object sender, Autodesk.AutoCAD.ApplicationServices.CommandEventArgs e)
         {

             if (e.GlobalCommandName == "BCLOSE")
             {
                 Document doc = Application.DocumentManager.MdiActiveDocument;
                 Database db = doc.Database;

                 using (Transaction trx = db.TransactionManager.StartTransaction())
                 {
                     BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;

                     foreach (string bName in blockNames)
                     {
                         if (bt.Has(bName))
                         {
                             ObjectId btrObjId = bt["C"].GetObject(OpenMode.ForRead).ObjectId;
                             BlockTableRecord btr = (BlockTableRecord)btrObjId.GetObject(OpenMode.ForRead);
                             if (btr.Explodable == true)
                             {
                                 btr.UpgradeOpen();
                                 btr.Explodable = false;
                             }

                         }
                     }

                     trx.Commit();
                 }
             }
         }


         static void BlockEditorOpen(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs  e)
         {

             if (e.Name == "BLOCKEDITOR" && e.Changed == true)
             {
                 if ((int)Application.GetSystemVariable("BLOCKEDITOR") == 0)
                 {
                     Document doc = Application.DocumentManager.MdiActiveDocument;
                     Database db = doc.Database;

                     using (Transaction trx = db.TransactionManager.StartTransaction())
                     {                   
                         BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;

                         foreach (string bName in blockNames)
                         {
                             if (bt.Has(bName))
                             {
                                 ObjectId btrObjId = bt["C"].GetObject(OpenMode.ForRead).ObjectId;                                 
                                 BlockTableRecord btr = (BlockTableRecord)btrObjId.GetObject(OpenMode.ForRead);
                                 if (btr.Explodable == true)
                                 {
                                     btr.UpgradeOpen();
                                     btr.Explodable = false;
                                 }
                               
                             }
                         }               

                         trx.Commit();
                     }
                 }

             }           

         }

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Prevent Block Explode
« Reply #1 on: December 13, 2010, 07:00:32 PM »
Just a note, but you can change the explode'ability of a block by code also, so if you really wanted a fool proof method, then I would think that you would have to put an event on the block itself.  If anything about the block changes, then fire the event, and check if the block's explode'ability has changed.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Prevent Block Explode
« Reply #2 on: December 13, 2010, 07:02:38 PM »

but of course, the events will only fire if the code is loaded :)
.. so any solution will only work if the user wants it to work.
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.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Prevent Block Explode
« Reply #3 on: December 13, 2010, 07:17:39 PM »
Just a note, but you can change the explode'ability of a block by code also, so if you really wanted a fool proof method, then I would think that you would have to put an event on the block itself.  If anything about the block changes, then fire the event, and check if the block's explode'ability has changed.


I did not go that path because of the overhead of event handlers
And If I am corrrect about the only to change it is throught the BlockEditor and "BCLOSE" is always called when the block editor closes then this should work.


but of course, the events will only fire if the code is loaded :)
.. so any solution will only work if the user wants it to work.

And the part of it demand loading and taking away the rights of the user not to change the installation


Here is another I started messing with that makes the blocks go invisible when the explode command starts.
Definetly not fool proof. And needs work, It sounded better in my head and thrown together quickly.

Code: [Select]
     ObjectIdCollection btrBlkObjIds = new ObjectIdCollection();
        public static ObjectIdCollection brefObjIds = new ObjectIdCollection();

        [CommandMethod("BlockBlock")]
        public void BlockBlock()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction trx = db.TransactionManager.StartTransaction())
            {

                ObjectIdCollection btrBlkObjIds = new ObjectIdCollection();
                BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
               
                if (bt.Has("C"))
                {
                    ObjectId btrObjId = bt["C"].GetObject(OpenMode.ForRead).ObjectId;
                    btrBlkObjIds.Add(btrObjId);
                     BlockTableRecord btr = (BlockTableRecord)btrObjId.GetObject(OpenMode.ForRead);
                   
                     ObjectIdCollection blkRefs =  btr.GetBlockReferenceIds(true, true);

                     foreach (ObjectId brefId in blkRefs)
                    {
                        brefObjIds.Add(brefId);
                    }
                }


                doc.CommandWillStart += new CommandEventHandler(ExplodeStart);
               
                trx.Commit();
               
            }

        }


         static void ExplodeStart(object sender, CommandEventArgs e )
        {
           
                Document doc = Application.DocumentManager.MdiActiveDocument;
                Database db = doc.Database;
                Editor ed = doc.Editor;


                if (e.GlobalCommandName == "EXPLODE")
                {
                    doc.CommandEnded += new CommandEventHandler(ExplodeEnd);
                    doc.CommandCancelled += new CommandEventHandler(ExplodeEnd);
                    ed.SelectionAdded += new SelectionAddedEventHandler(SelectionAdd);
                 
                    using (Transaction trx = db.TransactionManager.StartTransaction())
                    {

                        foreach (ObjectId brefId in brefObjIds)
                        {
                            Entity ent = brefId.GetObject(OpenMode.ForWrite) as Entity;
                           
                            ent.Visible = false;
                        }


                        trx.Commit();
                    }
                }

        }

         static void ExplodeEnd(object sender, CommandEventArgs e)
         {

           
                 Document doc = Application.DocumentManager.MdiActiveDocument;
                 Database db = HostApplicationServices.WorkingDatabase;
                 Editor ed = doc.Editor;

                 doc.CommandEnded -= new CommandEventHandler(ExplodeEnd);
                 doc.CommandCancelled -= new CommandEventHandler(ExplodeEnd);
                 ed.SelectionAdded -= new SelectionAddedEventHandler(SelectionAdd);

                 using (Transaction trx = db.TransactionManager.StartTransaction())
                 {

                     foreach (ObjectId brefId in brefObjIds)
                     {
                         Entity ent = brefId.GetObject(OpenMode.ForWrite) as Entity;
                         ent.Visible = true;
                     }

                     trx.Commit();
                 }

                 ed.UpdateScreen();
               
         }


         static void SelectionAdd(object sender, SelectionAddedEventArgs e)
         {
         
             Database db = HostApplicationServices.WorkingDatabase;
             using (Transaction trx = db.TransactionManager.StartTransaction())
             {

                 ObjectId[] selectId = e.AddedObjects.GetObjectIds();

                 if (brefObjIds.Contains(selectId[0]))
                 {
                     Application.SetSystemVariable("PICKFIRST", 0);
                 }
                 else
                 {
                     Application.SetSystemVariable("PICKFIRST", 1);
                 }
                 trx.Commit();
             }
         }


         


Left this off the first one

Code: [Select]
public static List<string> blockNames= new List<string>();

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Prevent Block Explode
« Reply #4 on: December 13, 2010, 07:30:17 PM »
Just a note, but you can change the explode'ability of a block by code also, so if you really wanted a fool proof method, then I would think that you would have to put an event on the block itself.  If anything about the block changes, then fire the event, and check if the block's explode'ability has changed.


I did not go that path because of the overhead of event handlers
And If I am corrrect about the only to change it is throught the BlockEditor and "BCLOSE" is always called when the block editor closes then this should work.

<snip>

That is what I'm saying.  Use this code ( below ).  It will change the ability to explode the block, even with your code running.

Code: [Select]
(vla-put-explodable (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (cdr (assoc 2 (entget (car (entsel "\n Select block.")))))) :vlax-true)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Prevent Block Explode
« Reply #5 on: December 13, 2010, 07:40:10 PM »

Code: [Select]
(vla-put-explodable (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (cdr (assoc 2 (entget (car (entsel "\n Select block.")))))) :vlax-true)

That is that smart people stuff. I get scared and confused when I see Lisp, but I at least want to be able to understand it before I start going the Lisp fourm and stealing it.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Prevent Block Explode
« Reply #6 on: December 14, 2010, 01:20:23 AM »

Code: [Select]
(vla-put-explodable (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (cdr (assoc 2 (entget (car (entsel "\n Select block.")))))) :vlax-true)

That is that smart people stuff. I get scared and confused when I see Lisp, but I at least want to be able to understand it before I start going the Lisp fourm and stealing it.

Didn't get a lot of sleep last night, so I'm off to bed now, but if no one explains it before tomorrow, I'll explain what the code is doing, step by step.  Basically it is just setting the exploade'ability of a selected block to true ( allowing it to be exploded ).
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Prevent Block Explode
« Reply #7 on: December 14, 2010, 11:36:29 AM »
Hope this makes it clearer what the code is doing.

Code: [Select]
(vla-put-explodable     ;  the property to set
    (vla-item           ;  a way to get something within a collection
        (vla-get-blocks ;  the collection ( table ) of block definitions
            (vla-get-activedocument     ;  the active drawing
                (vlax-get-acad-object)  ;  the current session of autocad
            )
        )
        (cdr            ;  the rest of the items in a list, excluding the first one
            (assoc      ;  returns the list that matches the arguement, in a associated list of lists
                2       ;  the dxf code for name
                (entget ;  gets the dxf code list of the entity
                    (car    ;  gets the first item in a list
                        (entsel "\n Select block.")     ;  selects a single entity, non-nested
                    )
                )
            )
        )               ;  this whole section just gets the name of the block selected
    )                   ;  this whole section gets the blocks definition ( BlockTableRecord ) from the block collection ( BlockTable )
    :vlax-true          ;  the value we want to set the property
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Prevent Block Explode
« Reply #8 on: December 14, 2010, 01:35:36 PM »
Thanks alot!!!!

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Prevent Block Explode
« Reply #9 on: January 15, 2011, 11:43:22 AM »
what about setting the currentDrawing to explodable?  I have hundreds of blocks I just inherited that need that property changed
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Prevent Block Explode
« Reply #10 on: January 15, 2011, 12:12:38 PM »
what about setting the currentDrawing to explodable?  I have hundreds of blocks I just inherited that need that property changed


I am not sure about setting the drawing but should not take long to iterate through a 100

This prints out the block name and its Explodable property then changes the value and prints it

Code: [Select]
[CommandMethod("ChangeExplodableProperty")]
        public void ChangeExplodableProperty()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            using (Transaction trx = db.TransactionManager.StartTransaction())
            {

                BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
                foreach (ObjectId objId in bt)
                {
                    BlockTableRecord btr = (BlockTableRecord)objId.GetObject(OpenMode.ForRead);

                    if (!btr.IsLayout)
                    {
                        ed.WriteMessage("\n" + btr.Name + " Explodable property is set to " + btr.Explodable.ToString());
                        btr.UpgradeOpen();
                        btr.Explodable = !btr.Explodable;
                        ed.WriteMessage("\n" + btr.Name + " Explodable property has changed to " + btr.Explodable.ToString());
                    }
                }


                trx.Commit();
            }
        }

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Prevent Block Explode
« Reply #11 on: January 17, 2011, 08:23:53 AM »
that works for the blocks IN the drawing, but what about the drawing itself?  meaning, the file that gets inserted as a block needs the property set
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

vegbruiser

  • Guest
Re: Prevent Block Explode
« Reply #12 on: January 18, 2011, 08:40:16 AM »
Hi Tim (going back to your LISP sample),

How would I make that work in AutoCAD 2009/2011? I've tried adding it to a .lsp file provided by a colleague, but can't figure out the correct syntax to call it.

Thanks,

Alex.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Prevent Block Explode
« Reply #13 on: January 18, 2011, 11:06:27 AM »
Hi Tim (going back to your LISP sample),

How would I make that work in AutoCAD 2009/2011? I've tried adding it to a .lsp file provided by a colleague, but can't figure out the correct syntax to call it.

Thanks,

Alex.

Right now you would just copy / paste it to the command line.  If you want to make it a callable command, then you need to wrap the whole function in a ' defun ' call like so:

Code: [Select]
(defun c:MakeExplodable ()

    (vla-put-explodable     ;  the property to set
        (vla-item           ;  a way to get something within a collection
            (vla-get-blocks ;  the collection ( table ) of block definitions
                (vla-get-activedocument     ;  the active drawing
                    (vlax-get-acad-object)  ;  the current session of autocad
                )
            )
            (cdr            ;  the rest of the items in a list, excluding the first one
                (assoc      ;  returns the list that matches the arguement, in a associated list of lists
                    2       ;  the dxf code for name
                    (entget ;  gets the dxf code list of the entity
                        (car    ;  gets the first item in a list
                            (entsel "\n Select block.")     ;  selects a single entity, non-nested
                        )
                    )
                )
            )               ;  this whole section just gets the name of the block selected
        )                   ;  this whole section gets the blocks definition ( BlockTableRecord ) from the block collection ( BlockTable )
        :vlax-true          ;  the value we want to set the property
    )
    (princ)
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

vegbruiser

  • Guest
Re: Prevent Block Explode
« Reply #14 on: January 18, 2011, 12:19:55 PM »
I'm getting an error when I run this in both AutoCAD (Mechanical) 2011 & AutoCAD (Civil 3d) 2009:



Thoughts?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Prevent Block Explode
« Reply #15 on: January 18, 2011, 12:22:42 PM »
Add the line ' (vl-load-com) ' as the first line under the defun.  That will load the ActiveX Arx, so that lisp can interact with ActiveX ( no matter how many times you call it, the arx will only be loaded once ).  Sorry about that.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

ronjonp

  • Needs a day job
  • Posts: 7527
Re: Prevent Block Explode
« Reply #16 on: January 18, 2011, 12:24:33 PM »
Add (vl-load-com).

** Too slow :lol:

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

vegbruiser

  • Guest
Re: Prevent Block Explode
« Reply #17 on: January 18, 2011, 12:29:58 PM »
Add the line ' (vl-load-com) ' as the first line under the defun.  That will load the ActiveX Arx, so that lisp can interact with ActiveX ( no matter how many times you call it, the arx will only be loaded once ).  Sorry about that.
Thanks Tim, that does the trick. :)

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Prevent Block Explode
« Reply #18 on: January 18, 2011, 10:39:50 PM »
that works for the blocks IN the drawing, but what about the drawing itself?  meaning, the file that gets inserted as a block needs the property set

I tried it on drawing inserted and it worked.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Prevent Block Explode
« Reply #19 on: January 19, 2011, 12:04:02 PM »
that works for the blocks IN the drawing, but what about the drawing itself?  meaning, the file that gets inserted as a block needs the property set

I tried it on drawing inserted and it worked.


What he is talking about, is setting a drawing explode'ability, so that when it is inserted, the block that represents the drawing is/isn't explodable.  To do that, you have to change the explodable property of the model space's block table record of the drawing in question.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Prevent Block Explode
« Reply #20 on: January 21, 2011, 07:03:53 AM »
what about setting the currentDrawing to explodable?  I have hundreds of blocks I just inherited that need that property changed

I think I understand you will have to do like the previous code if file is already inserted in a drawing


Code: [Select]
    [CommandMethod("ChangeCurrentDrawingExplodableProperty")]
        public void ChangeCurrentDrawingExplodableProperty()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
           
            using (Transaction trx = db.TransactionManager.StartTransaction())
            {
                BlockTableRecord msBtr = SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(OpenMode.ForWrite) as BlockTableRecord;
                msBtr.Explodable = !msBtr.Explodable;
                trx.Commit();
               

            }

            doc.SendStringToExecute("QSAVE ", true, false, false);
        }


David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Prevent Block Explode
« Reply #21 on: January 21, 2011, 08:51:57 AM »
This is what i ended up doing
Code: [Select]
[CommandMethod("CEP")]
        public static void ChangeExplodableProperty()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            using (Transaction trx = db.TransactionManager.StartTransaction())
            {

                BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
                foreach (ObjectId objId in bt)
                {
                    BlockTableRecord btr = (BlockTableRecord)objId.GetObject(OpenMode.ForRead);

                    if (btr.Name == "*Model_Space")
                    {
                        ed.WriteMessage("\n" + btr.Name + " Explodable property is set to " + btr.Explodable.ToString());
                        btr.UpgradeOpen();
                        btr.Explodable = !btr.Explodable;
                        ed.WriteMessage("\n" + btr.Name + " Explodable property has changed to " + btr.Explodable.ToString());
                    }
                }


                trx.Commit();
            }
        }

I left the extra messages in the code from above so I could see it from the command line.  I wrote a script that processed the files.  It took about 5 minutes to process the files.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)