January 31, 2008

Toggling Plot Style Display in a Layout

A request in a thread in the AutoCAD® Architecture Customization Discussion Group for a way to be able to turn on or turn off the display of plot styles on a layout tab without having to open the Page Setup dialog got me thinking the other night. It occurred to be that this would be a handy routine to have, now that the tabs can be hidden in more recent versions of AutoCAD and AutoCAD Architecture, taking away the quick right-click access to the Page Setup command. It also offered me the opportunity to begin to become familiar with the "new" VL functions in AutoLISP, which became available quite some time ago, right around the time that I found myself with less time to spend writing LISP routines. As it turned out, I got a rather limited exposure to the VL commands, but I was able to make use of a few of them to change the current status of the display of plot styles on a layout tab. I posted my first version of that routine in a reply to the previously mentioned thread, and thought I would share the code here.

(defun C:PST ( ; No arguments.
acadDocument ; Holds reference to the active AutoCAD drawing object.
acadLayout ; Holds reference to the active Layout object.
acadObject ; Holds reference to the AutoCAD object.
showPStyles ; Holds current status of PlotStyle display on the active Layout.
) ;_ End arguments & local variables.
(cond ; Cond A
((= (getvar "TILEMODE") 1) ; Model tab is active, abort command.
"C:PST is meant for use on a Layout tab, not on the Model tab."
"\nPlease change to a Layout tab and try again."
) ;_ End strcat.
) ;_ End alert.
) ;_ End condition A1.
(T ; Condition A2.
(vl-load-com) ; Load "vl" functions, if not already loaded.
acadObject (vlax-get-acad-object)
acadDocument (vlax-get-property acadObject 'ActiveDocument)
acadLayout (vlax-get-property acadDocument 'ActiveLayout)
showPStyles (vlax-get-property acadLayout 'ShowPlotStyles)
) ;_ End setq.
(if (= showPStyles :vlax-true)
(vlax-put-property acadLayout 'ShowPlotStyles :vlax-false)
(prompt "\nThe display of plot styles has been turned off. ")
) ;_ End progn.
(vlax-put-property acadLayout 'ShowPlotStyles :vlax-true)
(prompt "\nThe display of plot styles has been turned on. ")
) ;_ End progn.
) ;_ End if.
(vlax-release-object acadLayout)
(vlax-release-object acadDocument)
(vlax-release-object acadObject)
(command "_.REGENALL") ; Regenerate the screen graphics.
) ;_ End condition A2.
) ;_ End cond A.
) ;_ End C:PST.

The VL functions allow you to access the ActiveX object model (just like VBA!) in a LISP routine. Never having had the time to truly master VBA (and realizing that for ease of use, a LISP routine to run the VBA code would probably be needed anyway), for this relatively simple task it seemed to me that writing the entire thing in LISP was the better way to go. The vlax-get-acad-object function is used to get the AutoCAD "object" and save it to the acadObject variable. The vlax-get-property function is then used to get properties of the AutoCAD object and its subobjects:
  • The ActiveDocument property of the AutoCAD object is the currently active drawing object.
  • The ActiveLayout property of the currently active document is the currently active layout (or model) tab object.
  • The ShowPlotStyles property of a layout tab (not relevant for the Model tab, which can not display plot styles) indicates whether or not the display of plot styles is enabled for that layout tab. A value of :vlax-true indicates that the display is turned on; :vlax-false indicates that the display is turned off.
In developing the routine, I assigned the intermediate objects to variables, along with the value of the ShowPlotStyles property, so that I could see what sort of values each had and could figure out what my test string should be. After posting the routine, it occurred to me that I could have omitted assigning any of those values to a variable, and simply nested everything in the IF statement condition. I am not certain that would substantially improve performance, however, and felt that leaving it as written would be easier for me to decipher, should that be necessary in the future, after I have forgotten the details of how I wrote this routine.

I am also not certain if releasing the objects is necessary, given that the variables are local to the routine and should "go away" after it has run. Perhaps my next foray into VL territory will lead me to a better understanding of that.


JTB World said...

Nice. From what I understand vlax-release-object is only needed to release objects that are from outside of AutoCAD. For example if you automate Excel.

Anonymous said...

Nice, thanks!