Hi all & happy holidays
My question is somewhat of a challenge too. I currently insert certain dynamic block into drawings with a short function that first inserts the specified dynamic block and then immediately changes the visibility state to one specified as an argument to the function.
I'm wondering if it is possible / better / faster to somehow insert the dynamic block with the decided visibility state simultaniusly. I've been amazed by many capabilities of VL so I wouldn't at be suprised if this can be done. (the dynamic blocks I'm inserting could have many multiples in the drawing but I need this method to only effect the one being inerted at the time the function is called. I currently use entlast to decide which one is being inserted.)
What I'm currently doing is working fine, this question is only for fun for those of us working Christmas Eve 😞 No Worries.
Thank you to all who choose to participate.
Solved! Go to Solution.
Solved by Lee_Mac. Go to Solution.
The Visibility State would need to be altered after the block reference is inserted, since the ActiveX methods pertaining to the dynamic block properties would need a pointer to the relevant VLA-Object on which to operate.
I would personally suggest using the ActiveX InsertBlock method, and then perhaps using my Set Visibility State function with the VLA Block Reference Object returned by this method.
Lee
@mid-awe wrote:
Perhaps, inserting to 0,0,0 and then entering the vl-move, so that the user experiences the illusion of the method I was describing. (Would that slow the process a lot?) The illusion being as if the block the user is inserting is as intended without first viewing the default visibility state.
Using the MOVE command is a good idea (the standard AutoCAD command would need to be used instead of the ActiveX move method to achieve the 'ghosting' of the objects whilst the user picks a new insertion point), however, you would still see the original block inserted at the initial insertion point (whether that be 0,0 or elsewhere), and a rubberband between the ghosted block being moved and the original block (as you see with the standard MOVE command).
To offer an alternative approach, please try the attached program and let me know what you think
Lee
Slick Lee. A very nice "universal" approach. That certainly covers all bases.
I was thinking more along the lines of being able to use in CUI menu such as an argument (dynblkins "DBLOCKNAME" "DBLOCKVISSTATE"), which requires knowledge of the block and available visibility states. you pulled the rug from under me with this. Now the conundrum, I love universal solutions. Now what?
"Think, think, think" -Winnie, the POO
@mid-awe wrote:Slick Lee. A very nice "universal" approach. That certainly covers all bases.
Thank you mid-awe, I'm glad you like it!
@mid-awe wrote:I was thinking more along the lines of being able to use in CUI menu such as an argument (dynblkins "DBLOCKNAME" "DBLOCKVISSTATE"), which requires knowledge of the block and available visibility states. you pulled the rug from under me with this. Now the conundrum, I love universal solutions. Now what?
"Think, think, think" -Winnie, the POO
As you've correctly noted, in order to supply arguments to an appropriate function, you would need prior knowledge of the dynamic block structure - in particular, the names of the defined visibility states.
However, the above point aside, the various program prompts could be replaced with function arguments, and for this I would propose the following function:
;; Insert With Visibility State - Lee Mac ;; Provides an interface through which the user can insert a dynamic block ;; with a preselected visibility state. ;; blk - [str] Block name, filename or full filepath ;; vis - [str] Visibility State to set on insertion ;; Returns: [vla] Inserted VLA block reference object, else nil if unsuccessful (defun LM:insertwithstate ( blk vis / bse cmd def ent ext new obj pth rtn tmp ) (setq pth (vl-string-translate "/" "\\" (vl-filename-directory blk)) ext (cond ((vl-filename-extension blk)) (".dwg")) bse (vl-filename-base blk) ) (if (/= "" pth) (setq pth (strcat pth "\\")) ) (cond ( (not (or (and (tblsearch "block" bse) (setq blk bse) ) (setq blk (findfile (strcat pth bse ext))) ) ) (prompt (strcat "\nBlock \"" bse "\" not found.")) ) ( (progn (setq obj (vlax-invoke (vlax-get-property (LM:acdoc) (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace ) ) 'insertblock '(0.0 0.0 0.0) blk 1.0 1.0 1.0 0.0 ) ) (vla-put-visible obj :vlax-false) (= :vlax-false (vla-get-isdynamicblock obj)) ) (vla-delete obj) (prompt (strcat "\nBlock \"" bse "\" is not dynamic.")) ) ( (null (LM:setvisibilitystate obj vis)) (vla-delete obj) (prompt (strcat "\nUnable to set visibility state of block \"" bse "\" to \"" vis "\"." ) ) ) ( (setq tmp 0) (while (tblsearch "block" (setq blk (strcat "tmp" (itoa (setq tmp (1+ tmp)))) ) ) ) (vla-put-visible (car (vlax-invoke (LM:acdoc) 'copyobjects (list obj) (setq def (vlax-invoke (vla-get-blocks (LM:acdoc)) 'add '(0.0 0.0 0.0) blk ) ) ) ) :vlax-true ) (vla-delete obj) (setq ent (entlast) cmd (getvar 'cmdecho) ) (setvar 'cmdecho 0) (princ "\nSpecify insertion point: ") (if (and (vl-cmdf "_.-insert" blk "_S" 1.0 "_R" 0.0 "\\") (not (eq ent (setq ent (entlast)))) (setq new (vlax-ename->vla-object ent)) (= "AcDbBlockReference" (vla-get-objectname new)) ) (progn (setq rtn (car (vlax-invoke new 'explode))) (vla-delete new) ) ) (setvar 'cmdecho cmd) (vl-catch-all-apply 'vla-delete (list def)) ) ) rtn ) ;; Get Visibility Parameter Name - Lee Mac ;; Returns the name of the Visibility Parameter of a Dynamic Block (if present) ;; blk - [vla] VLA Dynamic Block Reference object ;; Returns: [str] Name of Visibility Parameter, else nil (defun LM:getvisibilityparametername ( blk / vis ) (if (and (vlax-property-available-p blk 'effectivename) (setq blk (vla-item (vla-get-blocks (vla-get-document blk)) (vla-get-effectivename blk) ) ) (= :vlax-true (vla-get-isdynamicblock blk)) (= :vlax-true (vla-get-hasextensiondictionary blk)) (setq vis (vl-some '(lambda ( pair ) (if (and (= 360 (car pair)) (= "BLOCKVISIBILITYPARAMETER" (cdr (assoc 0 (entget (cdr pair)))) ) ) (cdr pair) ) ) (dictsearch (vlax-vla-object->ename (vla-getextensiondictionary blk)) "acad_enhancedblock" ) ) ) ) (cdr (assoc 301 (entget vis))) ) ) ;; Set Dynamic Block Visibility State - Lee Mac ;; Sets the Visibility Parameter of a Dynamic Block to a specific value ;; blk - [vla] VLA Dynamic Block Reference object ;; val - [str] Visibility State Parameter value ;; Returns: [str] New value of Visibility Parameter, else nil (defun LM:SetVisibilityState ( blk val / vis ) (if (and (setq vis (LM:getvisibilityparametername blk)) (member (strcase val) (mapcar 'strcase (LM:getdynpropallowedvalues blk vis)) ) ) (LM:setdynpropvalue blk vis val) ) ) ;; Active Document - Lee Mac ;; Returns the VLA Active Document Object (defun LM:acdoc nil (eval (list 'defun 'LM:acdoc 'nil (vla-get-activedocument (vlax-get-acad-object)) ) ) (LM:acdoc) ) (vl-load-com) (princ)
You can call the above function with the name / filename / filepath of the block to be inserted, and the name of the visibility state to be set prior to block insertion, e.g.:
(LM:insertwithstate "myblock" "my state")
(LM:insertwithstate "myblock.dwg" "my state")
(LM:insertwithstate "C:\\myfolder\\myblock.dwg" "my state")
The function will then return the VLA-Object representation of the inserted block, if successful.
Thank you for this thread mid-awe, I have enjoyed experimenting with this function!
Lee
This has been real fun Lee. Great stuff for kissing away time on this joyous day
You've again proven your mastery of customizing AutoCAD. Salute to you Sir. (I'm afraid that is all the authority I have toward declairing you king of the day )
Thank you for these lessons, they have been enlightening.
Oh, and thank you for taking the bait and having a little fun with me.
Am I missing something here? When I try Lee's lisp routine, it comes back stating that "Selected block in not dynamic". I am selecting our standard company blocks that have 6-8 visibility states. I really like the sounds of the changes mid-awe suggested, but also get the error "block" is not dynamic.nil.
Seems the LM:getdynpropallowedvalues & LM:setdynpropvalue functions are missing?
(defun LM:SetVisibilityState ( blk val / vis )
(if
(and
(setq vis (LM:getvisibilityparametername blk))
(member
(strcase val)
(mapcar 'strcase (LM:getdynpropallowedvalues blk vis))
)
)
(LM:setdynpropvalue blk vis val)
);if
);defun
A part of Lees code is this:
( (progn (setq obj (vlax-invoke (vlax-get-property (LM:acdoc) (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace ) ) 'insertblock '(0.0 0.0 0.0) blk 1.0 1.0 1.0 0.0 ) ) (vla-put-visible obj :vlax-false) (= :vlax-false (vla-get-isdynamicblock obj)) ) (vla-delete obj) (prompt (strcat "\nBlock \"" bse "\" is not dynamic.")) )
I understand it in this way:
The problem is now: if it is dynamic (like moving, rotating), but without visibility, then the invisible block remains in the drawing.
Am I right - or wrong?
Regards
Thanks for posting! I have a block I'm working on turning into a toolbar command and this is almost perfect for it. The only thing missing for me would be to allow the user to rotate the block after placing it. I'm new to lisp routines and I can see the general place in the code where the insertion angle is defined, but I don't know how to allow the user to define it. I can see this post is pretty old, but I hope someone's still paying attention.
For handling the rotation, I can recommend one of these two solutions:
find this line
(vl-cmdf "_.-insert" blk "_S" 1.0 "_R" 0.0 "\\")
and replace it with
(vl-cmdf "_.-insert" blk "_S" 1.0 "_R" PAUSE "\\")
(It will result with the user being prompted to enter a rotation.) I don't prefer this option because first it requires altering Lee's code, and second, I prefer to use my mouse to rotate visually.
I prefer to call this function:
(defun RotateLastEnt (/ BASPNT ) (PRINC "\n\t =>> Specify Rotation: ") (SETQ BASPNT (CDR (ASSOC 10 (ENTGET (ENTLAST))))) (vl-cmdf "rotate" (ENTLAST) "" BASPNT PAUSE) )
just following a call to Lee's,
(LM:insertwithstate "C:\\myfolder\\myblock.dwg" "my state")
(RotateLastEnt)
It should work as expected.
Hope it helps.
Thanks mid-awe!
I almost have your second solution working for me, but something's not quite right.
Under the toolbar button macro I have the following typed in:
^C^C(lm:insertwithstate "M:/Adam/Library/CAD/Blocks/Piping/pipe fitting.dwg" "Pipe Down")
(rotatelastent)
But the rotate command doesn't run. I can get them each to run on their own, but not together. Am I missing something?
I'm using AutoCAD 2015 if that makes a difference.
Try entering the code on one line with out the
^C^C
Like this:
(lm:insertwithstate "M:/Adam/Library/CAD/Blocks/Piping/pipe fitting.dwg" "Pipe Down")(rotatelastent)
If that doesn't work for you then we can add the "RotateLastEnt" call at the end of Lee's code.
@Anonymous wrote:Couldn't get it to work with your first suggestion, but your second worked for me. Thanks for the help!
You are welcome. I am glad that I could help.
Lee,
I got the Lisp to work with a Macro I've added to my Ribbon (see below). What I'd like to be able to do now is prompt to enter visability/size required.
I've tried adding a pause '\' (backslash) or even double quotes (""), but neither worked. Is there another way of achieving this?
^C^Cucs;named;world;-layer;m;"ZE-TRIMBLE SLEEVE";;(load "L:/_BIM Standards/Acad MEP Support/Lisp Routines/DynBlockVisState.lsp");(LM:insertwithstate "L:/_MMC TOOL PALETTES/TRIMBLE/TRIMBLE SYMBOL LIBRARY/MM-TRIMBLE SLEEVE.dwg" "");
Thanks in advance
David Ortega