MicroStation and Application Development

MicroStation® is a computer-aided-design (CAD) tool produced by Bentley Systems. It is used by engineers, architects, and draughting technicians to create 3D models and 2D drawings.

MicroStation can be customised. Bentley Systems themselves have many applications for specialised markets that use MicroStation as a platform. Third-parties may use MicroStation as a platform on which to develop their application. Bentley Systems provide the MicroStation Software Development Kit (SDK) that software developers use to create their applications.

The SDK has two libraries: the MstnPlatformNet and the MicroStationAPI. The MstnPlatformNet provides a .NET interface. The MicroStationAPI provides a C++ interface.

MicroStation CONNECT also includes Visual Basic for Applications (VBA). It's a great tool for rapid application development and for developers who don't want to become involved in the complexities of the object-oriented programming idioms provided by C# and C++.

The MicroStationAPI for CONNECT is poorly understood by developers, partly because of the terse nature of the help documentation and lack of guidance in the form of examples. These articles attempt to clarify and explain the MicroStationAPI from a developer's viewpoint. In particular, it provides a commented code fragment that illustrates a common requirement: to provide a consistent way to enumerate a set of elements.

IElementSet

The MicroStationAPI provides the IElementSet interface definition. Help tells us, rather enigmatically: This interface provides a transparent way to provide access to a collection of ElementHandles. It is typically implemented by an iterator class returned by the set, but can be implemented by any application to supply other types of ElementHandle collections. What help doesn't tell us is why IElementSet exists and how it differs from ElementAgenda.

It's an abstract class, so you must inherit it and implement its pure virtual methods. Bentley staffer Paul Connelly commented: IElementSet is purposely opaque: user need neither know nor care how the elements are supplied.

ElementAgenda

ElementAgenda is a general-purpose class that stores a list of EditElementHandle. You'll find it implemented in DgnElementSet, among other classes.

ElementAgenda.BuildFromElementSet populates its internal list from any class that implements the IElementSet interface.

How to Implement IElementSet

Simple Example

Paul Connelly wrote this example to illustrate an implementation of IElementSet. This class contains a single ElementHandle, which is revealed by the IElementSet interface …

#include <ElementHandle.h>
class OneElement : public IElementSet
{
    ElementHandle eh_;
public:
    size_t        GetCount () override { return 1; }
    bool          GetFirst (ElementHandleR eh) override { eh = eh_; return true; }
    bool          GetNext (ElementHandleR) override { return false; }
};

Note how you use this class: call GetFirst() to get the first and only ElementHandle. GetNext() always returns false, making it easy to enumerate this minimalist container.

Container Example

Here's a more complex class that has a vector of ElementHandle. Now we must implement range checking when we assign the vector contents …

class MyCollection : public IElementSet
{
    size_t index_;
    bvector<MyClassInheritsFromElementHandle>  data_;

public:
    MyCollection () : index_ (0) {}
    size_t   GetCount () override { return data_.size (); }
    bool     GetFirst (ElementHandleR eh) override
    {
        index_ = 0;
        eh     = data [index_];
        return true;
    }

    bool     GetNext  (ElementHandleR eh) override
    {
        if (index_ != data_.size ())
        {
            eh = data [index_];
            ++index_;
            return true;
        }
        return false;
    }
};

How to Use IElementSet

Because we inherit IElementSet, our user finds it easy to enumerate our class contents …

    //  Simplest Example
    OneElement  one;
     … populate data somehow
    //  Enumerate OneElement
    ElementHandle  eh;
    bool           valid  { one.GetFirst (eh) };
    while (valid)
    {
        //  Do something with ElementHandle
        valid = one.GetNext (eh);
    }
    //  Collection Example
    MyCollection  data;
     … populate data somehow
    //  Enumerate MyCollection
    ElementHandle  eh;
    bool           valid  { data.GetFirst (eh) };
    while (valid)
    {
        //  Do something with ElementHandle
        valid = data.GetNext (eh);
    }