This article introduces you to VBA, how it is installed in IntelliCAD and how to add a VBA routine to a menu. While this may leave VBA as mysterious as ever for some readers, the fog should begin to clear as the series progresses.
Visual Basic for Applications (VBA) is a programming language which can be found in a number of Microsoft Windows applications. It has been developed by Microsoft as a variation of its Visual Basic programming language, able to be imbedded as a component into other applications to provide a Windows-compatible programming environment.
The current versions of both AutoCAD and IntelliCAD now provide VBA as a programming option. While the VBA implementation in AutoCAD has a reasonable amount of technical information and on-line help available, similar information for IntelliCAD is not so easy to obtain.
Perhaps the first question to be addressed is, why should one use VBA for programming in IntelliCAD? Here, we can address both AutoCAD and IntelliCAD equally, as the same reasons apply to both programs.
Most development in these programs is usually performed using LISP in IntelliCAD (AutoLISP in AutoCAD), an interpretive programming language which offers great flexibility. The biggest drawback with LISP is that it is slow. If substantial processing of data is required, this can take a lot of time to complete. Also, to implement any form of dialogue box requires interfacing with the DCL system and this can be quite messy.
For professional developers, more serious work can be done in SDS in IntelliCAD (or ObjectARX in AutoCAD). This involves writing programs, usually in the C language, then compiling these with certain supplied custom Libraries to obtain a program module which can run in association with the CAD program. Such applications run very much faster than LISP and can call upon all the features available in the C programming language. However, development in this manner usually requires a much higher level of programming knowledge and the need to obey specific requirements when interfacing your application to the host CAD program.
VBA falls neatly into the middle of these two options. It is reputed to be only marginally slower in processing speed than ARX, and only slightly more complex to learn than LISP. In fact, the real issue is one of difference rather than complexity. Someone who has only ever used LISP will find VBA attacks things from a completely different direction. In terms of program code it is probably much easier than LISP, with the IDE (Integrated Development Environment, or Editor screen) presenting the most obvious difference. VBA also provides very easy mechanisms to add full featured dialogue boxes and other user interface functions to give programs a very professional look.
The next question to be addressed is, how do we access VBA in IntelliCAD? We first have to install it. My advice here will relate directly to the IntelliCAD Professional 2000 by CADopia, though other versions should be very similar. CADopia only provides VBA support in their “Professional” version, so this wont work if you’re using the “Standard” version of the program. I’ve also not yet determined if their recently release 2001 version has any fundamental changes to it, though I doubt this would be the case.
The biggest problem with installing VBA is that the procedure is not very well documented anywhere. Once you know how, it’s quite simple. Installation has to be done manually, after the IntelliCAD program itself has been installed. So one must first install IntelliCAD, if this hasn’t already been done. Then, take a look at the sub-directories under the main IntelliCAD root directory. You should find a sub-directory named “RELEASE”. In this will be a file named “VBA6.MSI”. This is the VBA installation program.
What you do next will depend on how the copy of Windows on your particular computer has been set up, and on what programs it may have run in the past.
My recommendation is to do the following. First, start the Windows File Manager. Then find the “VBA6.MSI” file in the “RELEASE” sub-directory and double-click on it. This should cause Windows to run the file, or to give you an error message advising it doesn’t know what application to use with this file. If the file runs, then that’s great because you have just successfully installed VBA and don’t have to worry about anything in the following paragraph.
If you get the error message then it will be necessary to run another program first, then to run the “VBA6.MSI” file. You will now need to check in the “MSI” sub-directory below the “RELEASE” sub-directory. This should contain two program files, named INSTMSI.EXE and INSTMSIW.EXE. You will need to run the first file if you’re using Windows 98 (or similar), and the second file if you’re using Windows NT (or similar). Run the program by double-clicking on the file name in the Windows File manager. Not much visible should happen when the program runs. Then, return to the “VBA6.MSI” file and double-click on it again. This time it should run and VBA will be installed.
Finally, reboot your computer. This final step may not be necessary but it’s easier to do it than not, if only for peace of mind. We have now installed VBA for IntelliCAD.
There is one final step to perform. It will be necessary, assuming you’re using the standard IntelliCAD screen menu, to select OPTIONS from the TOOLS menu pulldown. Then, on the GENERAL tab, set the Experience Level to “Advanced”. This will cause a “Visual Basic” menu entry to be available from about midway down the TOOLS pulldown.
While the VBA Editor can be directly accessed from the TOOLS menu, it can also be called from the program’s command line. There are several commands available, all named to approximately correspond with the equivalent VBA commands to be found in AutoCAD, although in some cases their functions are quite different. These commands are, VBA or VBAIDE – call up the VBA Editor Screen VBALOAD or VBAUNLOAD – call up the Add In Manager Dialogue Box VBARUN – call up the dialogue box to run a VBA macro (program) You can also use the variation, “-VBARUN” to call up a program without displaying the dialogue box on the screen.
In short, you use VBA to get the Editor up for programming, and use VBARUN to cause the program to execute. The VBALOAD/VBAUNLOAD options bring up a menu which appears to involve the loading of external “Add In” program modules (DLL’s), which can be created in a standalone copy of Visual Basic, and for which I still need to learn more. In general there is a lack of any useful documentation for much of the IntelliCAD VBA implementation, but any prior knowledge of Visual Basic is a major benefit.
The final subject we will cover here is how to get a VBA application to run from a menu. Although we’ve not touched on any programming here, we will address some examples of VBA applications in the next installment of these articles.
We will prepare a small (one item) pulldown menu to load and execute a VBA application. This following menu code is for a simple menu, to be appended to the existing IntelliCAD menu, which will run an application function called “LoadApp” located in the “CommonProjects.vbi” file in IntelliCAD (more about the “CommonProjects” file in the next instalment).
* **POP1
[Test]
[Run Application]^C^C-VBARUN;LoadApp;
When this menu file is appended (import the file with the “append” check box set, using the CUSTOMISE option in the TOOLS pulldown) to your existing menu, a new menu item called “Test” will be available. When this is selected an option called “Run Application” will be presented. If this is selected a function called “LoadApp” will be run from the program code stored in the “CommonProjects.vbi” file located in the IntelliCAD base directory. The suffix “VBI” is given to IntelliCAD VBA programs. These can be associated with a specific drawing file, in which case a file with the same name as the drawing file will be created, but with the “VBI” file suffix, or they can be common to all drawings, in which case they are placed in the “CommonProjects” file.
Although we’ve covered several unrelated, and possibly confusing, items here, anyone with familiarity in Visual Basic should now have enough information to be able to start exploring VBA in IntelliCAD. For the rest, there will be more articles in this series where we will introduce the use of Visual Basic for Applications and how it can be applied to perform practical operations within IntelliCAD.
1. Introduction
We saw on the previous page how to set up VBA to run within IntelliCAD, and briefly discussed some of the benefits of using VBA. It’s now time to look at some simple programming examples, to get a feel for how VBA can be used practically.
It is assumed that the reader of this article has at least a passing familiarity with Visual Basic and the VBA IDE (Integrated Development Environment). If you don’t know how to create a Visual Basic form and add a button to it then it may be best to find this out before proceeding further here. The aim of this article is to describe the use of VBA in IntelliCAD, and not to present an introduction to Visual Basic.
The code for the examples here is presented in this article, but can also be accessed as a CommonProject file, or in the source code linked from the Resource Center.
If the description here is a little confusing then you should download the “CommonProject.vbi” file, copy it to your IntelliCAD directory (the place on disk where the Icad.exe file is located) and the application can then be run, and the code viewed in the Visual Basic Editor (VBA IDE).
2. Setting Things Up
Before we can perform any practical programming we need to first set up our VBA program so it can communicate with the IntelliCAD drawing. We need to set an object so we can use it to easily reference the drawing later on.
For the purposes of this article we will create a test program which can be accessed by any IntelliCAD drawing, so we need to enter the VBA Editor (from the Visual Basic menu option on the TOOLS pull-down menu). Then we need to add a new form under the “CommonProjects” section in the Project window.
Display this form on the screen and add a button to it. Now we’re ready to start. First, double-click on the form to display the code window for the “UserForm_Initialize” function. Within this you need to type the following,
‘ Set up drawing document
‘——————————–
Private Sub UserForm_Initialize()
Set Doc = IntelliCAD.ActiveDocument
End Sub
The comment lines are provided here for convenience and don’t need to be typed in. This line sets an object called “Doc” to represent an IntelliCAD document, which is effectively the IntelliCAD drawing file. The “UserForm_Initialize” function is called every time this form gets loaded, so every time you run the program this line of code will be executed, establishing a link between IntelliCAD and VBA.
We now need to define what the object “Doc” is. This is best done in a separate code module, as we will also need this module to provide a means to easily start the program from IntelliCAD. Create a module called MODULE1.BAS in the Editor.
To this add an initial line to globally define the object “Doc” to be an IntelliCAD document. By globally defining this we can refer to “Doc” anywhere in our program and it will be understood to refer to the IntelliCAD drawing. That is,
‘——————————–
‘ Load a user form automatically
‘——————————–
Sub LoadApp() Load UserForm1 UserForm1.Show
End Sub
Below this line we define a subroutine called “LoadApp”, as shown in the code above. This will be used later to make loading the application in IntelliCAD much more elegant. Effectively, when you call the “LoadApp” subroutine the user form called “UserForm1” will be loaded and displayed. This form is the form we will be placing our test functions on. This is the entire contents of the code module.
If we now return to our form (UserForm1) we can add a button to it, if we haven’t already done so. We can call this button “Exit” and behind it we will add some code to close the program, as follows;
‘ Close the form
‘——————————–
Private Sub CommandButton1_Click()
End End Sub
This makes up the core code needed in order to start doing useful things, so now we need to do something with it.
3. Accessing Some Drawing Information
The best, and simplest, starting point is to just extract some information from a drawing file and display it on the screen. The most basic data we can access is the name of the current drawing file. Create a new button on the form and give it the caption “Drawing Name”. Also add a text box to the form, so we have somewhere to display the drawing name once we’ve extracted it. Behind the button type the following code;
‘————————
‘ Get the current drawing name
‘————————
Private Sub CommandButton2_Click()
UserForm1.TextBox1.Text = “Drawing Name: ” + Doc.Name End Sub
That’s all there is to it. When you run the program and select the button the drawing name will be displayed in the text box on the form. The variable “Doc.Name” references the drawing name (it gets the “Name” property from the “Doc” object). This is then concatenated with the text string “Drawing Name: ” and assigned to the text box’s “Text” property.
We can access the current drawing layer name in a similar way. Create another button on the form, label it “Current Layer Name” then type the following code behind the button.
‘——————————–
‘ Display layer name
‘——————————–
Private Sub CommandButton3_Click() Dim LayerName As String LayerName = Doc.ActiveLayer.Name MsgBox “Layer: ” + LayerName End Sub
When selected this button will display the current drawing layer name in a message box on the screen. We could perform this function in a single line of code, as before, but here we’ll take things a bit slower. We first define a local string variable called “LayerName”, so we can store the name somewhere. We may wish to use the value later. We then access the “ActiveLayer” and get its “Name” property, storing this in the “LayerName” string variable. Finally we display this using the Visual Basic “MsgBox” command.
Note that we defined the “Doc” object mainly to make life easier, and reduce the amount of typing required, and also the program complexity. We could have just as well obtained the current layer name using the command,
IntelliCAD.ActiveDocument.ActiveLayer.Name
instead of,
Doc.ActiveLayer.Name
It should be apparent that part of the trick in programming in VBA with IntelliCAD is in just knowing, or remembering, the properties available for the various functions. There is not a great deal of documentation available for VBA in IntelliCAD, so much programming comes down to trial-and-error, or finding and learning from other people’s code examples. As you build up experience you’ll also build up a library of useful code which can be easily reused in many situations.
4. Accessing a Variable
Having accessed the drawing and current layer names, we can now progress a little further. Now we will access a drawing variable. For convenience, we will seek to obtain the AutoCAD/IntelliCAD drawing version number. This is virtually the same as for accessing the layer name, but we’re using a different VBA command. As before, create a new button on the form, label it “Version Number” and type the following code behind it.
‘ Display a Variable
‘——————————–
Private Sub CommandButton4_Click()
Dim Ver As String Ver = Doc.GetVariable(“ACADVER”) MsgBox “Version: ” + Ver End Sub
Again we set a string variable, to store the value we obtain. We now use the “GetVariable” function to extract the variable value we require. This value will be “ACADVER”, which is the standard variable name you would use to access a variable from the IntelliCAD command line. We then display this value in a message box on screen. You could use this same function to display any drawing variable, simply by altering the variable name requested.
5. Drawing a Line
We should now be becoming more familiar with the basics of how to interact with the drawing file from within VBA. For this example, instead of extracting values from the drawing, we will progress to creating drawing entities, beginning with a single line. As before, create a new button on the form, label it “Draw Line” and type the following code behind it.
‘ Draw a Line
‘——————————–
Private Sub CommandButton5_Click()
Dim Lin As IntelliCAD.Line
Dim StartPt As IntelliCAD.Point
Dim EndPt As IntelliCAD.Point Set StartPt = Library.CreatePoint(0, 10, 10) Set EndPt = Library.CreatePoint(10, 10, 0) Set Lin = Doc.ModelSpace.AddLine(StartPt, EndPt) Lin.Update End Sub
This operation is a little more complex. We need to define some input data, this being a start point and an end point for the line. We can then create the line itself. To integrate with IntelliCAD we need to define a variable called “StartPt” and another called “EndPt” as IntelliCAD “Point” objects. The variable names can be anything you like, but they must be defined as “IntelliCAD.Point” objects. We also need to define an IntelliCAD line object, called “Lin” here.
We then need to set the X, Y and Z coordinates of the start and end points. This is done using a general IntelliCAD Library function called “CreatePoint”. We will be drawing a line between the points 0, 10, 0 and 10, 10, 0. Having defined these two points, we now wish to add a line entity to our drawing and we wish to add it in modelspace. So we use the “AddLine” method, to create a modelspace line, from the “StartPt” coordinate to the “EndPt” coordinate. Finally we need to “Update” the line object to make sure it gets displayed.
While this may sound a little messy just to draw a line between two points, it must be remembered we are writing a computer program, and the program can employ custom functions. We could adjust the code here to create a “DrawLine” function, and encase the above into a custom function which just requires 6 numbers to be submitted (2 sets of coordinates) in order to draw the line.
It should be mentioned here that how points are handled is the main difference between AutoCAD’s implementation of VBA and IntelliCAD’s VBA. In general, in VBA, AutoCAD stores 3D coordinates as values in an array;
while IntelliCAD explicitly defines them as properties of a value;
Although mentioning this may be a bit premature, it is worth knowing that because of this AutoCAD and IntelliCAD VBA programs are not likely to be compatible with each other, even though the VBA programming interface they use is fundamentally the same.
6. Drawing a Circle
To draw a circle is virtually the same as drawing a line.
Create a new button, label it “Draw Circle” and type the following code behind it.
‘ Draw a Circle
‘——————————–
Private Sub CommandButton6_Click()
Dim Circ As IntelliCAD.Circle
Dim CenPt As IntelliCAD.Point
Dim Rad As Double Set CenPt = Library.CreatePoint(0, 10, 10) Rad = 8# Set Circ = Doc.ModelSpace.AddCircle(CenPt, Rad) Circ.Update End Sub
Based on our previous comments regarding the operation of the function to create a line, this code should be fairly clear to understand. We define a centre point and then add a circle to the drawing using the “AddCircle” function.
7. Running the Program
Having presented several simple examples of programming in IntelliCAD using VBA we now really only need to explain the relevance of the “LoadApp” function we included when we first created our core code. This relates to our closing remarks in the previous article, which can be found at, http://www.cadinfo.net/icad/VBA-1.htm
LoadApp in IntelliCAD The IntelliCAD Screen showing the Macro form used to load VBA functions. Note the “LoadApp” function is available for loading our test program.
To start a VBA function from the IntelliCAD command line, or from a menu, we use the “-VBARUN” command. This requires us to specify a macro name to be run. Here, “LoadApp” is the macro name. So when the “-VBARUN” command is entered, and the “LoadApp” macro name is provided, VBA will load that function.
The function will then load the UserForm1 form, which will display our test program on the IntelliCAD screen. The program will persist until the “Exit” button is selected, at which point the program will shut down.
Let’s see how to draw 3D face and text entities, as a continuation of the previous article. We will then progress on to how to work with entities, get points on the display screen and how to use object snap modes within a program.
Building a 3D Face
As a progression from drawing lines and circles, we will now consider how to create two more entity types. By looking at all four entity creation routines it should start to become obvious that there is an underlying structure present. This involves first defining the various variable types, then giving specific values to these variables. An entity is then “added” to the drawing, being first defined using some form of “AddEntity” command, then “updated” so it appears correctly within the drawing file.
‘ Draw a 3DFACE
‘——————————————————
Private Sub CommandButton2_Click()
Dim Face As IntelliCAD.Face3D
Dim Pt1 As IntelliCAD.Point
Dim Pt2 As IntelliCAD.Point
Dim Pt3 As IntelliCAD.Point
Dim Pt4 As IntelliCAD.Point
Set Pt1 = Library.CreatePoint(0, 0, 0)
Set Pt2 = Library.CreatePoint(10, 0, 0)
Set Pt3 = Library.CreatePoint(10, 10, 0)
Set Pt4 = Library.CreatePoint(0, 10, 0)
Set Face = Doc.ModelSpace.Add3DFace(Pt1, Pt2, Pt3, Pt4)
Face.Update
End Sub
‘——————————————————
In the case of the above routine, we first define one variable as a “Face3D” type, and four point variables. We then supply coordinates for the four points, using the IntelliCAD “CreatePoint” function. Next we set the “Face3D” variable (called “Face” here) to be the 3DFACE defined by the four points, then finally we “Update” the entity, and we have a 3DFACE added to thedrawing.
There are a substantial number of functions available to add various entity types to a drawing file. The following is a list of those available within IntelliCAD VBA;
2D Entities
AddArc, AddCircle, AddEllipse, AddInfiniteLine, AddLine, AddMText, AddPointEntity, AddLightWeightPolyline, AddPolyfaceMesh, AddPolyline, AddRay, AddSolid, AddSpline, AddText, AddTrace
3D Entities
Add3DFace, Add3DMesh, Add3DPoly, AddBox, AddCone, AddCylinder, AddWedge, AddTorus, AddSphere
Dimensioning
AddDim3PointAngular, AddDimAligned, AddDimAngular, AddDimDiametric, AddDimOrdinate, AddDimRadial, AddDimRotated, AddLeader, AddTolerance,
Other Entities
AddAttributeDef, AddHatch, AddImage
Creating Some Text
To reinforce the basic structure of functions which create new drawing entities, we will finally create a simple function to write some text on the screen. As we’ve already described, we first define the variables we will use, then set values for them.
That is, we need an insertion point for the text, plus a text height, then the actual string of text to be printed. The text is then created using the “AddText” function, then set with an “Update” command, as follows,
‘ Draw some Text
‘——————————————————
Private Sub CommandButton3_Click()
Dim Txt As IntelliCAD.Text
Dim InsPt As IntelliCAD.Point
Dim Stext As String
Dim Ht As Double
Set InsPt = Library.CreatePoint(0, 0, 0) ‘ insertion pointHt = 3.5 ‘ text height
Stext = “Hello” ‘ text string
Set Txt = Doc.ModelSpace.AddText(Stext, InsPt, Ht)
Txt.Update
End Sub
‘——————————————————
Picking an Entity on the Screen
One of the key requirements for a programming language operating within a CAD program is interactivity. We need our programs to be able to interact with the program user in order to perform many operations. So we now need to introduce a few commands which enable us to interact with entities on the computer screen. First we will consider how to select an object on the screen and find out what it is. For this operation we need to use a function called “GetEntity”. The following code is a simple example of how to implement this.
‘ Pick an entity
‘——————————————————
Private Sub CommandButton4_Click()
Dim PickObj As IntelliCAD.Entity
Dim Pt1 As IntelliCAD.Point
Dim Ename As String
UserForm1.Hide
Doc.Utility.GetEntity PickObj, Pt1, “Pick an Object”
Ename = PickObj.EntityName
MsgBox “Name: ” & Ename
MsgBox “Selected Point: ” & vbCrLf & “X: ” & Format(Pt1.x, “0.00”) & vbCrLf & “Y: ” & Format(Pt1.y, “0.00”) & vbCrLf & “Z: ” & Format(Pt1.z, “0.00”) & vbCrLf
UserForm1.Show
End Sub
‘——————————————————
There are several features in this function which need to be discussed. Because we’re asking the computer user to select a point on the computer screen, we need to first display our dialogue box for them to select an option, then hide it temporarily so the user has free access to the whole screen. This is the reason there is a “UserForm1.Hide” command, which is executed before we ask for an entity to be selected. After all processing is complete we redisplay the dialogue box with a “UserForm1.Show” command, so the user can proceed to select another command. Here we are assuming the pick command is implemented from a VBA form (dialogue box) called “UserForm1”.
The “GetEntity” function has three parameters. The “PickObj” parameter returns an identifier for the entity selected. The “Pt1” parameter returns the actual point location which was selected, while the third parameter is a text prompt, which displays on IntelliCAD’s command line, provided to the user to advise them what to do. Note that “PickObj” and “Pt1” are our own variable names here. You are not obliged to use these particular names when you use the “GetEntity” function.
The reason both a point location and an entity identifier are returned is that in some situations the actual point selected may be relevant to further processing which may take place.
In our example, having selected an entity, we will simply tell the user what type of entity was selected. So we access the “EntityName” property of our selected entity, then display it on the screen in a standard Visual Basic message box. We could then move into the entity and extract its particular data, but we will leave that exercise for a later article. We also display the coordinates of the point which was picked, again using a standard Visual Basic message box. Picking a Point on the Screen
We also need to be able to select points on the computer screen.
The following routine shows the operation of this “GetPoint” function. It expects one or two parameters, optionally. There is a text string passed which is a prompt to appear on the IntelliCAD command line, and an optional point location. This is directly equivalent to the Lisp command, with the optional point value defining a location from which a “rubber band” line will originate. When this routine is executed, a rubber band line will appear, anchored at the origin (0,0,0) and moving in response to the mouse cursor. When the mouse button is pressed that screen point is returned and the rubber band line then becomes a fixed line between the origin and the selected point.
‘ Pick a point on the screen
‘——————————————————
Private Sub CommandButton5_Click()
Dim Pt1 As IntelliCAD.Point
Dim PickPt As IntelliCAD.Point
Dim Lin As IntelliCAD.Line
UserForm1.Hide
Set Pt1 = Library.CreatePoint(0, 0, 0)
Set PickPt = Doc.Utility.GetPoint(Pt1, “Pick a Point”)
MsgBox “Selected Point: ” & vbCrLf & “X: ” & Format(PickPt.x, “0.00”) & vbCrLf & “Y: ” & Format(PickPt.y, “0.00”) & vbCrLf & “Z: ” & Format(PickPt.z, “0.00”) & vbCrLf
Set Lin = Doc.ModelSpace.AddLine(Pt1, PickPt)
Lin.Update
UserForm1.Show
End Sub
‘——————————————————
As previously, we are interacting with the user’s display screen, so we are required to clear any dialogue boxes from the screen before any on-screen selections can be made, using the “UserForm1.Hide” command. We recover the dialogue boxes after we’ve finished, using the “UserForm1.Show” command.
We first define the origin point (0,0,0) so we can use it for the anchor of the rubber band line. We then implement the “GetPoint” command and store the selected point in a variable called “PickPt”. We display the coordinates of this point to the user with a VBA message box, then finally draw a line bewteen the selected point and the anchor point, using the “AddLine” function.
Note that if the rubber band line is not required, the “Pt1” value is just not provided, but the comma between the two parameters is still necessary, as shown here,
Now we can pick a point and draw a line. If we’re asking the user to select points on the screen we cannot be sure they will provide accurate point locations, so we should ideally use Object Snap (OSNAP) modes to return accurate point selections. The next example illustrates one way to do this. The method shown here is not the best one, but it helps to illustrates some IntelliCAD VBA functions.
The general objective of the following function is to draw a circle of radius 1.0 unit, with its centre point located at the end of a line. The centre point is located on the end of the line using OSNAP to find the nearest endpoint.
As usual, we first define our variables, then hide the user form.
Here we’ve also added the line “On Error Resume Next” to give some degree of fault tolerance should a bad snap selection be made. We then create a new circle centred on the selected point, using the “AddCircle” command.
‘ Snap to end of line and draw a circle
‘——————————————————
Private Sub CommandButton6_Click()
Dim Pnt1 As IntelliCAD.Point
Dim Circle1 As IntelliCAD.Circle
On Error Resume Next
UserForm1.Hide ‘ temporarily hide the form
Doc.ObjectSnapMode = True ‘ turn on osnap mode
Set Pnt1 = Doc.Utility.EntitySnap(Doc.Utility.GetPoint(, “Select Center:”), vicOsnapEnd)
Doc.ObjectSnapMode = False ‘ turn off osnap mode
Set Circle1 = Doc.ModelSpace.AddCircle(Pnt1, 1#)
Circle1.Update
UserForm1.Show ‘ redisplay the form
End Sub
‘——————————————————
The key functions here are the “ObjectSnapMode = True/False” and the “EntitySnap” functions. The former is a switch used to turn the OSNAP mode on or off within VBA. It’s equivalent to the standard IntelliCAD commands “OSNAP ON” and “OSNAP OFF” which you would typically enter on the command line. The “EntitySnap” function takes a point and applies an OSNAP mode to it. So if we had a point called “Pt1” and we wanted to apply OSNAP ENDP to it, the command would be,
which should return a new point “Pt2” which is the result of looking for an endpoint near the point “Pt1”. If there is no valid point found, an error would occur. This is why we need to use the “On Error Resume Next” statement, to avoid the function failing within IntelliCAD in this situation, crashing and reporting an error condition.
Because we’re in the process of picking a point on the screen, we use the whole “GetPoint” command in place of the “Pt1” point. So we’re effectively saying,
Now, provided you select a point very near to the end point of a line, this example function will work correctly, but with one restriction. In the normal course of events OSNAP provides a target (aperture) box to let you know the active region for point picks. In this particular case the target box is not displayed, which is a nuisance. I’m not sure whether this is intentional, or a bug in the VBA implementation, or there is some other way to display the target box. Fortunately there is a better way to use OSNAP.
Using Object Snap more Elegantly
Using the same basic function as before, with the same objective of drawing a circle at the end of a line, the following routine performs this operation far more elegantly. It relies on us defining two general functions, to turn OSNAP on and off in a different way. While the “ObjectSnapMode = True/False” command is an internal command within IntelliCAD’s VBA, we are also able to alter OSNAP by manipulating the standard program variables. So, by setting the program variable OSMODE we can do various things with the object snap modes. This method has the key benefit that it displays the target box when OSNAP is active.
‘ Osnap example function
‘——————————————————
Private Sub CommandButton7_Click()
Dim Pnt1 As IntelliCAD.Point
Dim Circle1 As IntelliCAD.Circle
On Error Resume Next
UserForm1.Hide ‘ temporarily hide the form
Osnap_On (vicOsnapEnd + vicOsnapCenter)
Set Pnt1 = Doc.Utility.GetPoint(, “Select Center: “)
Osnap_Off
Set Circle1 = Doc.ModelSpace.AddCircle(Pnt1, 2#)
Circle1.Update
UserForm1.Show ‘ redisplay the form
End Sub
‘——————————————————
‘ Turn on OSNAP modes
‘——————————————————
Sub Osnap_On(IntVal As Integer)
Doc.SetVariable “OSMODE”, IntVal
End Sub
‘——————————————————
‘ Turn off all OSNAP modes
‘——————————————————
Sub Osnap_Off()
Doc.SetVariable “OSMODE”, vicOsnapNone
End Sub
‘——————————————————
Here we’ve written two very small functions to handle the OSNAP operation. We have a new function now, called “Osnap_Off”, which will turn OSNAP off with a single call. We also have a complementary function, called “Osnap_On”, which will turn OSNAP on with any set of filters you may require. Internal to IntelliCAD’s VBA are a range of standard names for constants.
There is a set defining all the available OSNAP modes, listed as follows,
0 = Clear entity snaps = vicOsnapNone
1 = Endpoint snap = vicOsnapEnd
2 = Midpoint snap = vicOsnapMid
4 = Center snap = vicOsnapCenter
8 = Point snap = vicOsnapNode
16 = Quadrant snap = vicOsnapQuadrant
32 = Intersection snap = vicOsnapIntersection
64 = Insertion point snap = vicOsnapInsert
128 = Perpendicular snap = vicOsnapPerpendicular
256 = Tangent snap = vicOsnapTangent
512 = Nearest snap = vicOsnapNear
1024 = Quick snap = vicOsnapQuick
4096 = Plan view intersection snap = vicOsnapPlanViewIntersection
For the above list, the integer value on the left can be used to define an OSNAP mode, or the text value on the right. The actual modes are described in the centre. While there’s a lot less typing involved in using the integer values, the text values are far more descriptive and helpful if you find you have to edit your code a long time after it was originally written. Hence, using our new “Osnap_On” function, we could enable the command OSNAP ENDP with either of the following two commands,
Osnap_On (1)
We can also combine multiple modes, as follows,
With this revised means of setting OSNAP we now only need to use the standard “GetPoint” function to pick a point and have OSNAP operate the same way it does in normal, manual drawing operations.
Example Program Code
For readers of this article who are interested in trying out the examples presented, but would rather not have to type them into their system, the file “CommonProjects.Vbi” is provided. This, when placed in your standard IntelliCAD directory, will cause the examples to be available when you run IntelliCAD. Note that the “CommonProjects.Vbi” file is loaded when IntelliCAD is first started, but it is a file common to all projects and you may already have a copy on your system, being used for some other application. You may temporarily rename the other one while you try these examples, then rename things back again afterwards.
Alternatively, three source code files are provided, as follows,
UserForm1.Frm
UserForm1.Frx
Module1.Bas
Download all files (zip archive)
Note that the FRM and BAS files are text files while the FRX file contains the dialogue box data and is a binary file. These 3 files can be loaded into IntelliCAD’s VBA, within the VBA Editor using the “Import” command. They are the component parts, and could be used to create a new “CommonProjects.Vbi” file.
The next page describes a function to create or set drawing layers, and will be the start of the creation of a set of standard utility functions, to make general VBA programming quicker and easier.
This page describes the manipulation of layers in VBA, and present a function to create or set drawing layers. It also marks the beginning of the creation of a library of standard utility functions, to make general VBA programming in IntelliCAD quicker and more convenient.
The functions and examples presented here are included in a single VBA project. The screen for this, when running, is shown below, while the files themselves comprise either the executable code (which contains the program code), in the file,
CommonProjects.Vbi
or the individual source code files,
UserForm1.Frm
UserForm1.Frx Module1.Bas
These files can be downloade in a single zip archive on teh previous page.
Note that if you want to use the “CommonProjects.Vbi” file you will have to copy this into your IntelliCAD directory. There may already be a file of this name in the directory, so you should rename the existing file. It might be dangerous to delete it as it may be part of some other application.
Getting the Current Layer Name
We’ll start by just getting the current layer name (the name which is the currently active drawing layer) and displaying that on the screen. This function has been presented previously, but makes a good point from which to expand on the subject of drawing layers.
‘ Display the current Layer name
‘———————————————————-
Private Sub CommandButton2_Click()
Dim LayerName As String LayerName = Doc.ActiveLayer.Name MsgBox “Layer: ” + LayerName, vbInformation
End Sub
‘———————————————————-
The function operation is very simple. We first define a variable, called “LayerName”, as a string. This will be used to store the actual layer name we get from VBA. We then use the “ActiveLayer” function and request its “Name” property. This returns us the name of the current drawing layer, which we store in the “LayerName” variable. Finally we display this on the computer screen using the standard VBA “MsgBox” (Message Box) command.
Our example “Layer Function” program’s dialogue box, open on the IntelliCAD screen. Our example “Layer Function” program’s dialogue box, open on the IntelliCAD screen.
Getting an Entity Layer Name
While it’s nice enough to be able to get the currently active drawing layer, it would be far more useful to get a display of the drawing layer for any entity. That is, if you were to pick an entity, then its layer would be displayed. The following function will perform this task.
‘ Pick an entity and display the layer name
‘———————————————————-
Private Sub CommandButton6_Click()
Dim PickObj As IntelliCAD.Entity
Dim Pt1 As IntelliCAD.Point
Dim Ename As String UserForm1.Hide ‘ hide the form
Doc.Utility.GetEntity PickObj, Pt1, “Pick an Object” Ename = PickObj.EntityName MsgBox “Name: ” & Ename & vbCrLf & _ “Layer: ” & PickObj.Layer UserForm1.Show ‘ redisplay the form
End Sub
‘———————————————————-
Its operation should be fairly clear. We need to perform two basic operations. We first need to pick an object on the screen, which is done using the “GetEntity” function, then we need to get its layer name, which is accessed using the “Layer” property of the selected object.
The “GetEntity” function requires three parameters. The first is an entity object (called “PickObj” here), which is returned by the function and stores the entity information for the particular item picked. The second is a pick point, which is the location of your pick on the screen. This is returned by the function, and stored in the “Pt1” variable here. The third parameter is a prompt string, which will be displayed when the function executes.
We now have the entity data for an item which was selected on screen, and would like to get its name and layer. The name is extracted using the “EntityName” property of the selected object (PickObj). This value is stored in a variable called “Ename”. Note that the variables “Ename”, “PickObj” and “Pt1” have been previously defined at the start of this function.
Like the entity name, the entity layer is a property of the selected object (PickObj), so this is easily accessed by requesting “PickObj.Layer”. The entity name was obtained as a separate operation, whereas the layer name was obtained as part of the message box display function. This data can be accessed in various ways. If required, the message box function could just as easily have been rewritten as,
Also note the pair of commands,
UserForm1.Show ‘ redisplay the form
are used here to allow interactivity with the user. The form must be suppressed while the user selects an entity on the screen, to stop it getting in the way, then redisplayed after the selection has been made. This procedure has been described more fully in a previous article.
Also, when trying this function, it’s a good idea to first open an existing drawing, which contains a number of entities on different layers. A new drawing will not provide anything for you to test it on. Alternatively, create a test drawing comprising several lines, each on a different drawing layer.
Creating a New Layer
Having presented some ways to interrogate a drawing for information about existing layers, we now need to discuss how to create new layers. To add a new layer to a drawing requires a single command, as shown below.
‘ Create a New Layer called “TestLayer1”
‘———————————————————-
Private Sub CommandButton3_Click()
Dim Lyr As IntelliCAD.Layer Set Lyr = Doc.Layers.Add(“TestLayer1”) Lyr.Color = vicYellow
End Sub
‘———————————————————-
Here, we first need to define a layer object (called “Lyr” here) as an IntelliCAD Layer entity. We then use the “Layers.Add” function to create a new layer, this layer having the name defined in the single function parameter (the name “TestLayer1” here). Once the layer has been created we can manipulate its various properties by accessing and changing them, as shown in the last line of the function. Here we set the layer colour to be yellow, by setting the “Color” property of the “Lyr” layer entity to be “vicYellow”.
Note that “vicYellow” is a predefined constant in VBA which contains the numeric value for yellow. It’s easier to use (and remember) the “vicYellow” variable name than have to define it as a hexadecimal number. A Routine to Create or Set Layers
One of the most useful AutoLisp functions I ever wrote was a routine to create or set drawing layers. This operated by looking for a particular drawing layer. If it existed then it was made the current drawing layer. If it didn’t exist then it was created. When I moved to VBA this was one of the first functions I set out to create, and this is the function I shall now present.
The function is called “SetLayer” and its use is shown below.
‘ Create a new layer (using the SetLayer function)
‘———————————————————-
Private Sub CommandButton4_Click() SetLayer “FLANGE”, 1, “CONTINUOUS”
End Sub
‘———————————————————-
The function is called with three parameters. The first is the layer name, the second the layer colour and the third the line type for this layer. The function will look to see if a layer with the specified name exists. If it does then that layer will be set to be the current drawing layer. If the layer does not exist then a new layer of that name will be created, using the specified colour and line type. This function’s best feature is its flexibility. You don’t need to keep track of layer names as it will take care of itself.
The following are the functions making up “SetLayer” and are modified from code obtained from various other sources, so I don’t claim any ownership of this. I’ve simply adapted the functions to my specific requirements. There are three separate functions involved; the main “SetLayer” function, a function to check whether a layer exists and a function to set the required linetype. The main “SetLayer” function is as follows.
‘ Function to set an existing layer or create a new drawing layer
‘———————————————————-
Sub SetLayer(LayerName As String, _ LayerColour As Integer, _ LayerLineType As String)
Dim NewLayer As IntelliCAD.Layer
Dim RetLayer As Object Set RetLayer = Doc.ActiveLayer
‘ Return current layer ‘ If the layer does not exist then create it If LayerExist(LayerName) = False Then Set NewLayer = Doc.Layers.Add(LayerName) ‘ Create Layer NewLayer.Color = LayerColour NewLayer.Linetype = LayerLineType ‘ Linetype must already exist Set CurrentLayer = NewLayer End If
‘ The layer must now exist, so set it to be the current layer
Doc.ActiveLayer = CurrentLayer End Sub
‘———————————————————-
This function operates as follows. It first checks to see if the requested layer name already exists (using a function which will be described a little later). If it does not exist then a new layer is created using the “Layers.Add” function. It then has a colour assigned to it, and a line type (again using a function which will be described later). If the layer does exist then it is simply set to be the current drawing layer.
The function used to check whether the requested layer exists is as follows.
‘ Function to determine if a layer exists
‘———————————————————-
Function LayerExist(ByVal LayerName As String) As Boolean Dim Element As Object
LayerExist = False For Each Element In Doc.Layers
If Element.Name = Ucase(LayerName)
Then LayerExist = True Set CurrentLayer = Element
Exit For
End If
Next
End Function
‘———————————————————-
This is called with the specified layer name. A flag called “LayerExist” is initially set to be false, assuming the layer does not exist. We then move through each entry in the complete set (collection) of drawing layers, comparing their name to that of the layer we want. If we find a match then we set the flag to be true, set the layer to be the current drawing layer and exit the function. If we don’t find a match then the function will exit after all the existing layer names have been checked, with the flag still set to be false.
Finally, the third function we need is a function to set the layer line type, shown below. If you don’t need line types other than “CONTINUOUS” then this can be ignored and the appropriate line in the “SetLayer” function removed. Although this function should be able to load a new linetype, it is safer to have all the line types you may want to use already loaded into the drawing. It’s best to have these preloaded in your prototype (template) drawing file, so this routine will always work correctly.
‘ Function to load a new line type into the drawing
‘———————————————————-
Sub SetLineType(LineTypeName As String)
Dim entry As IntelliCAD.Linetype
Dim found As Boolean
found = False
For Each entry In ThisDrawing.Linetypes
If StrComp(entry.Name, LineTypeName, 1) = 0
Then found = True
Exit For
End If
NextIf Not (found)
Then ThisDrawing.Linetypes.Load LineTypeName, “ICAD.LIN”
End If
End Sub
‘———————————————————-
As with the function to check if a layer exists, this operates in a similar way. It sets a flag called “found” to initially be false, then progresses through all the linetypes in the drawing. If a match is found the flag is set to be true then the function exits. The linetype is actually set in the “SetLayer” function. This routine only checks whether it must load a new linetype. If no match is found the function attempts to load the requested linetype from the “ICAD.LIN” linetype file, then exits, for the new linetype to then be set in the “SetLayer” function.
As this is a generally useful function it should be included in a program module (MODULE1.BAS for example), as a public function, where it can be accessed from anywhere in your application.
The Sample Application
The code examples provided with this article illustrate the functions described above. However, the “SetLayer” code example does a little more than just display the function operation. We’ve included an example where you can choose a layer name and a layer colour from two list boxes, then create a new layer using these values with the “SetLayer” command. This is a better guide to how you may want to employ this function in your own code, and also a good illustration of the flexibility of the “SetLayer” command itself.
Finding More About the Commands Available in IntelliCAD VBA
Following the previous article in this series, which dealt with object snap modes, the question was asked, “How did I know about all the OSNAP variable names?”. There is very little documentation available for VBA in IntelliCAD, so what reference sources exist to help you find which commands and functions are available to you?
There is a degree of help available in the IntelliCAD HELP files. I’m basing this series on Cadopia’s version of IntelliCAD, so this may vary slightly from some other versions. If you access the HELP from the IntelliCAD drawing screen, and search through this using the Index, there are examples and information in there about how to use specific VBA commands.
Unfortunately, this assistance does not extend to the HELP system within the VBA Editor screen. In a typical Visual Basic Editor it would be possible to highlight a single word or command, then press the <F1> key and have an appropriate screen of information about that command displayed. In VBA here though, this would generally give you a message that there was no information available for the particular command.
To get a complete overview of the commands available for IntelliCAD within VBA, you will need to look at the “Object Browser”, accessed from within the VBA Editor screen. This is opened from one of the central icons on the top menu bar.
When selected, a dialogue box will appear displaying a list of all the functions available to you within VBA.
This is typically a long list, so we need to isolate only those commands relevant to IntelliCAD. This is done by selecting the list box in the top left of the Object Browser dialogue box and choosing “IntelliCAD”. Normally all the available function libraries are displayed, but we can limit the functions shown to only a single library, which is what we’ve done here.
How to select only the IntelliCAD function library in the Object Browser. Showing how to select only the “IntelliCAD” function library in the “Object Browser”. We are only interested in the commands related to IntelliCAD, so we need to remove all the other options from the display.
The purpose of the Object Browser is to allow you to see all the functions and associated items which are present in a particular library, and which you can access. For example, if we consider the case of our previous article, where I needed to find all the snap modes provided within VBA, and the constant names they had been given, then this can be done with the Object Browser. By selecting “ObjectSnapMode” in the left column I am then presented with all the available options in the right column.
The list of available Object Snap modes, accessed and displayed using the Object Browser. The list of available Object Snap modes, accessed and displayed using the “Object Browser”.
Although the Object Browser is not really an on-line help system, it does give an overview of the full range of functions available to you, and a general guide as to how they may work. So, at worst, you can determine a particular operation is available, but you may have to experiment a bit in order to get it to work properly.
The Object Browser does have one additional feature. It will offer a template as to how a particular function will operate. For example, if you select “Document” in the left column, the right column will display all the options available. If you then select, for example, the “GetVariable” function in the right column, the area at the bottom of the dialogue box will display the parameters which need to be passed to this function, their type and the value which would be returned. In this case, the “GetVariable” function will need to have a variable name passed to it, in the form of a string, while the returned value will be the value of the chosen system variable.
Another example of using the “Object Browser”. Here we have found the “GetVariable” function for an IntelliCAD document. Note that the format of the function is displayed in the box at the bottom of the screen. This shows it requires a string variable to be passed to it (the variable name) and returns a system variable value. With just a bit of guesswork you can generally find out how most of the IntelliCAD VBA functions operate.
Conclusion
In this article we’ve addressed several issues related to handling layers in IntelliCAD’s VBA. We’ve also described a few ways to get a little more information about the functions which are available to you. In the next article we hope to present a simple programming application, to show how everything fits together.
Please help for gettign bounding box value in progeCad Lisp
(setq vlaobject_solid (vlax-ename->vla-object ename_solid))
(vla-getboundingbox vlaobject_solid ‘p1_cylbot ‘p1_cyltop)
(setq p1_bot (vlax-safearray->list p1_cylbot))
(setq p1_top
(vlax-safearray->list p1_cyltop))
Please help for solving the problem of converting ProgeCad entity to vla object
Thanks and Regards
Vilas Jadhav
+91 9766471794
Hi
I have working with Autolisp and AutoCad
I have use function for getting bounding box in lisp
(setq vlaobject_solid
(vlax-ename->vla- object ename_solid))
(vla-getboundingbox
vlaobject_solid ‘p1_cylbot ‘p1_cyltop)
(setq p1_bot
(vlax-safearray->list p1_cylbot))
(setq p1_top
(vlax-safearray->list p1_cyltop))
But In ProgeCad lisp I have not able to conver autocad entity to vla entity
Please Help for converting entity to vla object in progeCad
Thanks and Regards
vilas Jadhav
9766471794
[email protected]