Visual Basic for Applications in IntelliCAD
Part 3
John McIver
The third in a series of articles introducing custom programming of IntelliCAD and AutoCAD using Visual Basic for Applications (VBA)
The first
article described how to initially set up the VBA facility within
IntelliCAD and gave an overview of its benefits over other programming
options. www.cadinfo.net/icad/VBA-1.htm
The second article introduced some basic IntelliCAD commands, implemented
using VBA, such as how to draw lines and circles. www.cadinfo.net/icad/VBA-2.htm
This article will show the way 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 point
Ht = 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.
This is done using a "GetPoint" function. For those familiar with
Lisp programming in IntelliCAD, but still coming to terms with
VBA, a useful tip is that there is generally an equivalent
function in VBA to each of those available in Lisp. So the
"GetPoint" function in VBA equates closely to the
"GetPoint"function in Lisp.
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 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 (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 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
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 article will describe 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.

|
Sponsored Links |
<% Call SelectBanner("sponsoredlinks") %>
AnyDWG Offers DWG to PDF, DWG to DXF, PDF to DWG, DWG to JPG, PDF to DXF Converters
|
AutoDWG offers DWF to DWG, DWG to PDF , PDF to DWG,
DWG to Flash Converters, DWG Viewer.
|
eCampus.com
Get your stuff for College... Cheap!
Textbooks, Greek Gear, DVD's, University Clothing, Computers and MORE!
|
Access Your PC from Anywhere
Free Trial plus 10% Off!
|
|
|
|
|