AfraLISP - Learn AutoLISP for AutoCAD productivity

Visual LISP Sample Files

by Kenny Ramage

This document supplements the code comments contained in the sample files that are included in Visual LISP. It details the uses for these files and the concepts they demonstrate.

This document expands on the code comments already included in the sample files that ship with Visual LISP. The following sections explain the important concepts that these sample files are meant to demonstrate.

Before reading further, please note that this document assumes you are already familiar with the Visual LISP Integrated Development Environment (IDE) and the AutoLISP programming language.

Visual LISP Sample Files

If for some reason you do not have the Visual LISP Sample files, you can download them from here.

Visual LISP contains a collection of sample LISP files that are located in <your Visual LISP directory>\Sample. These files range in complexity from basic AutoLISP to advanced techniques in implementing the Visual LISP connection to the AutoCAD ActiveX Object Model. You will also encounter examples that use the special ActiveX Extension functions included in the Visual LISP function library.

You should be able to find the following files in your \SAMPLE directory :

<your Visual LISP directory>\Sample

Sample
afact.lsp regarx.lsp
drawline.lsp regdump.lsp
drawline-with-errors.lsp sym-exp.lsp
grafun.lsp timestamp.lsp
hello.lsp tmatrix.lsp
image.lsp Unload-VL-app.lsp
LispData1.lsp yinyang.lsp
LispData2.lsp  

<your Visual LISP directory>\Sample\ActiveX

Active X
al-tst.lsp vla-tst.mkp
vla-tst.lsp vla-tst.prj
vla-tst.mkl  

<your Visual LISP directory>\Sample\Reactors

Reactors
acdbex.lsp a-mtext.lsp aap-reg.lsp
copyself.lsp ctie.lsp dimex.lsp
dumbells.lsp editex.lsp getparm.dcl
linkex.lsp objex.lsp pipe.lsp
sel-reac.lsp rctr.lsp rctr-tst.mkl
rctr-tst.mkp rctr-tst.prj reac-tst.prj
r-info.lsp r-init.lsp rolls.lsp
rsame.lsp rtie.lsp rtrans.lsp
rtransl.lsp rutils.lsp same-rcl.lsp
sel-reac.lsp toplevel.lsp getparm.lsp

Each of the following explanations includes a list of the functions in the sample files as well as the syntax you should use to call them from the Visual LISP Console prompt. However, function names preceded by a c: can be called from the AutoCAD command line as well. All other functions must be called from the Visual LISP Console prompt unless you explicitly export them to AutoCAD as native AutoLISP functions, at which point you could call them from the AutoCAD command line.

The executable function lists that accompany the sample file explanations follow the syntax as described here :

Example of a non-exported function :

functionA

Executable syntax :

(functionA arg1 arg2 etc…) (from the Visual LISP Console only)

Example of an exported function :

c:functionB

Executable syntax :

(c:functionB) (from the Visual LISP Console or AutoCAD command line)

functionB (from the AutoCAD Command Line only) This syntax will not be included later in this document; it should be understood as a feature of preceding function names with a "c:".

Visual LISP Samples

afact.lsp

This file defines two functions that use recursion to factorize an integer. Each function requires one argument which should be an integer between 1 and 31. For example, (fact1 5) returns 120 by calling fact2 which in turn calls fact1, each time decreasing the value of the argument by 1 and multiplying it by the product from the previous function’s return value.

The range of 1 to 31 is based on a limitation of the ability of AutoLISP and Visual LISP to process any value outside of its Integer data type range, a 32-bit signed value. The range is between -2,147,483,648 and 2,147,483,647 or -231 ³ X ³ (231 - 1).

However, with regard to the practice of recursion, the limitation on the depth of recursion for this routine is far more lenient. In the AutoLISP environment, these functions can reach a depth of 144; in the Visual LISP environment, these functions can reach a depth of 983. The maximum attainable depth varies by the complexity of the routine.

Executable functions :

fact1
fact2

Executable syntax :

(fact1 n)

The argument n is an integer between 1 and 31.

(fact2 n)

The argument n is an integer between 1 and 31.

drawline.lsp

