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 …
ActiveDesignFile
)
*.lin
) file
An MDL 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
VBA class
that hides the details of the MDL functions that handle a StringList
.
MDL function 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 (*.lin
) file.
To find line styles in a line style resource file (*.lin
) we need another MDL function,
mdlLineStyle_getLinNames
.
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 StringLists
.
Once we've declared a function, we can use it in our VBA code.
Here's the VBA declaration for mdlLineStyle_nameGetStringList
,
taken from the MDL function reference help documentation …
Declare Function mdlLineStyle_nameGetStringList Lib "stdmdlbltin.dll" ( _
ByVal pAuxInfo As LongPtr, _
ByVal options As Long) As LongPtr ' Returns StringList *
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 For..Next
loop.
MDL function 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 LongPtr, _ ByRef pInfo As LongPtr, _ ByVal list As LongPtr, _ ByVal n As Long) As Long
Because VBA doesn't do pointers,
we declare each pointer as a VBA Long
to accommodate the 64-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 LongPtr
Dim n As Long
Dim list As LongPtr
... get list from somewhere
mdlStringList_getMember pString, 0, list, n
Now VBA variable pString
points at the text buffer in the StringList
.
I could not figure out how to copy the text from the buffer into a VBA String
variable.
Luckily,
Artur Goldsweer,
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
VBA String
variable …
Declare Function SysAllocString Lib "oleaut32" (ByVal CharPtr As LongPtr) As String
Now it's simple to copy text from that mdlStringList_getMember
pointer …
Dim pString As LongPtr Dim n As Long Dim list As LongPtr ... 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.
Class clsLineStyleList
provides a simple interface …
Method | Argument | Comment |
---|---|---|
TraceStyleNames | Writes a list of line style names to the Immediate window | |
StyleExists | String style name | Returns True if the named line style exists in the current list |
LineStyleCount | Returns Long size of the current line style list | |
LineStyleByIndex | Long index | Returns String name of line style at specified index in list |
GetResourceLineStyles | String fileName | Loads line style list from a named resource (*.lin ) file |
GetDgnLibLineStyles | Loads line style list from visible DGNLibs | |
GetActiveDgnLineStyles | Loads line style list from active DGN file | |
GetAllLineStyles | Loads line style list from both active DGN file and DGNLibs | |
CountLineStylesInDGNLibs | Returns Long no. of names in DGNLib | |
CountLineStylesInActiveDGN | Returns Long no. of names in active DGN file |
The VBA project's Main
procedure creates an instance of class clsLineStyleList
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
VBA project.
Unpack the ZIP archive and copy LineStyles.mvba
to a location where MicroStation
can find it.
A good place to copy it would be \Workspace\Standards\vba
.
To start enumerating line styles, enter the following into MicroStation's keyin dialog …
vba run [LineStyles]modMain.Main