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 find MicroStation Line Styles with MicroStation Visual Basic for Applications (MVBA).
MicroStation VBA has some support for line styles, but MDL provides more.
For example, the
DesignFile.LineStyles method obtains a list of line style names
available to the specified DGN file.
However, it doesn't tell you where that line style definition is located.
There are three possible sources where a line style definition could be stored …
StringList is, as you probably guessed, a list of strings.
However, they are stored in a C-style structure, are allocated dynamically
and are accessed by C-style pointers.
Consequently, they are not easy to handle from VBA.
We've written a
that hides the details of the MDL functions that handle a
mdlLineStyle_nameGetStringList lets you specify the source of the
StringList it returns.
It will find all line styles,
or those in the active design file or
those in visible DGNLibs.
However, it doesn't find line styles in a line style resource (
To find line styles in a line style resource file (
*.lin) we need another MDL function,
That function take the name of a line style resource (
*.lin) file and returns a
StringList of lines found in that file.
It doesn't look in the active design file, nor in any DGNLib.
Not all MicroStation functionality is available directly through VBA. MicroStation's line styles fall partially 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 functions that handle
Once we've declared a function, we can use it in our VBA code.
Here's the VBA declaration for
taken from the MDL function reference help documentation …
Declare Function mdlLineStyle_nameGetStringList Lib "stdmdlbltin.dll" ( _ ByVal pAuxInfo As Long , _ ByVal options As Long ) As Long ' Returns void *
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.
We enumerate the
StringList and find the line style name from each member of that list.
To achieve that we use MDL function
mdlStringList_getMember in a
mdlStringList_getMember is tricky to use from VBA.
Here's the MDL function declaration …
long mdlStringList_getMember ( char** ppString, long** ppInfoFields, StringList const* pStringList, long memberIndex );
The problem is caused by the first argument, which is the address of a C-style pointer.
If the function returns successfully,
ppString points to the start of the internal text buffer.
Here's the VBA function declaration …
Declare Function mdlStringList_getMember Lib "stdmdlbltin.dll" ( _ ByRef pString As Long, _ ByRef pInfo As Long, _ ByVal list As Long, _ ByVal n As Long) As Long
Because VBA doesn't do pointers,
we declare each pointer as a VBA
Long to accommodate the 32-bit unsigned integer value of the C-style pointer.
Furthermore, by pass that argument
ByRef so that the C function receives the address of our simulated pointer.
Call the function like this …
Dim pString As Long Dim n As Long Dim list As Long ... get list from somewhere mdlStringList_getMember pString, 0, list, n
Now VBA variable
pString points at the text buffer in the
I could not figure out how to copy the text from the buffer into a VBA
a Bentley Systems staff member in Germany, came to my rescue on the
MicroStation Programming Forum.
Artur proposed this Win32 function that correctly allocates memory and copies a C-style string to a
String variable …
Declare Function SysAllocString Lib "oleaut32" (ByVal CharPtr As Long) As String
Now it's simple to copy text from that
mdlStringList_getMember pointer …
Dim pString As Long Dim n As Long Dim list As Long ... get list from somewhere mdlStringList_getMember pString, 0, list, n Dim s As String s = SysAllocString (pString) ' Bingo!
We've created a project that demonstrates the functionality available through MDL to VBA developers.
Because the MDL StringList is not compatible with VBA semantics, we're wrapped it in a VBA class.
clsLineStyleList provides a simple interface …
| ||Writes a list of line style names to the Immediate window|
| || ||Returns |
| ||Returns |
| || ||Returns |
| || ||Loads line style list from a named resource ( |
| ||Loads line style list from visible DGNLibs|
| ||Loads line style list from active DGN file|
| ||Loads line style list from both active DGN file and DGNLibs|
| ||Returns |
| ||Returns |
The VBA project's
Main procedure creates an instance of class
and exercises its interface.
Depending on your configuration of MicroStation,
some of those tests may work and some may fail.
Your mileage will vary.
The above code is available in this MicroStation
Unpack the ZIP archive and copy
LineStyles.mvba to a location where MicroStation
can find it.
A good place to copy it would be
To start enumerating line styles, enter the following into MicroStation's keyin dialog …
vba run [LineStyles]modMain.Main