This sample file is used throughout the documentation to demonstrate Visual LISP concepts and features. It is the corrected version of the drawline-with-errors.lsp file which this document describes next.

This routine defines a simple function that draws a line with the AutoCAD LINE command using the AutoLISP command function after it asks the user to specify a start point and end point. If the user does not pass valid coordinate values for the start point and end point prompts, the routine will return a predefined error message.

Executable functions :

drawline

Executable syntax :

(drawline)

drawline-with-errors.lsp

This file is the same as drawline.lsp, however, it contains deliberate errors. The focus of this routine is to provide the user with the opportunity to become familiar with Visual LISP debugging tools. This sample file is referenced in your online Help in :

Developing Programs With Visual LISP
Checking for Syntax Errors
Checking the Balance of Parentheses
Using Color Coding to Detect Syntax Errors

As explained earlier, this routine draws a line with the AutoCAD LINE command using the AutoLISP command function after it asks the user to specify a start point and end point. The user will first need to debug the program to make it functional. See Chapter 6 of your on-line Help documentation for information on Visual LISP’s debugging tools.

Executable functions :

drawline

Executable syntax :

(drawline)

grafun.lsp

This file contains two main functions that can be used to compare the speed of calling AutoCAD commands with the AutoLISP command function verses implementation of ActiveX methods. Both programs create a 3D mesh and return the time required to complete the task. The al-gf function uses AutoCAD commands to create the 3D mesh, and the vla-gf function uses ActiveX methods to create the 3D mesh.

You will need to make sure that the User Elapsed Timer is on (see the TIME command in your AutoCAD on-line Help).

Executable functions :

c:vla-gf (ActiveX methods)
c:al-gf (AutoCAD commands)

Executable syntax :

(c:vla-gf)
(c:al-gf)

Note: The first time an ActiveX function is executed, you may notice less of a speed improvement than expected because the environment may need to be initialized or AutoCAD may need to reclaim memory. Subsequent calls using that connection will be significantly faster than calling AutoCAD commands using the AutoLISP command function.

hello.lsp

This sample file demonstrates the difference between implicitly and explicitly exporting functions to AutoCAD and AutoLISP from the Visual LISP environment.

The c:hello command is a Command defined function ("c:") and is therefore implicitly exported to AutoLISP and can be called from the AutoCAD command line when loaded in Visual LISP.

The HELLO function passes an argument to a princ expression as the second part of a string that is printed at the command line. It is called by the hello-autocad function which is explicitly exported to AutoLISP using the vl-acad-defun function when loaded in Visual LISP.

A significant point that this routine demonstrates is that functions which are exported to AutoCAD or AutoLISP from Visual LISP are not functions at all. They are simply references to functions which exist as USUBR routines in the Visual LISP environment. For example, if you open and load hello.lsp in Visual LISP and then enter (type hello-autocad) at the AutoCAD command line, it will return EXRXSUBR. This signifies that hello-autocad is contained in an external ARX subroutine (in this case, vlide.arx). Therefore, when you call the hello-autocad function, it is not being executed in the AutoLISP environment; it is being executed in the Visual LISP environment.

Executable functions :

c:hello
hello-autocad
hello

Executable syntax :

(c:hello) (hello-autocad s) The "s" argument is the string the user passes to the function.
(hello s) The "s" argument is the string the user passes directly when calling the hello function or indirectly when calling the hello-autocad function. Note that (hello s) is only available from Visual LISP and not AutoLISP since it was neither implicitly or explicitly exported to AutoLISP.

image.lsp

This sample file demonstrates a workaround for a limitation involving the AutoCAD IMAGE command where you are not allowed to pass additional arguments when calling it with the AutoLISP command function within Visual LISP. As an alternative, this file demonstrates how a user can insert an image using ActiveX methods. A suggested example of executable syntax is included at the end of the image.lsp file.

Executable functions :

insert-image

Executable syntax :

