v3 CP4177 Ambrosius

download v3 CP4177 Ambrosius

of 30

Transcript of v3 CP4177 Ambrosius

  • 8/13/2019 v3 CP4177 Ambrosius

    1/30

    Leveraging ActiveX Libraries with AutoLISPLee AmbrosiusAutodesk, Inc.

    CP417-7 Do you have the basics of AutoLISP mastered and want to evolve from Newbie toMaster? This class might be just what you are looking for. You will learn how to work with events andreactors, access the Windows Registry, use AutoCAD and Windows ActiveX libraries, and connect toother Windows applications, such as Microsoft Word or Excel. This class is not recommended forthose new to AutoLISP.

    Learning ObjectivesAt the end of this class, you will be able to:

    Use the AutoCAD ActiveX library to access objects in an open and closed drawing

    Access and store values in the Windows Registry, Xdata, Xrecords, and Dictionaries

    Define application, document, and other types of reactors

    Manipulate the Windows environment

    Use AutoCAD to drive Microsoft Office applications, such as Microsoft Word and Excel

    About the SpeakerLee is one of the technical writers on the AutoCAD team at Autodesk and has been an AutoCAD userfor over 15 years in the fields of architecture and facilities management. He has been teaching AutoCADusers for over a decade at both the corporate and college level. He is best known for his expertise inprogramming and customizing AutoCAD-based products, and has 10+ years of experience programmingwith AutoLISP, VBA, Microsoft .NET, and ObjectARX. Lee has written articles for AUGI

    publications and white papers for Autodesk on customization. He is the author of several books onAutoCAD and has been an active technical editor for AutoCAD books in the Bibleand For Dummies

    series.

    Twitter: http://twitter.com/leeambrosius

    Email: [email protected]

    Blog: http://hyperpics.blogs.com

  • 8/13/2019 v3 CP4177 Ambrosius

    2/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    2

    Contents1 Use the COM Library with Open and Closed Drawings ....................................................... 32

    Accessing and Storing Information for Use Later ................................................................ 5

    3 Monitoring Activity in AutoCAD with Reactors ....................................................................154 Working with Windows .......................................................................................................175 Working with Microsoft Office .............................................................................................216 Where to Get More Information ..........................................................................................30

  • 8/13/2019 v3 CP4177 Ambrosius

    3/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    3

    1 Use the COM Library with Open and Closed DrawingsAutoCAD 2000 marked a major expansion of the AutoLISP development language which added

    hundreds of new functions, and most of these functions allowed you to access objects in a

    drawing like never before. This expansion of the AutoLISP language is known as Visual LISP

    and it allows you to use the COM libraries that come with AutoCAD and other applications that

    support a COM interface.

    Using the COM interface, you can access objects in AutoCAD in a much different way than you

    might have in the past through using AutoCAD commands or DXF code values. Below are

    some basic examples of how to work with the COM (Component Object Model) library in the

    current drawing and a drawing that is not even open in the current session of AutoCAD. The

    COM interface allows you to access the AutoCAD application or a document object.

    Once you have an object, you can list the available properties and methods for the object by

    using the vlax-dump-objectfunction with the T flag. The syntax for the vlax-dump-

    objectfunction is (vlax-dump-object obj [flag]).

    For example, (vlax-dump-object (vlax-get-acad-object))displays the properties

    and methods available for the AutoCAD application object.

    Tip:When using the Visual LISP functions, you must use the (vl-load-com)function in order

    to access the methods and properties in the AutoCAD COM library.

    Create Objects Using the COM Interface;; Create a blue circle using Visual LISP

    (defun c:CreateCircle-VL ( / acadObj docObj spaceObj cenPoint circObj)(setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (if (= (vla-get-activespace docObj) acModelSpace)(setq spaceObj (vla-get-modelspace docObj))(setq spaceObj (vla-get-paperspace docObj))

    )

    (setq cenPoint (vlax-make-safearray vlax-vbdouble '(0 . 2)))(vlax-safearray-fill cenPoint '(5.0 5.0 0.0))

    (setq circObj (vla-addcircle spaceObj cenPoint 1.75))

    (vla-put-color circObj 5)(princ))Modifying Objects Using the COM Interface;; Change all objects to ByLayer(defun c:ChangeAll2ByLayer ( / acadObj docObj spaceObj for-item)

    (setq acadObj (vlax-get-acad-object))

  • 8/13/2019 v3 CP4177 Ambrosius

    4/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    4

    (setq docObj (vla-get-activedocument acadObj))

    (if (= (vla-get-activespace docObj) acModelSpace)

    (setq spaceObj (vla-get-modelspace docObj))(setq spaceObj (vla-get-paperspace docObj))

    )

    (vlax-for for-item spaceObj(vla-put-color for-item acByLayer)

    (vla-put-linetype for-item "BYLAYER")

    (vla-put-lineweight for-item acLnWtByLayer))

    (princ))

    Opening Drawings with ObjectDBX

    ObjectDBX allows you to work with drawings much more efficiently when you need to quickly

    manipulate or access the contents of a drawing without opening the drawing in the application.

    When a drawing is opened using ObjectDBX, you are limited to accessing the objects differently

    than you do the document window.

    The biggest limitation that you are bound to when working with ObjectDBX is not being able to

    get input from the user through object selections and points in the drawing. The following

    sample code uses ObjectDBX to open a drawing in memory and copy all of the dimension styles

    from the in memory drawing into the current drawing.

    ;; Open drawing in the background and import all dimension styles(defun c:AccessExternalDrawing ( / acdbObj cntDimstyles acObject arTemp

    arDimStyles cntStep)

    (if (= acLibImport nil)(progn

    (vlax-import-type-library :tlb-filename"C:\\Program Files\\Common Files\\Autodesk Shared\\axdb18enu.tlb"

    :methods-prefix "acdbm-":properties-prefix "acdbp-":constants-prefix "acdbc-"

    )(setq acLibImport T)

    ))

    (setq acdbObj (vlax-create-object "ObjectDBX.AxDbDocument.18"))

    (acdbm-open acdbObj"c:\\datasets\\CP417-7\\data files\\External Drawing.dwg")

    (setq cntDimstyles 0)

  • 8/13/2019 v3 CP4177 Ambrosius

    5/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    5

    (vlax-for acObject (vla-get-Dimstyles acdbObj)

    (setq arTemp arDimStyles)

    (setq arDimStyles (vlax-make-safearray vlax-vbObject(cons 0 cntDimstyles)))

    (setq cntStep 0)(repeat cntDimstyles

    (vlax-safearray-put-element arDimStyles cntStep(vlax-safearray-get-element arTemp cntStep))

    (setq cntStep (1+ cntStep)))

    (vlax-safearray-put-element arDimStyles cntDimstyles acObject)(setq cntDimstyles (1+ cntDimstyles))

    )

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq dbObj (vla-get-database docObj))

    (setq dimstylesColl (vla-get-dimstyles dbObj))

    (vla-copyobjects acdbObj arDimStyles dimstylesColl)

    (vlax-release-object acdbObj)(princ))

    2 Accessing and Storing Information for Use LaterThe commands that you use in AutoCAD often store previously used values so you can quickly

    access these values the next time you use the command in the same drawing session, between

    drawing sessions, or globally across all drawings and sessions. The way information is stored

    for use later by a command depends on what the command is used for.

    The following are several different examples of how AutoCAD stores values for different

    commands:

    CIRCLE commandThe last radius entered is maintained within only the currentdrawing session, and once the drawing is closed the setting is lost.

    FILLET commandThe last fillet radius entered is maintained between sessions, so if

    the drawing is closed and re-opened the last value entered is the one that is used by the

    FILLET command the next time it is started.

    OPTIONS commandThe last profile set current is the profile that is used for each

    drawing that is opened and when AutoCAD is closed and re-opened.

  • 8/13/2019 v3 CP4177 Ambrosius

    6/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    6

    When creating custom applications, often persisting information is just done within the current

    drawing and session, so if the drawing is closed the routine usually uses a set of default values

    the next time it is loaded. This might be ideal for many custom routines, just like the CIRCLE

    command but might not be the best user experience.

    Visual LISP allows you to access the Windows Registry to persist data across multiple sessions

    of AutoCAD at a time. The Windows Registry can be great for storing the paths of custom

    blocks or even a setting used to determine which discipline should be used for a set of custom

    tools that are designed to work differently for each discipline.

    If you want to store different information on a per drawing basis, you can create custom

    dictionaries. Xrecords are then appended to a dictionary and contain the information that you

    want to persist similar to system variables, but you can post multiple values to a single record.

    Xdata can also be used to attach custom information per object in a drawing.

    Important:When working with the Windows Registry, exercise caution as you do not want to

    overwrite or delete a key that you did not create or do not understand what its intended purpose

    is. If you start altering values and keys for an application other than your own, the application

    may become unstable the next time it is used.

    The Windows Registry can be modified and viewed using the Registry Editor which can be

    started using Run from the Start menu and typing regedit.exe.

    Windows Registry

    Visual LISP offers four main functions that are used to read and write values to and from the

    Windows Registry. The functions that are available for working with the Windows Registry arelisted in the following table.

    Function with syntax Description

    vl-registry-delete

    (vl-registry-delete key [value])

    Removes a key or value from theregistry

    vl-registry-descendents

    (vl-registry-descendents key [value(s)])

    Returns a listing of either subkeys orvalue names of the key specified

    vl-registry-read

    (vl-registry-read key [value])

    Reads the data from the default valueof a key or a specific value

    vl-registry-write

    (vl-registry-write key [value data])

    Writes a single piece of data from tothe default value of a key or a specificvalue

  • 8/13/2019 v3 CP4177 Ambrosius

    7/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    7

    ;; Command demonstrates the use of the functions;; used to work with the Windows Registry.(defun c:WinReg ( / reg-val)

    (alert(strcat "Current Discipline: "

    (if (setq reg-val(vl-registry-read

    "HKEY_CURRENT_USER\\Software\\ABC" "Discipline"))reg-val "")

    ))

    (vl-registry-write "HKEY_CURRENT_USER\\Software\\ABC""Discipline" "Civil")

    (vl-registry-write "HKEY_CURRENT_USER\\Software\\ABC""RelativeBlockPath" "/Custom/Blocks")

    (vl-registry-write "HKEY_CURRENT_USER\\Software\\ABC\\MyDraftingSettings""FilletRadius" 0)(vl-registry-write "HKEY_CURRENT_USER\\Software\\ABC\\MyLayerSettings"

    "NotesLayer" "Notes")

    (vl-registry-descendents "HKEY_CURRENT_USER\\Software\\ABC")

    (startapp "regedit")(princ))

    Xdata, Dictionaries, and Xrecords

    Storing data in the Windows Registry is nice, but is not always a practical approach if the data

    changes from drawing to drawing or even object to object. AutoCAD allows you to storeinformation on individual objects as well as in custom dictionaries.

    Each object in the drawing can have non-graphical data associated with it; this data is stored as

    Xdata. Custom dictionaries can be created and used to store data in what are called Xrecords

    which are similar in concept to a row in a spreadsheet or database.

    Diagram of how Xdata is stored

    DrawingModel Space

    Object

    Xdata

    Diagram of how a global Dictionary is stored

    DrawingDictionaries Collection

    Dictionary

    Xrecord1

    Xrecord2

  • 8/13/2019 v3 CP4177 Ambrosius

    8/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    8

    Diagram of how a Dictionary is stored on a per object as an extension dictionary

    DrawingModel or Paper Space

    ObjectDictionary

    Xrecord1

    Xrecord2

    When assigning Xdata to an object you use the DXF codes that are 1000 and higher. Based on

    the value that you want to store in the Xdata, you must use the corresponding DXF code value.

    The following table lists the DXF codes and the value types that can be used with them.

    DXF Code Value Type

    1000-1009 String (255 character limit prior to AutoCAD

    2000 or 2049 single

    1010-1059 Double

    1060-1070 16

    1071 32

    Before you assign Xdata to an object, you must first register the name of the application

    associated with the Xdata using the Regapp function. The Regapp function takes a single

    argument and that is the application name, (regapp app).

    There are several different ways of working with Xdata, dictionaries, and Xrecords and the

    method that you choose is based on whether you are more comfortable with Classic AutoLISPor Visual LISP functions. The following table lists the functions that are part of Visual LISP for

    working with Xdata. Utilizing Classic AutoLISP allows for your programs to work on Windows

    and Mac OS X.

    Function with syntax Description

    vl-get-xdata

    (vl-get-xdata obj app artypes arvalues)

    Retrieves the data for an application onan object

    vl-set-xdata

    (vl-set-xdata obj artypes arvalues)

    Sets or removes the data for anapplication on an object

    ;; Demonstrates how to attach Xdata using the xdataLISP-VL helper function(defun c:SetXdata-VL ( / xDtype xDvalue)

    (setq xDtype (vlax-make-safearray vlax-vbinteger '(0 . 5)))(setq xDvalue (vlax-make-safearray vlax-vbvariant '(0 . 5)))

    (vlax-safearray-fill xDtype (list 1001 1000 1002 1070 1005 1002))

  • 8/13/2019 v3 CP4177 Ambrosius

    9/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    9

    (vlax-safearray-fill xDvalue(list "ACAD" "DSTYLE" "{" 347(cdr (assoc 5 (entget (tblobjname "ltype" "center"))))"}"))

    (xdataLISP-VL (car (entsel "\nSelect object to add Xdata to: "))"ACAD" xDtype xDvalue

    ))

    ;; Removes the attached Xdata using the xdataLISP-VL helper function(defun c:RemoveXdata-VL ()

    (setq xDtype (vlax-make-safearray vlax-vbinteger '(0 . 0)))(setq xDvalue (vlax-make-safearray vlax-vbvariant '(0 . 0)))

    (vlax-safearray-fill xDtype (list 1001))(vlax-safearray-fill xDvalue (list "ACAD"))

    (xdataLISP-VL (car (entsel "\nSelect object to remove Xdata from: "))"ACAD" xDtype xDvalue)

    )

    ;; Helper function for SetXdata-VL and RemoveXdata-VL;; Example (xdataLISP-VL entityName "MyApp" xDataTypeCodes xDataValues)(defun xdataLISP-VL (entityName appName xDtypeNew xDvalueNew / obj dimSize

    dimSizeNew xDtypeOld xDvalueOld)(if (/= entityName nil)(progn

    (regapp appName)

    (setq obj (vlax-ename->vla-object entityName))

    (vla-getxdata obj appName 'xDtype 'xDvalue)

    (vla-setxdata obj xDtypeNew xDvalueNew))

    )

    (princ))

    The Visual LISP approach to working with Xdata can be more complex when compared to

    ClassicAutoLISP, but it is easier to use once you understand the syntax and structure of

    creating and assigning Xdata.

    The following table lists the functions that you will use when working with Xdata in Classic

    AutoLISP. You will also still need to use the Regapp function as previously described.

  • 8/13/2019 v3 CP4177 Ambrosius

    10/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    10

    Function with syntax Description

    entget

    (enget ssname)

    Retrieves the data for an entity

    assoc

    (assoc dxf-code entdata)

    Searches out an element in a list and returnsonly the associated list

    cons

    (assoc dxf-code value)

    Constructs a dotted pair, DXF code type andvalue

    subst

    (subst new-list old-list org-list)

    Substitutes an old list of values for a new list

    ;; Demonstrates how to attach Xdata using the xdataLISP helper function

    (defun c:SetXdata ()

    (xdataLISP (car (entsel "\nSelect object to add Xdata to: "))

    (list "ACAD" '(1000 . "DSTYLE") '(1002 . "{") '(1070 . 347)

    (cons 1005 (cdr (assoc 5 (entget (tblobjname "ltype" "center")))))

    '(1002 . "}"))

    )

    )

    ;; List the Xdata attached to an object

    (defun c:ListXdata ()(assoc -3 (entget (car (entsel "\nSelect object to lists Xdata: ")) '("*")))

    )

    ;; Removes the attached Xdata using the xdataLISP helper function

    (defun c:RemoveXdata()

    (xdataLISP (car (entsel "\nSelect object to remove Xdata from: ")) '("ACAD"))

    )

    ;; Helper function for SetXdata and RemoveXdata

    ;; Example (xdataLISP entityName '("MyApp" (1004 . "Piping"))))

    (defun xdataLISP (entityName lstValue / entData)

    (if (/= entityName nil)

    (progn

    (regapp "ACAD")

    (setq entData (entget entityName '("ACAD")))

    (if (/= (assoc -3 entData) nil)

    (if (= (nth 0 (cadr (assoc -3 entData))) "ACAD")

  • 8/13/2019 v3 CP4177 Ambrosius

    11/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    11

    (setq entData (subst (cons -3 (list lstValue)) (assoc -3 entData) entData))

    (setq entData (append entData (list (list -3 lstValue))))

    )

    (setq entData (append entData (list (list -3 lstValue)))))

    (entmod entData)

    (entupd entityName)

    )

    )

    (princ)

    )

    Like Xdata, dictionaries are used to hold non-graphical data that can be referenced by multiple

    different objects in a drawing at a time. Multiline styles, groups, and layer filters among othersare stored in named dictionaries. Dictionaries can hold objects and Xrecords, commonly

    Xrecords are stored in a dictionary but that depends on what the dictionary is used for.

    When assigning values to an Xrecord, you use DXF codes just like you do for defining Xdata but

    the DXF codes used fall into the normal range used for objects which is between 1 and 369.

    The following table lists the DXF codes used with Xrecords and the value types that they can be

    assigned. For additional information on DXF codes look up the topic Group Codes in

    Numerical Order in the AutoCAD online help system.

    DXF Code Value Type

    0-9 String (255 character limit prior to AutoCAD2000 or 2049 single-byte characters with

    AutoCAD 2000 or later)

    10-39 Double precision 3D point value

    40-59 Double-precision floating-point value

    60-79 16-bit integer values

    90-99 32-bit integer values

    100 String (255-character maximum string lengths)

    102 String (255-character maximum string lengths)

    105 String representing hexadecimal value(handle)

    110-119 Double precision floating-point value

    120-129 Double precision floating-point value

    130-139 Double precision floating-point value

    140-149 Double precision scalar floating-point value

    170-179 16-bit integer value

  • 8/13/2019 v3 CP4177 Ambrosius

    12/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    12

    210-239 Double-precision floating-point value

    270-279 16-bit integer value

    280-289 16-bit integer value

    290-299 Boolean flag value

    300-309 Arbitrary text string

    310-319 String representing hex value of binary chunk

    320-329 String representing hex handle value

    330-369 String representing hex object IDs

    Since dictionaries are stored in the drawing differently than Xdata and contain Xrecords, you

    must use a different set of functions from those that you have already seen with Xdata. The

    following table lists the Visual LISP functions used to work with Xrecords and dictionaries.

    Function with syntax Description

    vla-get-dictionaries

    (vla-get-dictionaries document)

    Retrieves a listing of all thedictionaries stored in the drawing

    vla-addxrecord

    (vla-addxrecord dict-obj name)

    Adds an Xrecord to the dictionaryobject

    vla-setxrecorddata

    (vla-setxrecorddata xrec-obj types values)

    Sets the data on an Xrecord

    vla-getxrecorddata

    (vla-getxrecorddata xrec-obj types values)

    Gets the data on an Xrecord

    ;; Create a dictionary using Visual LISP

    (defun c:CreateDictionary-VL ( / ); acadObj docObj dictsColl)

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq dictsColl (vla-get-dictionaries docObj))

    (setq dictObj (vla-add dictsColl "MY_CUSTOM_DICT2"))

    (setq xrecObj (vla-addxrecord dictObj "XREC_1"))

    (setq xDtype (vlax-make-safearray vlax-vbinteger '(0 . 2)))

    (setq xDvalue (vlax-make-safearray vlax-vbvariant '(0 . 2)))

    (setq xPoint (vlax-make-safearray vlax-vbdouble '(0 . 2)))

    (vlax-safearray-fill xPoint '(5.0 5.0 0.0))

  • 8/13/2019 v3 CP4177 Ambrosius

    13/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    13

    (vlax-safearray-fill xDtype '(1 10 71))

    (vlax-safearray-fill xDvalue (list "Visual LISP Dictionary" xPoint 11))

    (vla-setxrecorddata xrecObj xDtype xDvalue)

    (princ)

    )

    ;; Delete a dictionary using Visual LISP

    (defun c:DeleteDictionary-VL ( / acadObj docObj dictsColl dictObj)

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq dictsColl (vla-get-dictionaries docObj))

    (vla-delete (vla-item dictsColl "MY_CUSTOM_DICT2"))

    (princ)

    )

    ;; Prints the data from an Xrecord using Visual LISP

    (defun c:PrintXrec-VL ( / acadObj docObj dictsColl dictObj xrecObj xDtype xDvalue)

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq dictsColl (vla-get-dictionaries docObj))

    (setq dictObj (vla-item dictsColl "MY_CUSTOM_DICT2"))

    (setq xrecObj (vla-item dictObj "XREC_1"))

    (vla-getxrecorddata xrecObj 'xDtype 'xDvalue)

    (if (/= xDtype nil)

    (progn

    (princ (vlax-safearray->list xDtype))

    (terpri)

    (princ (vlax-safearray->list xDvalue))

    )

    )

    (princ)

    )

  • 8/13/2019 v3 CP4177 Ambrosius

    14/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    14

    The following table lists the functions that you can use to work with dictionaries in Classic

    AutoLISP.

    Function with syntax Descriptiondictadd

    (dictadd dict-entity rec-name entity)

    Adds a custom dictionary to thespecified entity

    dictremove

    (dictremove entity name)

    Removes a custom dictionary

    dictnext

    (dictnext entity [flag])

    Returns the next entry in adictionary

    dictrename

    (dictrename entity old-name new-name)

    Renames a dictionary from the oldname to a new name

    dictsearch

    (dictsearch entity name [flag])

    Searches a dictionary for an item

    ;; Demonstrates how to create a dictionary

    (defun c:CreateDictionary ( / dict xname newdict datalist)

    (setq dict (list '(0 . "DICTIONARY") '(100 . "AcDbDictionary")))

    (setq xname (entmakex dict))

    (setq newdict (dictadd (namedobjdict) "MY_CUSTOM_DICT" xname))

    (setq datalist (append (list '(0 . "XRECORD") '(100 . "AcDbXrecord"))

    '((1 . "Custom string") (10 5.0 5.0 0.0)

    (71 . 11))))

    (setq xname (entmakex datalist))

    (dictadd newdict "XREC_1" xname)

    (princ)

    )

    ;; Deletes a custom dictionary

    (defun c:DeleteDictionary ()

    (dictremove (namedobjdict) "MY_CUSTOM_DICT")

    )

    ;; Prints the data from an Xrecord

    (defun c:printXrec ( / dictName dictEntry newdictlist xrec)

  • 8/13/2019 v3 CP4177 Ambrosius

    15/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    15

    (setq dictName "MY_CUSTOM_DICT"

    dictEntry "XREC_1"

    )

    (setq newdictlist (dictsearch (namedobjdict) dictName))

    (setq xrec (cadr (member (cons 3 dictEntry) newdictlist)))

    (princ (entget (cdr xrec)))

    (princ)

    )

    3 Monitoring Activity in AutoCAD with ReactorsAutoCAD monitors a lot of actions that take place in the application, while a drawing is open,

    and when objects are added to or modified in the drawing. Visual LISP allows you to step in

    and catch many of these actions through what is known as a reactor.

    Reactors come in a variety of types, some of the more common reactor types are listed in the

    following table.

    Reactor Description

    :VLR-AcDb-Reactor Database reactor

    :VLR-Command-Reactor Command reactor

    :VLR-DeepClone-Reactor Deep clone reactor

    :VLR-DocManager-Reactor Document management reactor

    :VLR-DWG-Reactor Drawing reactor (opening or closing a drawingfile)

    :VLR-DXF-Reactor DXF file handling reactor (reading and writing)

    :VLR-Editor-Reactor General editor reactor (available forbackwards compatibility)

    :VLR-Insert-Reactor Block insertion reactor

    :VLR-Linker-Reactor Linker reactor

    :VLR-Lisp-Reactor LISP reactor

    :VLR-Miscellaneous-Reactor Reactors that are not part of other reactortypes (pick first changes and layout switching)

    :VLR-Mouse-Reactor Mouse reactor (right-click and double-click)

    :VLR-Object-Reactor Object reactor (appending and modifyingobjects)

    :VLR-SysVar-Reactor System variable reactor

    :VLR-Toolbar-Reactor Toolbar reactor (toolbar images change size)

  • 8/13/2019 v3 CP4177 Ambrosius

    16/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    16

    :VLR-Undo-Reactor Undo reactor

    :VLR-Wblock-Reactor Writing a block reactor

    :VLR-Window-Reactor AutoCAD or drawing window reactor (windowis moved or resized)

    :VLR-XREF-Reactor XREF reactor (attaching, reloading, ordetaching)

    For more information about reactors, take a look at the AutoLISP Reference Guide in the

    AutoCAD online help.

    Important:When using reactors you cannot call a command using the Command function; this

    is due to the way reactors are designed. You must use the Visual LISP functions and the COM

    API to mimic the behavior of the commands that you need.

    Command Reactor

    Command reactors are one of the most commonly used reactors. They allow you to be notified

    when a command is started, ends, gets cancelled, or fails for some reason. The following

    sample code shows how to watch for a specific command, in this case the Hatch, and perform a

    task before the command even begins.

    ;; Check to see if our custom command reactors

    ;; have been loaded into the current drawing

    (if (= hyp-rctCmds nil)

    (setq hyp-rctCmds (vlr-command-reactor nil

    '((:vlr-commandCancelled . hyp-cmdAbort)(:vlr-commandEnded . hyp-cmdAbort)

    (:vlr-commandFailed . hyp-cmdAbort)

    (:vlr-commandWillStart . hyp-cmdStart)

    )

    )

    )

    )

    ;; Callback used when the user presses ESCape

    ;; or when the command ends by itself or due to

    ;; a problem

    (defun hyp-cmdAbort (param1 param2)

    (if (/= hyp-gClayer nil)

    (setvar "clayer" hyp-gClayer)

    )

    (setq hyp-gClayer nil)

  • 8/13/2019 v3 CP4177 Ambrosius

    17/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    17

    )

    ;; Callback used when a command is started

    (defun hyp-cmdStart (param1 param2)

    (setq hyp-gClayer (getvar "clayer"))

    (cond

    ((= (car param2) "QDIM")(prompt "\nQDIM started"))

    ((or (= (car param2) "HATCH")

    (= (car param2) "BHATCH")

    (= (car param2) "GRADIENT")

    )

    (progn

    (if (= (tblsearch "layer" "Hatch") nil)

    (progn

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq layerObj (vla-add (vla-get-layers docObj) "Hatch"))

    (vla-put-color layerObj acRed)

    ))

    (setvar "clayer" "Hatch")

    )

    )

    )

    )

    4 Working with WindowsMicrosoft creates many different APIs (Application Programming Interfaces) for themselves and

    other developers to take advantage of features found in Windows and the applications theydevelop. Since Visual LISP allows you to tap into COM libraries outside of AutoCAD, you can

    manipulate the features of Windows such as the file system and to collect information about the

    current user that is currently logged into the system and even the computer that the user is

    using.

  • 8/13/2019 v3 CP4177 Ambrosius

    18/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    18

    Create Desktop Shortcut for AutoCAD

    Below is an example of using the Windows Host Scripting Object to create a shortcut on the

    Desktop that allows you to use the /w command line switch to start AutoCAD with a specific

    workspace. Desktop shortcuts are one of many different ways to help enforce CAD standards

    and help to make the users life just a little bit easier, but since it can take time to setup icons on

    each computer they are often not used. The amount of configuration time is not a factor with

    the sample code, and it can be run at startup using a file likeAcaddoc.lsp.

    ;; Create shortcut on desktop

    (defun c:CreateDesktopShortcut ( / wshShell desktopFldr myDocsFldr shrtObj)

    (if (= wshLibImport nil)

    (progn

    (vlax-import-type-library

    :tlb-filename "c:\\windows\\system32\\wshom.ocx"

    :methods-prefix "wshm-"

    :properties-prefix "wshp-"

    :constants-prefix "wshk-"

    )

    (setq wshLibImport T)

    )

    )

    (setq wshShell (vlax-create-object "WScript.Shell"))

    (setq desktopFldr (wshm-Item

    (wshp-get-SpecialFolders wshShell) "Desktop"))

    (setq myDocsFldr (wshm-Item

    (wshp-get-SpecialFolders wshShell) "MyDocuments"))

    (setq shrtObj (wshm-CreateShortcut

    wshShell (strcat desktopFldr "\\My AutoCAD.lnk")))

    (wshp-put-TargetPath shrtObj

    "\"C:\\Program Files\\Autodesk\\AutoCAD 2012 - English\\acad.exe\"")

    (wshp-put-Arguments shrtObj "/w \"3D Modeling\"")

    (wshp-put-Description shrtObj "Custom AutoCAD Desktop Shortcut")

    (wshp-put-WindowStyle shrtObj wshk-WshNormalFocus)

  • 8/13/2019 v3 CP4177 Ambrosius

    19/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    19

    (wshp-put-HotKey shrtObj "Ctrl+Alt+A")

    (wshp-put-WorkingDirectory shrtObj myDocsFldr)

    (wshp-put-IconLocation shrtObj

    "C:\\Program Files\\Autodesk\\AutoCAD 2012 - English\\acad.exe, 0")

    (wshm-save shrtObj)

    (vlax-release-object wshShell)

    (princ)

    )

    AutoCAD offers a number of different command line switches that can be used to control its

    start up behavior. Other popular and useful command line switches are /t to specify a drawingtemplate for the default drawing that is created when AutoCAD first starts up and /p to specify

    the user profile that AutoCAD should use.

    To find out about these and other command line options in AutoCAD look up the topic

    Customize Startup in theAutoCAD online Help system. For additional information on the

    Windows Host Script Object, visit Microsofts website and do a search on Windows Script

    Documentation to download the help file for Windows scripting.

    Working with Environment Variables

    Environment variables are used to store information and settings about the current user logged

    into the machine, computer specific settings, or application specific settings. Some environmentvariables can be set or retrieved using AutoLISP with the Setenv and Getenv, but these

    functions are mainly limited to accessing some settings in the Windows Registry for AutoCAD

    and a few of the common Windows environment variables.

    By using the Windows Host Scripting Object, you can access all of the Windows environment

    variables and use strings with expandable variables contained in a string. By having access to

    the Windows environment variables, you can access and store custom settings outside of the

    Windows Registry. Environment variables are stored in two different ways; user or system.

    You use the keyword USER when you want to work with va riables that are specific to the user

    that is currently logged in or SYSTEM to work with variables that are machine specific and are

    not user specific.

    To see which variables are available to you, launch a DOS prompt and enter the command

    SET.

    To see which variables are specific to you as a user, or the system go to Start (menu) >>

    Control Panel and double-click System. You might have to switch to the Classic View based on

    your current version of Windows operating system. For Windows Vista or Windows 7, click the

  • 8/13/2019 v3 CP4177 Ambrosius

    20/30

  • 8/13/2019 v3 CP4177 Ambrosius

    21/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    21

    (princ)

    )

    5 Working with Microsoft OfficeBeing able to manipulate objects in AutoCAD and Windows can go a long way to improving

    workflow and help to decrease the number of redundant tasks that you might normally do every

    day. Being able to efficiently use your design information downstream can help a project get out

    faster and more cost effectively. Like you previously learned, Visual LISP is capable of working

    with other COM libraries and Microsoft offers many different COM libraries to work with its

    Microsoft Office applications such as Word and Excel.

    The following samples demonstrate

    Printing a Microsoft Word document to the default printer Showing how to take information from AutoCAD to create a Microsoft Word document

    Pushing and pulling information from an Microsoft Excel spreadsheet to modify content

    of a drawing

    Accessing information from a Microsoft Access (MDB) database

    Print Documents through Word

    If you are creating documents with Word dynamically and they need to be a part of a bid

    package, you will most likely want to have them printed and someone review them or maybe

    you want to have a user manual online and allow the user to print specific documents off for

    certain in-drawing conditions or assembly instructions. Whatever your reason might be, you can

    print a Word document off and the sample code below shows using a custom function to do just

    that.

    ;; Usage: (PrintMSWordDoc "c:\\datasets\\CP417-7\\data files\\spec1.doc")

    ;; Open a document in MS Word and print it using the default printer

    (defun PrintMSWordDoc (strWordDoc / wordObj wordDocsObj wordDocObj)

    (if (= wordLibImport nil)

    (progn

    (vlax-import-type-library

    :tlb-filename

    "C:\\Program Files\\Microsoft Office\\OFFICE12\\MSWORD.OLB"

    :methods-prefix "wordm-"

    :properties-prefix "wordp-"

    :constants-prefix "wordc-"

    )

    (setq wordLibImport T)

    )

    )

  • 8/13/2019 v3 CP4177 Ambrosius

    22/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    22

    (setq wordObj (vlax-create-object "Word.Application.12"))

    (setq wordDocsObj (vlax-get-property wordObj 'Documents))

    (setq wordDocObj (wordm-open wordDocsObj strWordDoc))

    (wordm-printout wordDocObj)

    (wordm-close wordDocObj wordc-wdDoNotSaveChanges)

    (wordm-quit wordObj wdDoNotSaveChanges)

    (vlax-release-object wordObj)

    (princ)

    )

    Create new Word Document Based on Information in DrawingOften when you create a drawing, you might also need to generate a quote based on the

    information contained in the drawing. Using the Microsoft Word COM library you can create a

    new document from scratch or even populate information into a document based on a template.

    The following sample code demonstrates how to create a new document from scratch and

    create a series of paragraphs that contain the names of the layers, dimension styles, text styles

    and blocks contained in the drawing.

    ;; Creates a new Word document and extracts styles from the current drawing.

    ;; The extracted information is added to the new Word document.

    (defun c:CreateMSWordDoc ( / acadObj docObj wordObj wordDocsObj wordDocObjwordParasObj wordParaObj wordParaRangeObj

    wordSentencesObj wordSentenceObj

    wordSentenceFontObj)

    (if (= wordLibImport nil)

    (progn

    (vlax-import-type-library

    :tlb-filename

    "C:\\Program Files\\Microsoft Office\\OFFICE12\\MSWORD.OLB"

    :methods-prefix "wordm-"

    :properties-prefix "wordp-"

    :constants-prefix "wordc-"

    )

    (setq wordLibImport T)

    )

    )

  • 8/13/2019 v3 CP4177 Ambrosius

    23/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    23

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq wordObj (vlax-create-object "Word.Application.12"))

    (setq wordDocsObj (vlax-get-property wordObj 'Documents))

    (setq wordDocObj (wordm-Add wordDocsObj))

    (setq wordParasObj (wordp-get-paragraphs wordDocObj))

    (setq wordParaObj (wordm-add wordParasObj))

    (setq wordParaRangeObj (wordp-get-range wordParaObj))

    (wordp-put-text wordParaRangeObj

    (strcat "Welcome to Autodesk University 2011"

    "\nWhat you are seeing is a very basic "

    "example of creating a Word document using "

    "the MS Word object. The example code creates "

    "a listing of layers, dimension styles, text "

    "styles and block names from the current "

    "drawing.\n\n"))

    (setq wordSentencesObj (wordp-get-sentences wordParaRangeObj))

    (setq wordSentenceObj (wordm-item wordSentencesObj 1))

    (setq wordSentenceFontObj (wordp-get-font wordSentenceObj))

    (wordp-put-bold wordSentenceFontObj :vlax-true)(wordp-put-underline wordSentenceFontObj :vlax-true)

    (wordp-put-size wordSentenceFontObj 16)

    (setq wordParaObj (wordm-add wordParasObj))

    (setq wordParaRangeObj (wordp-get-range wordParaObj))

    (wordp-put-text wordParaRangeObj

    (strcat "Report from drawing: " (vla-get-fullname docObj) "\n\n"))

    (listItems (vla-get-layers docObj) "Layer List")

    (listItems (vla-get-dimstyles docObj) "Dimension Style List")(listItems (vla-get-textstyles docObj) "Text Style List")

    (listItems (vla-get-blocks docObj) "Block List")

    (wordp-put-visible wordObj :vlax-true)

    (vlax-release-object wordObj)

    (princ)

  • 8/13/2019 v3 CP4177 Ambrosius

    24/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    24

    )

    ;; Used to create a new paragraph based on the items in the collection

    ;; The title line is formatted as bold, underlined and a size of 14.(defun listItems (coll title / itemList wordParaObj wordParaRangeObj

    wordSentencesObj wordSentenceFontObj)

    (setq itemList "")

    (vlax-for for-item coll

    (setq itemList (strcat itemList "\n" (vla-get-name for-item)))

    )

    (setq wordParaObj (wordm-add wordParasObj))

    (setq wordParaRangeObj (wordp-get-range wordParaObj))

    (wordp-put-text wordParaRangeObj (strcat title itemList "\n\n"))

    (setq wordSentencesObj (wordp-get-sentences wordParaRangeObj))

    (setq wordSentenceObj (wordm-item wordSentencesObj 1))

    (setq wordSentenceFontObj (wordp-get-font wordSentenceObj))

    (wordp-put-bold wordSentenceFontObj :vlax-true)

    (wordp-put-underline wordSentenceFontObj :vlax-true)

    (wordp-put-size wordSentenceFontObj 14)

    )

    Extract Information to Microsoft Excel Workbook

    Microsoft Excel is a very powerful application that allows you to perform complex calculations or

    even create tables of information such as door and window schedules. The sample code below

    demonstrates the ability to extract information from a drawing. In this case it is the diameter of

    the circles in the drawing and their object handle. The object handle will be used to later update

    the objects in the drawing after the values in Microsoft Excel have been changed.

    ;; Creates a new Excel spreadsheet and extract the

    ;; circles from the current drawing.

    ;; The extracted information is added to the new Excel spreadsheet.(defun c:ExtractDrawingToExcel ( / acadObj docObj excelObj excelWorkbooksObj

    excelWorkbookObj excelWorksheetsObj

    excelWorksheetObj excelRangeObj

    spaceObj cnt for-item)

    (if (= excelLibImport nil)

    (progn

  • 8/13/2019 v3 CP4177 Ambrosius

    25/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    25

    (vlax-import-type-library

    :tlb-filename

    "C:\\Program Files\\Microsoft Office\\OFFICE12\\Excel.exe"

    :methods-prefix "exlm-":properties-prefix "exlp-"

    :constants-prefix "exlc-"

    )

    (setq excelLibImport T)

    )

    )

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq excelObj (vlax-create-object "Excel.Application.12"))

    (exlp-put-visible excelObj :vlax-true)

    (setq excelWorkbooksObj (vlax-get-property excelObj 'Workbooks))

    (setq excelWorkbookObj (exlm-add excelWorkbooksObj))

    (setq excelWorksheetsObj (vlax-get-property excelWorkbookObj 'Worksheets))

    (setq excelWorksheetObj (exlp-get-item excelWorksheetsObj 1))

    (setq excelRangeObj (exlp-get-range excelWorksheetObj "A1"))(exlp-put-value2 excelRangeObj

    (vlax-make-variant "Welcome to AU 2011" vlax-vbstring))

    (if (= (vla-get-activespace docObj) acModelSpace)

    (setq spaceObj (vla-get-modelspace docObj))

    (setq spaceObj (vla-get-paperspace docObj))

    )

    (setq excelRangeObj (exlp-get-range excelWorksheetObj "A2"))

    (exlp-put-value2 excelRangeObj (vlax-make-variant "Handle" vlax-vbstring))

    (setq excelRangeObj (exlp-get-range excelWorksheetObj "B2"))

    (exlp-put-value2 excelRangeObj (vlax-make-variant "Radius" vlax-vbstring))

    (setq cnt 3)

    (vlax-for for-item spaceObj

    (if (= (vla-get-objectname for-item) "AcDbCircle")

  • 8/13/2019 v3 CP4177 Ambrosius

    26/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    26

    (progn

    (setq excelRangeObj

    (exlp-get-range excelWorksheetObj (strcat "A" (itoa cnt))))

    (exlp-put-value2 excelRangeObj(vlax-make-variant (vla-get-handle for-item) vlax-vbstring))

    (setq excelRangeObj

    (exlp-get-range excelWorksheetObj (strcat "B" (itoa cnt))))

    (exlp-put-value2 excelRangeObj

    (vlax-make-variant (vla-get-radius for-item) vlax-vbdouble))

    (setq cnt (+ cnt 1))

    )

    )

    )

    (exlm-saveas excelWorkbookObj

    "c:\\datasets\\CP417-7\\data files\\circle-radius"

    exlc-xlNormal "" "" :vlax-false

    :vlax-true exlc-xlNoChange exlc-xlLocalSessionChanges

    :vlax-false "" "" :vlax-false)

    (vlax-release-object excelObj)

    (princ)

    )

    ;; Opens an Excel spreadsheet and updates the entities in the

    ;; drawing based on the values in the spreadsheet.

    (defun c:UpdateDrawingFromExcel ( / acadObj docObj excelObj

    excelWorkbooksObj excelWorkbookObj

    excelWorksheetsObj excelWorksheetObj

    excelRangeObj strHandle

    ss cnt)

    (if (= excelLibImport nil)

    (progn

    (vlax-import-type-library:tlb-filename

    "C:\\Program Files\\Microsoft Office\\OFFICE12\\Excel.exe"

    :methods-prefix "exlm-"

    :properties-prefix "exlp-"

    :constants-prefix "exlc-"

    )

    (setq excelLibImport T)

  • 8/13/2019 v3 CP4177 Ambrosius

    27/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    27

    )

    )

    (setq acadObj (vlax-get-acad-object))

    (setq docObj (vla-get-activedocument acadObj))

    (setq excelObj (vlax-create-object "Excel.Application.12"))

    (exlp-put-visible excelObj :vlax-true)

    (setq excelWorkbooksObj (vlax-get-property excelObj 'Workbooks))

    (setq excelWorkbookObj

    (exlm-open excelWorkbooksObj

    "c:\\datasets\\CP417-7\\data files\\circle-radius"))

    (setq excelWorksheetsObj (vlax-get-property excelWorkbookObj 'Worksheets))

    (setq excelWorksheetObj (exlp-get-item excelWorksheetsObj 1))

    (setq excelRangeObj (exlp-get-range excelWorksheetObj "A3"))

    (setq cnt 3)

    (while (setq strHandle

    (vlax-variant-value (exlp-get-value2 excelRangeObj)))

    (setq ss (handent strHandle))

    (setq obj (vlax-ename->vla-object ss))

    (setq excelRangeObj

    (exlp-get-range excelWorksheetObj (strcat "B" (itoa cnt))))

    (vla-put-radius obj

    (vlax-variant-value (exlp-get-value2 excelRangeObj)))

    (setq cnt (+ cnt 1))

    (setq excelRangeObj

    (exlp-get-range excelWorksheetObj (strcat "A" (itoa cnt))))

    )

    (vlax-release-object excelObj)

    (princ)

    )

    Work with Access Database using DAO

    The DAO (Data Access Object) allows you to access data in a Microsoft Access database which

    can be used to populate the title block of a drawing or even keep track of project management

  • 8/13/2019 v3 CP4177 Ambrosius

    28/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    28

    information. Microsoft Access databases are a great way to manage information in or from a

    drawing so it can be used downstream later to generate project quotes or manage information

    like building/IT assets.

    The sample code demonstrates how to utilize an Microsoft Access database that contains a

    single table and to step through the records contained in the table as well as update a field for

    one of the records in the table.

    ;; Opens an Access Database file and reports on the number of records in a

    table and

    ;; the records contained in the table.

    (defun c:AccessDatabase ( / daoObj dbObj rstObj fieldsObj)

    (if (= daoLibImport nil)

    (progn(vlax-import-type-library

    :tlb-filename

    "C:\\Program Files\\Common Files\\

    Microsoft Shared\\DAO\\dao360.dll"

    :methods-prefix "daom-"

    :properties-prefix "daop-"

    :constants-prefix "daoc-"

    )

    (setq daoLibImport T)

    )

    )

    (setq daoObj (vlax-create-object "DAO.DBEngine.36"))

    (setq dbObj (daom-opendatabase daoObj

    "c:\\datasets\\CP417-7\\data files\\AU2011.mdb"))

    (setq rstObj (daom-openrecordset dbObj "tblEmployees" daoc-dbOpenDynaset))

    (daom-movefirst rstobj)

    (daom-movelast rstobj 0)

    (prompt (strcat "\n" (itoa (daop-get-recordcount rstObj))

    " records in table."))

    (daom-movefirst rstobj)

    (prompt "\n\nEmployee names")

    (while (= (daop-get-eof rstObj) :vlax-false)

  • 8/13/2019 v3 CP4177 Ambrosius

    29/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    29

    (setq fieldsObj (daop-get-fields rstObj))

    (prompt (strcat "\nFirst name: "

    (vlax-variant-value(daop-get-value

    (daop-get-item fieldsObj "FirstName")))))

    (prompt (strcat "\nLast name: "

    (vlax-variant-value

    (daop-get-value (daop-get-item fieldsObj "LastName")))))

    (terpri)

    (daom-movenext rstobj)

    )

    (daom-movefirst rstobj)

    (daom-findfirst rstobj "FirstName='Bob'")

    (if (= (daop-get-nomatch rstobj) :vlax-true)

    (prompt "\nNo matching record")

    (progn

    (setq fieldsObj (daop-get-fields rstobj))

    (prompt (strcat "\nBob was in room "

    (vlax-variant-value

    (daop-get-value(daop-get-item fieldsObj "RoomNumber")))))

    (terpri)

    (daom-edit rstobj)

    (daop-put-value (daop-get-item fieldsObj "RoomNumber") "103A")

    (prompt "but is now in room 103A.\n")

    (daom-update rstobj 1 0)

    (princ))

    )

    (daom-close rstobj)

    (daom-close dbObj)

    (vlax-release-object daoObj)

  • 8/13/2019 v3 CP4177 Ambrosius

    30/30

    CP417-7: Leveraging ActiveX Libraries with AutoLISP

    (gc)

    (princ)

    )

    6 Where to Get More InformationWhen you are first start using the functionality found in an ActiveX library, you will most likelyhave some questions and where you go to find answers might not be clear. The following is alist of resources that you can use to get help:

    o Help SystemThe AutoLISP Reference Guide in the AutoCAD online Help systemcontains information on using some of the COM related functions, but you will also needto turn to the AutoCAD ActiveX Reference Guide. To access the AutoLISP ReferenceGuide, go to: http://exchange.autodesk.com/autocad/enu/help. The AutoCAD ActiveXReference Guide can be found at C:\Program Files\Common Files\Autodesk Shared\

    acadauto.chm.o Autodesk Discussion ForumsThe Autodesk forums provide peer-to-peer networking

    and some interaction with Autodesk moderators. You can ask a question about anythingin AutoCAD and get a response from a fellow user or Autodesk employee. To accessthe discussion forums, go to http://forums.autodesk.com , click AutoCAD, and then clickone of the links for a subgroup.

    o AUGI ForumsThe AUGI forums provide peer-to-peer networking where you can askquestions about virtually anything in AutoCAD and get a response from a fellow user.Visit AUGI at http://www.augi.com.

    o Industry Events and ClassesIndustry events such as AUGI CAD Camp andAutodesk University are great places to learn about new features in an Autodesk

    product. Along with industry events, you might also be able to find classes at your localtechnical college or Autodesk Authorized Training Center (ATC).

    o InternetThere are samples and tutorials on the Internet that demonstrate otheraspects of the AutoCAD and Microsoft Office ActiveX libraries. Use your favorite searchengine, such as Google or Bing and search on the topic of interest.