| Visual Basic for Applications in IntelliCAD - Page 3 |
Page 3 of 4
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 FaceAs 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 3D Entities Dimensioning Other Entities Creating Some TextTo 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 ScreenOne 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, Set PickPt = Doc.Utility.GetPoint(, "Pick a Point") Using Object Snap
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, Set Pt2 = Doc.Utility.EntitySnap(Pt1, vicOsnapEnd)
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, Set Pt1 = Doc.Utility.GetPoint(, "Select Center: ")
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 ElegantlyUsing 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 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 (vicOsnapEnd)
Osnap_On (1) We can also combine multiple modes, as follows, Osnap_On (vicOsnapEnd & vicOsnapMid & vicOsnapNode)
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 CodeFor 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. UserForm1.Frm 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. |