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.
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
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.
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.
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; } };
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); }
Post questions about C++ and the MicroStationAPI to the MicroStation Programming Forum.