(insert-image image_file_name insertion_point scale rotation)
For example :
(insert-image ".\\Textures\\3ds.tga" '(0.0 0.0 0.0) 1 0.0)

LispData1.lsp

This sample file demonstrates two examples of the ability of Visual LISP to add and remove non-graphical data in a drawing using Visual LISP vlax-ldata-xxx extension functions. These functions are advanced solutions to the standard procedures for adding and removing dictionary data.

Upon executing the function, the routine runs through two examples using the
vlax-ldata-xxx functions. The first example creates and stores data to key "KEY1" in the named object dictionary that it also creates called "MY-DICT". It then lists the data contained in the key and finishes by removing the key, but it does not remove the dictionary entry.

The second example creates a Circle object, associates it with key "KEY2" which the routine stores in the AutoCAD extension Dictionary (ACAD_XDICTIONARY), and lists the extension data which it stored in that key using the vlax-ldata-put function. It then proceeds to remove the key and finally deletes the Circle object.

Executable functions :

c:lispdata-test

Executable syntax :

(c:lispdata-test)

LispData2.lsp

Similar to the second section of LispData1.lsp, this sample file demonstrates the use of non-graphical data in a drawing by allowing the user to add or change the value of key "LDT" associated with a graphical object and located in the AutoCAD extension dictionary, using the vlax-ldata-xxx functions. The "LDT" key value is not set on a selected object until you run the routine once. Afterwards, you can use the routine to change the value associated with key "LDT" for that object.

Executable functions :

c:ldt

Executable syntax :

(c:ldt)

regarx.lsp

Please note that this description supplements the extensive comments contained in the Regarx.lsp file. Furthermore, it supersedes the comments in the source code on the function arguments which are incorrect.

The regarx.lsp sample file demonstrates how to register the Visual LISP IDE ARX application for demand loading by designated commands. It also provides a thorough explanation of the information necessary to implement this mechanism since the wrong information in any location of the registry can completely disable AutoCAD and possibly your operating system. Please back up your registry before running any commands that edit and change your registry entries.

Regarx.lsp also suggests code on how to unregister command demand loading. The register-VL-app function defined in this routine is a replica of Visual LISP’s vlax-reg-app function. With either of these functions, you will be able to register the Visual LISP IDE ARX application by designating the correct parameters for instructing AutoCAD to load the application on demand. The vlax-reg-app function is more general and can be used to register any application. Please see the Visual LISP documentation for a description of that function.

The register-VL-app function requires three arguments :

  1. app-rp - The application name: a key to be entered in the Registry. It will need to look like this: "SOFTWARE\\your_application_name"
  2. cmds - A quoted list of the commands which you designate for the demand loading of Vlide.arx when invoked (demand loading requires at least the 4 bit-code value to be set in the loadctrls parameter below).
  3. loadctrls - An integer flag that is equal to the sum of any combination of the following possibilities (from the ObjectARX Developer’s Guide) :
    0 No action taken (do not load the application).
    1 Load the application upon detection of proxy object.
    2 Load the application upon AutoCAD start-up.
    4 Load the application upon invocation of a command (defined in your cmds parameter).
    8 Load the application upon request by the user or another application.
    16 Do not load the application.

At the end of the file, you will find sample code that passes correct parameters to the register-VL-app function.

Executable functions :

register-vl-app

Executable syntax :

(register-vl-app "SOFTWARE\\your_app_name

'("[command name]" "[command name]" etc…)
[loadctrls]
)

For example to register Visual Lisp for demand loading :

register-vl-app (strcat "SOFTWARE\\Autodesk\\VisualLISP\\"

(_VLISP-VERSION))
'("Command1" "Command2")
4
)

regdump.lsp

This sample file provides an example of what can be accomplished with Visual LISP registry functions. The dump-registered-apps function prints out a registry database subtree for every application that is registered for demand loading in your AutoCAD Release 14 configuration.

One particular expression worth mentioning in the registry-tree-dump function (called by dump-registered-apps) is the second occurrence of the foreach function which contains a recursive call to registry-tree-dump. For each application that is registered for demand loading, there are three subkeys: Commands, Loader, and Name. This particular foreach expression applies the registry-tree-dump function to the string concatenation of each these three subkeys with the key for each of the registered applications to build and print out its subtree.

Executable functions :

dump-registered-apps

Executable syntax :

(dump-registered-apps)

