Reactors - Page III
Object Reactors, or "VLR-Object-Reactor",
fall under general reactor types. They are almost identical in
functionality to Drawing and Command reactors except for a couple of
things! They need to include a reference to the Object that will be
reacted upon, (Crikey, that sounds terrible!!) and the reference to the
Object needs to be created before the reactor is called. Let's have a look
at the syntax of an Object reactor :
(vlr-object-reactor owners
data callback)
The "data" and "callback"
arguments, we are familiar with. But what is the "owner"
argument? This is an AutoLisp list of Visual Lisp Objects identifying the
drawing Objects to be watched. In other words, a reference to the Object
that contains the reactor.
The reactor event we are going to use is the ":vlr-modified
event", and our Callback function will be named "print-length".
Have a look at the coding for our reactor :
(vlr-object-reactor (list myLine)
"Line Reactor" '((:vlr-modified . print-length)))
As I mentioned earlier though, we need to
have a reference to the Object before we can call this statement. Consider
the following :
(vl-load-com)
;*************
(defun line-draw ()
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
(setq mspace (vla-get-modelspace acadDocument))
(setq apt (getpoint "Specify First Point: "))
(setq pt (getpoint "Specify next point: " apt))
(setq myLine (vla-addline mspace (vlax-3d-point apt)(vlax-3d-point pt)))
(setq lineReactor (vlr-object-reactor (list myLine)
"Line Reactor" '((:vlr-modified . print-length))))
(princ)
);defun
We started off by drawing a line. As the line was created from scratch,
and created using Visual Lisp functions, we already have a reference to
the line Object. (myLine). We can now safely run our reactor
function and attach it to our Line.
"But where is the Callback function?"
Hah, I was waiting for that. We've made the Callback function a separate
function for one main reason. If we didn't, every time we ran the
application it would prompt us to draw a new line. So, what we have to do
now, is link the reactor function to our Callback function so that when
our line is modified, only the Callback function is put into motion. The
reactor sends three arguments to the Callback function, the notifier-object
(our line), the reactor-object (:vlr-modified), and the
event parameter-list which in this case is nil.
Here's the coding for the Callback function :
(defun print-length (notifier-object reactor-object parameter-list)
(cond
((vlax-property-available-p notifier-object "Length")
(alert (strcat "The length is now "
(rtos (vla-get-length notifier-object)))))
);cond
(princ)
);defun
(princ)
Copy all of this coding into one file and save it as "Line-Draw.Lsp".
Now load "Line-Draw.Lsp" and then run (line-draw).
Draw a single line when prompted. Now stretch the line so that it's length
changes. A dialog will appear displaying the new length of the line :
In essence, this is what happened :
- We loaded "Line-draw.Lsp" and all functions
contained within were placed into memory.
- We ran (line-draw) which prompted us to draw a line. The
reactor was then loaded and linked to both the line Object and the
Callback function.
- As the Callback function "print-length" was also
loaded into memory, every time we modify the line Object, the Callback
function is processed and the length of the line is displayed.
Did you notice how we checked that our Object had a "Length"
Property before continuing? Good idea, as this validation can save
lot's of problems.
"But what happens when I close my drawing? Will I lose all my
reactors?"
Good questions. Reactors can be transient or persistent. Transient
reactors are lost when the drawing closes and this is the default reactor
mode. Persistent reactors are saved with the drawing and exist when the
drawing is next open.
You can use the "vlr-pers" function to make a reaction
persistent. To remove a persistence from a reactor and make it transient,
use the "vlr-pers-release" function. To determine whether
a reactor is persistent or transient, use the "vlr-pers-p"
function. Each function takes the reactor Object as it's only argument :
_$(vlr-pers lineReactor)
#<VLR-Object-Reactor>
If successful "vlr-pers" returns the specified reactor
Object.
Note : A reactor is only a link between an event and a Callback
function. The Callback function is not part of the reactor, and is
normally not part of the drawing. The reactors saved in the drawing are
only usable if their associated Callback functions are loaded in AutoCAD.
In other words, if we made our reactor "lineReactor"
persistent, we would have to ensure that the Callback function "print-length"
was loaded every time the drawing containing our lines with reactors was
opened.
If you would like the source coding for all the example in this
tutorial, then you can download them from here.
|