
The previous chapter was about first attempts to find one's way in the tree of objects. To z.B. To find out which color for Layer "0" is set, we used this function: (defun test6( / ) (vl-load-com) (vlax-get-property (vlax-invoke-method (vlax-get-property (vlax-get-property (vlax-get-acad-object) "ActiveDocument" ) "Layers ) "Item" "0" ) "Color" ) ) (test6) => 7 This chapter will now focus on how to avoid such a jumble of code – there are shorter ways to find out that the layer is white. And how can we accomplish this? Visuallisp provides us with a whole package of functions that avoid the tedious shambling from object to object and bring us more or less directly to the goal. Perhaps you will groan now and ask: 'And why then only so awkwardly, if it also much more simply goes?'
There are two reasons for this: The structure of this tree (and thus the object structure of AutoCAD) simply must be understood, otherwise you can't write ActiveX programs. This reason should be obvious. The second reason is that there is no documentation for the shortcut functions! Maybe it exists, but I haven't found any yet.
All these functions we are talking about here have the name prefix (vla-…). There are a lot of them, how many there really are, we will find out in this chapter. They are replaced by the obligatory call of (vl-load-com) and can be used from then on. However, due to the lack of documentation, you have to figure out the number and type of arguments yourself – that means you have to know your way around the object tree and look it up there.
However, the arguments are not the problem – more difficult is first of all to find out which functions there are at all. You can't search in a list and then say: "This could be the one I need right now"!". On the other hand, you certainly can't learn them by heart from example programs – maybe you have all the 'normal' Lisp functions in your head, but that's just too many!
How can one determine at all, what there is? The only thing left for us to do is to look at the symbol table of the Lisp interpreter. For that there is the function with the nice name (atoms-family). With this function you can control by the argument whether the symbol names are listed as strings or as symbols. So that we can use (substr) which vla-functions can filter out, we decide to use strings. (defun get-vla-functions( / rl) (vl-load-com) (vl-sort (vl-remove-if-not (function (lambda(name / ) (= (strcase(substr name 1 4)) "VLA") ) ) (atoms-family 1) ) '< ) ) First of all a few words about this function: Even if some with the prefix (vl-…) If there are some functions in it, it's not about ActiveX in any way. Even if (vl-sort) and (vl-remove-if-not) it is 'normal' Lisp-functions – just newly added with VisualLisp. At (function) the prefix has been omitted for some reason. (function) is a (quote) with additional effect: it is a hint that the quoted expression is a lambda function. The VisualLisp compiler will then compile the function to bytecode – when using (quote) it does not. But this also means that this expression is no longer changeable at runtime.
In a nutshell: The function creates a list of all symbols in the symbol table and then filters out those that start with the prefix (VLA-…) begin. A word about the case-sensitivity of the functions, symbols, constants of ActiveX: It does not matter at all. In memory (and therefore also in the symbol table) everything is converted to uppercase anyway – or so we think! By the way, the ActiveX functions accept the names of properties both as strings and symbols: ; string notation (vlax-get-property (vlax-get-acad-object) "ActiveDocument" ) ; symbol notation (vlax-get-property (vlax-get-acad-object) 'ActiveDocument ) ; large or small plays… (vlax-get-property (vlax-get-acad-object) "ACTIVEDOCUMENT" ) ; does not matter at all… (vlax-get-property (vlax-get-acad-object) 'activedocument ) ; so it is most readable (vlax-get-property (vlax-get-acad-object) 'ActiveDocument ) But now back to our family research function. The output is so long that AutoCAD does not even display it in full length in the text window. So we test once with (length), how many functions are involved at all: (length(get-vla-functions)) => 1163 This figure is output in my case under AutoCAD 2002, and since AutoDESK uses the complete VisualLisp package from 2000i without any modification (d.H. Even without bugfixes etc.), the figure should also be valid for AutoCAD 2000i. So our function can be seen as an approach, but to work with it, the result is much too unwieldy.
So we go one step further. We need a function that filters the output function again according to search criteria – so if z.B. Is interested in the keyword 'Layer', the function must output all VLA functions containing the string 'Layer'. (defun find-vla-functions(pattern / ) (mapcar'read (vl-remove-if-not (function (lambda(name / ) (wcmatch name (strcat "*"(strcase pattern) "*") ) ) ) (get-vla-functions) ) ) ) (find-vla-functions "layer") => (vla-get-ActiveLayer vla-get-DefaultPlotStyleForLayer vla-get-Layer vla-get-LayerOn vla-get-Layers vla-get-XRefLayerVisibility vla-put-ActiveLayer vla-put-DefaultPlotStyleForLayer vla-put-Layer vla-put-LayerOn vla-put-XRefLayerVisibility) What a surprise – not that these functions were output: This was to be expected. But that she (with (read) converted to symbols) are not converted to upper case, that is the surprise. With ActiveX everything stops – even the statement of the manual that symbols can be entered 'case insentitive', but that the processing and output is always done in capital letters, is undermined by the ActiveX interface.
Back to what we actually want – shortening the ActiveX code. Let's return to an example from the previous chapter: We want to change the color of the layer "0" to be determined. The function we are looking for is quickly found, it can only be (vla-get-ActiveLayer) Act. We can also find a function to get the color of something: (find-vla-functions "color") => (vla-get-AutoSnapMarkerColor vla-get-AutoTrackingVecColor vla-get-Color vla-get-DimensionLineColor vla-get-ExtensionLineColor vla-get-GraphicsWinLayoutBackgrndColor vla-get-GraphicsWinModelBackgrndColor vla-get- GripColorSelected vla-get-GripColorUnselected vla-get-LayoutCrosshairColor vla-get-ModelCrosshairColor vla-get-TextColor vla-get-TextWinBackgrndColor vla-get-TextWinTextColor vla-get-TrueColorImages vla-put-AutoSnapMarkerColor vla- put-AutoTrackingVecColor vla-put-Color vla-put-DimensionLineColor vla-put-ExtensionLineColor vla-put-GraphicsWinLayoutBackgrndColor vla-put-GraphicsWinModelBackgrndColor vla-put-GripColorSelected vla-put-GripColorUnselected vla- put-LayoutCrosshairColor vla-put-ModelCrosshairColor vla-put-TextColor vla-put-TextWinBackgrndColor vla-put-TextWinTextColor vla-put-TrueColorImages) Here, perhaps, we should use the short function (vla-get-color) try. Of course now the two functions must be called in combination. We'll just give it a try: (vla-get-color(vla-get-ActiveLayer)) => ; Error: Too few arguments Well, this is actually logical, if you consider that every open drawing has an actual layer. We still have to specify that we refer to the current drawing. That for this a function (vla-get-ActiveDocument) exists and this then still the application-object needed as an argument – sure, we know that. (vla-get-color (vla-get-ActiveLayer (vla-get-ActiveDocument (vlax-get-acad-object) ) ) ) => 7 Well then! In the next chapter follows another approach, with the help of which we can possibly shorten the code.