sym-exp.lsp

This sample file defines two functions and uses the Visual LISP vl-acad-defun function to explicitly export them to the AutoLISP environment. Each of these two functions contain only one expression: a call to one Visual LISP symbol function. These symbol functions, vlisp-import-symbol and vlisp-export-symbol, are used to copy variables between the Visual LISP environment and the AutoLISP environment.

It is important to recognize that vl-acad-defun does not actually copy the function to AutoLISP. What it does is insert a reference to a function which exists as a USUBR routine in the Visual LISP environment. Therefore, although you call the function in AutoLISP, it is still executed in Visual LISP.

It is also important to notice that the vl-acad-defun expressions appear outside of the defined functions. If they were inside a non-command line function (no "c:"), it would be impossible to call either of the two functions in sym-exp.lsp if you compiled it as an ARX routine because the vl-acad-defun expressions could never be evaluated. Therefore, there are two rules to follow for explicitly exporting functions from an ARX routine without using a command line function to evaluate vl-acad-defun expressions :

  1. The vl-acad-defun expressions must be contained outside of the defined functions.
  2. You must select "Initialize in load time" in step 7 of the Application Wizard.

Code is included at the end of the sample file which can be used to test these functions from the AutoCAD command line.

Executable functions :

vlisp-to-acad-symbol
acad-to-vlisp-symbol

Executable syntax :

(vlisp-to-acad-symbol str) The str argument represents the name of a variable in quotes.
(acad-to-vlisp-symbol str)
The str argument represents the name of a variable in quotes.

timestamp.lsp

This program utilizes Editor Reactors to update a "time-stamp" text entity each time the user completes an instance of the PLOT command. Between the user pressing OK to begin the plotting procedure and AutoCAD spooling to the plotter, the Editor Reactor fires off the callback function which adds or updates a time-stamp text entity at a base point of 0,0,0.

This routine ties together several major concepts that other sample files cover individually:

The LDATA functions: Using vlax-ldata-put, it creates a global dictionary named "TIME-STAMP". This dictionary contains a key named "TEXT-OBJECT" whose value is the "time-stamp" text entity in the form of a Visual LISP ActiveX Object.

The REGISTRY functions: Using vlax-reg-app, entries are made in the Registry that associates vlide.arx (the primary Visual LISP module) or whichever ARX application from which you first ran the Register-Timestamp function in the AutoCAD application. The result is that until you run the Unregister-Timestamp function, the associated ARX application will automatically be launched the next time you start AutoCAD regardless of the drawing file that you open.

Furthermore, if you open the drawing in which you registered the Time-Stamp routine without the associated ARX loaded, you will receive a notification dialog informing you that the required ARX application is missing.

Please note that if you have already registered other commands to demand load the Visual LISP IDE, once Register-TimeStamp is run, those commands will no longer demand load the Visual LISP IDE. To return to other commands for demand loading of vlide.arx, you will have to re-register your command since the UnRegister-TimeStamp function merely turns off demand loading but leaves the registered application pointing to TimeStamp.

There is a workaround contained in this sample file which solves an "Object Open for Read" error which you may receive in connection with associating a callback function with the PLOT command to modify a graphical entity. The workaround is to add an additional graphical object to the drawing after creating the object which the callback function modifies. This behavior is documented and explained in the Visual LISP Readme file.

Executable functions :

c:register-timestamp
c:unregister-timestamp

Executable syntax :

(c:register-timestamp)
(c:unregister-timestamp)

tmatrix.lsp

Upon loading this sample file, it uses ActiveX function calls to draw a line. It then passes the line as a VLA Object along with a 4 x 4 transformation matrix to the vla-TransformBy function in order to rotate the line by 90 degrees. The file provides a total of five different matrices which can be used to rotate, move, or scale the line. To switch to a different matrix, change the variable called in the vla-TransformBy expression.

The use of matrices can be an excellent shortcut for manipulating graphical objects. Once created, the code for a matrix can easily be reapplied in other functions. The following documentation can be found in the Visual LISP online Help in the AutoLISP Function Reference under "nentselp" :

matrix

