Introduction

The MicroStation Development Library (MDL) and MicroStationAPI provide APIs for developers wanting to create custom applications for MicroStation® from Bentley Systems. We create a MicroStation application as a DLL, written using C++ and built with the Microsoft C++ compiler and linker provided with Visual Studio.

When editing your source code, you can choose whether to use Microsoft Visual Studio, Microsoft Visual Studio Code, or one of your favourite text editors.

When building your app, you can use Visual Studio or the Bentley Systems make (bmake) tools.

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);
    }

Questions

Post questions about C++ and the MicroStationAPI to the MicroStation Programming Forum.