Introduction to MicroStation

MicroStation® is a 3D computer-aided-design (CAD) application for personal computers and workstations. MicroStation is produced by Bentley Systems, Inc.

MicroStation can be customised in various ways. This article shows how to set a MicroStation Snap Mode with MicroStation Visual Basic for Applications (MVBA).

MicroStation: Snap Mode Buttons

MicroStation's Snap Mode enable you to draw some graphic object by snapping to another object. For example, you may want to snap the start point of one line to the mid-point of another line. Setting the Snap Mode (or snap lock) to mid-point enables that action.

Using MDL Functions from VBA

Not all MicroStation functionality is available directly through VBA. MicroStation's Snap Mode setting falls into that list of omissions. Fortunately, for these uncommon cases, we can fall back on the MicroStation Development Library (MDL). MDL is a C/C++ API, but VBA can use its functions provided the appropriate declarations are made in your VBA modules.

In this case we need to declare the MDL function mdlParams_setLock. Once we've declared a function, we can use it in our VBA code. Here's the VBA declaration for mdlParams_setLock, taken from the MDL function reference help documentation …

Declare PtrSafe Function mdlParams_setLock Lib "stdmdlbltin.dll" ( _
 ByRef lockVal As Long , _
 ByVal paramName As Long ) As Long

The function declaration should be copied to your VBA code module. It should be placed near the top of the module, before any VBA procedure definition.

Note: The MDL documentation tells us to pass the first parameter ByVal. This is incorrect: use the ByRef keyword as shown above.

Thanks go to the developers of PHOCAD and eagle eye technologies for pointing that out.

Snap Mode Constants

We need to define a number of integer constants that are used by that MDL function. I haven't simply invented these values — they are taken from a couple of the MDL header files. MDL header files are installed with the MicroStation SDK. If you haven't installed that SDK the header files won't be available on your computer. That should not be a problem because I've translated the definitions from MDL to VBA.

The name of the lock setting is ACTIVEPARAM_SNAPMODE, defined like this …

' ACTIVEPARAM_SNAPMODE is defined in MDL header file <mdl.h>
Public Const ACTIVEPARAM_SNAPMODE As Long = 501

That lock setting takes one of a combination of values from the list below. The list is defined as an enumeration …

' SNAP_MODE_XXX values are defined in MDL header file <msdefs.h>
Public Enum SnapModeVals
    SNAP_MODE_FIRST = 0
    SNAP_MODE_NEAREST = 1
    SNAP_MODE_NEAREST_KEYPOINT = 2
    SNAP_MODE_MIDPOINT = 4
    SNAP_MODE_CENTER = 8
    SNAP_MODE_ORIGIN = 16
    SNAP_MODE_BISECTOR = 32
    SNAP_MODE_INTERSECTION = 64
    SNAP_MODE_TANGENCY = 128
    SNAP_MODE_TANGENTPOINT = 256
    SNAP_MODE_PERPENDICULAR = 512
    SNAP_MODE_PERPENDICULARPOINT = 1024
    SNAP_MODE_PARALLEL = 2048
    SNAP_MODE_POINTTHROUGH = 4096
    SNAP_MODE_POINTON = 8192
    SNAP_MODE_MULTI1 = 16384
    SNAP_MODE_MULTI2 = 32768
    SNAP_MODE_MULTI3 = 65536
End Enum

VBA Subroutine Wraps MDL Function

Now we have a function declaration and a list of values relevant to that function, we can write a VBA wrapper that hides the gory details. Here's an example VBA subroutine that set Snap Mode Nearest. You can adapt this wrapper to make your own VBA Snap Mode subroutines …

Public Sub SetSnapModeNearest ()
    mdlParams_setLock SNAP_MODE_NEAREST, ACTIVEPARAM_SNAPMODE
End Sub

Check Snap State

Check whether whether AccuSnap is currently snapped to an element using MDL function mdlAccuSnap_isSnapped. Here's its declaration …

Declare PtrSafe Function mdlAccuSnap_isSnapped Lib "stdmdlbltin.dll" ( ) As Long 

Here's a VBA wrapper function …

Public Function AccuSnapIsSnapped () As Boolean
    AccuSnapIsSnapped = 0 <> mdlAccuSnap_isSnapped
End Function

Check Snap Mode

See whether or not the user wants AccuSnap active. Here's its declaration …

Declare PtrSafe Function mdlAccuSnap_isUserEnabled Lib "stdmdlbltin.dll" ( ) As Long

Here's a VBA wrapper function …

Public Function AccuSnapIsUserEnabled () As Boolean
    AccuSnapIsUserEnabled = 0 <> mdlAccuSnap_isUserEnabled
End Function

Check Locate Enabled

Indicates whether AutoLocate has been enabled by the current tool. Here's its declaration …

Declare PtrSafe Function mdlAccuSnap_isLocateEnabled Lib "stdmdlbltin.dll" ( ) As Long

Here's a VBA wrapper function …

Public Function AccuSnapIsLocateEnabled () As Boolean
    AccuSnapIsLocateEnabled = 0 <> mdlAccuSnap_isLocateEnabled
End Function