The first three columns of the matrix specify scaling and rotation. The fourth column is a translation vector.

The functions that use a matrix of this type treat a point as a column vector of dimension 4. The point is expressed in homogeneous coordinates, where the fourth element of the point vector is a scale factor that is normally set to 1.0. The final row of the matrix, the vector [M30 M31 M32 M33], has the nominal value of [0 0 0 1]; it is currently ignored by the functions that use this matrix format. In this convention, applying a transformation to a point is a matrix multiplication that appears as follows :

matrix

This multiplication gives us the individual coordinates of the point as follows :

matrix

As these equations show, the scale factor and the last row of the matrix have no effect and are ignored.

It is also noteworthy to mention a Visual LISP function called vlax-tmatrix which will accept a list of four lists representing a 4 x 4 transformation matrix (each sub-list contains four numbers). Specifically, it will process the lists, converting each number to a real and then returns the list in a format that is compatible with ActiveX requirements. The return can then be passed to the vla-TransformBy function.

Executable functions :

none

Executable syntax :

none - simply open and load the file.

unload-VL-app.lsp

When run from the AutoCAD command line, this program ends your Visual LISP session by unloading the vlide.arx module. Using Visual LISP functions not available in native AutoLISP, it creates a script file in the Windows System Temp directory with the Visual LISP application path and name (vlide.arx) along with the ARXUNLOAD command. It then uses the AutoCAD SCRIPT command to run the script.

Executable functions :

c:unvl

Executable syntax :

(c:unvl)

yinyang.lsp

This sample file is referenced throughout the Visual LISP online documentation. It is used as an example for debugging in Chapter 6, building applications in Chapter 7, and defining some functions in the Visual LISP AutoLISP Function Reference.

The routine asks for user input and draws a "Yin-Yang" symbol with basic AutoCAD geometry commands. Using the vl-acad-defun function, it explicitly exports the yinyang function as a native AutoLISP function so it can be called from within the AutoLISP environment in addition to the Visual LISP environment. Please see the section on sym-exp.lsp for more information on the use of the vl-acad-defun function.

Executable functions :

yinyang

Executable syntax :

(yinyang)

Visual LISP ActiveX Samples

vla-tst.prj

The ActiveX enabled sample programs demonstrate and test the speed enhancements with using the Visual LISP "vla-" function connections to the ActiveX Object Model versus the conventional AutoLISP function library. The al-tst function draws 2000 circles and changes their properties by means of the native AutoLISP functions. The vla-tst function completes the same test using Visual LISP VLAX functions and ActiveX methods and properties. You will need to make sure that the User Elapsed Timer is on (see the TIME command in your AutoCAD online Help).

To Run the test :

Build the vla-tst.arx application.

Note: Because the contents of MKP files are dependent on the directory structure of the system on which they originated, using the vla-tst.mkp file may generate error messages. It is recommended you select the "New Application Wizard" option under File > Make Application to create a new MKP file for your system.

There are several options for running the test command functions :

  • Load the resulting vla-tst.arx file in AutoCAD.
  • Run the ActiveX test using the vla-tst command.
  • Run the AutoLISP test using the al-tst command.
  • Run the native AutoLISP (uncompiled) test by unloading vla-tst.arx, loadingal-tst.lsp in AutoCAD and using the al-tst command.
  • Load the vla-tst.prj files into Visual LISP, run the uncompiled vla-tst or al-tst functions from the AutoCAD Command Line (or (c:vla-tst) and (c:al-tst) from the Visual LISP Console).

Each test prints the elapsed time for the procedure.

Executable functions :

c:vla-tst
c:la-tst

Executable syntax :

(c:vla-tst)
(c:la-tst)

Visual LISP Reactor Samples

Both of these reactor projects build upon Visual LISP code that is covered in the preceding sample files. However, these two sample projects implement Visual LISP’s reactor functions. At this time, the only other way to accomplish this in AutoCAD drawings is to write ObjectARX C++ applications.

If you are planning on implementing reactors within your Visual LISP code, there is important documentation you will need to review in addition to the sample code in these projects. Please carefully study Lessons 6 and 7 of the Visual LISP Garden Path Tutorial as well as Chapter 9 in the Visual LISP online Help documentation.

rctr-tst.prj

This project demonstrates how to create circles of equal radii which lie on a given curve, have an equal step in distance along the curve, and maintain these relationships when some of the objects are modified. The project also gives you examples of including DCL files in your compiled applications, registration of LISP defined commands, and self registration of an application or command.

Note: Before loading the Rctr-tst project into Visual LISP, you may need to set the Project properties Build Options for the FAS directory and TMP directories for the appropriate directory location on your hard drive. Otherwise you may receive this error when attempting to load the project: ; *** ERROR: in project RCTR-TST: the FAS Directory does not exist: FAS.

There is one minor change which you will need to make in order for this sample code to work. Please modify the following line in the Getparm.lsp file from :

(setq radius (get-radius (vlax-curve-getStartPoint aCurve)))

to :

(setq radius (get-radius-from-point (vlax-curve-getStartPoint aCurve)))

After loading the source files using the project file rctr-tst.prj, you can start the program using the RCTR-TST command. This command will prompt you to choose between dialog or prompt mode. In both cases, you will first select a circle that you have previously drawn before running this command. Next, you will be asked to determine the circles’ initial radius, their number and color, and finally if the reactors will be persistent. If you choose the persistent option, all reactors will be restored automatically in subsequent drawing sessions (persistent reactors are saved with the drawing, transient reactors are not). After the command ends, you can change the radii of the circles, the parameters of the curve, and move the circles or curve all in a dynamic relationship to each other.

The Rctr-tst project contains no c:RCTR-TST function defined in any of the source files. Instead, it uses the vlax-add-cmd function and registers this command in the registry.

Note: If you wish to compile this as an application, it is important to note that because the contents of MKP files are dependent on the directory structure of the system on which they originated, using the Rctr-tst.mkp file may generate error messages. It is recommended you select the "New Application Wizard" option under File Make Application to create a new MKP file for your system.

Executable functions :

rctr-tst

Executable syntax :

(rctr-tst) (from the Visual LISP console only)
rctr-tst (from the AutoCAD command line only)

reac-tst.prj

This project comprises of a host of different functions which provide examples of what can be accomplished using Reactors. These examples cover each of the four types of Reactors: Linker, Editor, Database, and Object. For more information on the different reactor types, see Attaching Reactors to AutoCAD Drawings in Chapter 9 of your Visual LISP online Help.

After opening the reac-tst.prj project, choose the "Load Source Files" button. This process will print out the associated functions to the AutoCAD Text Window due to the contents of toplevel.lsp. As you will see in the text window output after loading the source files (which is included below), each function is associated with another function that will provide information on how it works. Text Window contents :

Function Information
To test: SAME-RCL-TST For information: SAME-RCL-INFO
To test: RTRANSL-TST For information: RTRANSL-INFO
To test: ROLLS-TST For information: ROLLS-INFO
To test: PIPE-TST For information: PIPE-INFO
To test: OBJEX-TST For information: OBJEX-INFO
To test: LINKEX-TST For information: LINKEX-INFO
  To stop: STOP-LINKEX-TST
To test: EDITEX-TST For information: EDITEX-INFO
  To stop: STOP-EDITEX-TST
To test: DUMBELLS-TST For information: DUMBELLS-INFO
To test: DIMEX-TST For information: DIMEX-INFO
To test: COPYSELF-TEST For information: COPYSELF-INFO
To test: ACDBEX-TST For information: ACDBEX-INFO
  To stop: STOP-ACDBEX-TST
To test: A-MTEXT-TEST For information: A-MTEXT-INFO

It is important to load the entire project rather than individual source files because some of the routines call functions that are defined in other files. Review the following table to see where you can find examples of specific Reactor types.

Reactors Linker Editor Database Object
a-mtext.lsp       x
acdbex.lsp     x  
copyself.lsp   x   x
dimex.lsp       x
dumbells.lsp       x
editex.lsp   x    
linkex.lsp x      
objex.lsp       x
pipe.lsp   x   x
rolls.lsp       x
rtransl.lsp       x
same-rcl.lsp       x