Introduction

The C++ MicroStationAPI and its predecessor the MicroStation Development Library (MDL) 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.

MicroStation Element Properties

MicroStation is a 3D CAD tool. Users draw 3D or 2D objects in one of eight views. Drawn objects are termed elements. A graphic element represents something that a user can draw, such as a line, arc, rectangle or cone. Elements are persisted in a DGN model, which is part of a DGN file.

Developers who write applications for MicroStation one of several APIs …

This article is for developers who use the C++ MicroStationAPI.

Element Properties Project

A DGN element, as you probably know, has a set of properties. Those include generic properties, such as colour and level, that may belong to any graphic element. They additionally include properties that apply only to certain types of element. For example, a line element has a length property; an ellipse element has major and minor radius properties.

Here, we're looking at MicroStation's ECSchemas and how you can query an element's DGN properties using the ECSchema API, which is a sub-set of the MicroStationAPI. The MicroStationAPI is delivered with the MicroStation SDK, which you can obtain via the Bentley Developer Network (BDN).

ECSchema

ECSchemas have been a part of MicroStation since MicroStation V8i. With MicroStation CONNECT they assume greater importance. At the same time they have become more versatile.

Class DgnECTypeAdapter converts underlying DGN element property values to user-oriented data. Because the MicroStation built-in schemas inform unit conversion, that class and its companion, DgnECTypeAdapterContext, calculates the value that the user expects to see. For example, an area is displayed as 423m² rather than 423000000 UORs squared.

Here's a code snippet extracted from the ElementProps project. This is slightly modified from an example posted on Be Communities by Bentley Systems staffer Yongan Foo  …

void GetElementProperties (ElementHandleCR eh)
{
    DgnECManagerR           ecMgr   = DgnECManager::GetManager ();
    FindInstancesScopePtr   scope   = FindInstancesScope::CreateScope (eh, FindInstancesScopeOption(DgnECHostType::Element));
    ECQueryPtr              ecQuery = ECQuery::CreateQuery (ECQUERY_PROCESS_SearchAllClasses);
                                               //ECQUERY_PROCESS_SearchAllExtrinsic will only search ECXAttr
    ecQuery->SetSelectProperties (true);
    for (DgnECInstancePtr instance: ecMgr.FindInstances (*scope, *ecQuery))
    {
        DgnElementECInstanceP elemInst = instance->GetAsElementInstance();
        WPrintfString outStr(L"--------- className = %s, instanceId = %s ---------------",
                             elemInst->GetClass().GetName().GetWCharCP(),
                             elemInst->GetInstanceId().GetWCharCP());
        mdlOutput_messageCenter (DgnPlatform::OutputMessagePriority::Debug, outStr.c_str (), outStr.c_str (), DgnPlatform::OutputMessageAlert::None);
        for (ECPropertyP ecProp : elemInst->GetClass().GetProperties())
        {
            WString wStr;
            ECValue ecVal;
            elemInst->GetValue(ecVal, ecProp->GetName().GetWCharCP());
            IDgnECTypeAdapterR typeAdapter = IDgnECTypeAdapter::GetForProperty(*ecProp);
            IDgnECTypeAdapterContextPtr typeContext = IDgnECTypeAdapterContext::Create(*ecProp, *elemInst, ecProp->GetName().GetWCharCP());
            typeAdapter.ConvertToString(wStr, ecVal, *typeContext);
            WPrintfString outStr2(L"\t%s[%s] = %s",
                ecProp->GetDisplayLabel().GetWCharCP(), ecProp->GetTypeName().GetWCharCP(), wStr.GetWCharCP());
        	mdlOutput_messageCenter (DgnPlatform::OutputMessagePriority::Debug, outStr2.c_str (), outStr2.c_str (), DgnPlatform::OutputMessageAlert::None);
        }
    }
}

When that code is called, MicroStation's Message Center shows something like this (many lines omitted) …

Circle Element properties...
 End Point[point3d] = -24.022m, 11.598m
 Start Point[point3d] = -24.022m, 11.598m
 Axis Ratio[double] = 1.00000
 Secondary Vector[point3d] = 0.000m, 1.732m
 Primary Vector[point3d] = 1.732m, 0.000m
 Center[point3d] = -25.755m, 11.598m
 Primary Axis[double] = 1.732m
 Perimeter[double] = 10.884m
 Area[double] = 9.428 Sq.m
 Angle[double] = 0.000°
 Range High[point3d] = -24.022m, 13.330m
 Range Low[point3d] = -27.487m, 9.865m
 Class[int] = Primary
 Line Style[int] = ByLevel (0)
 Weight[int] = ByLevel (0)
 Color[int] = ByLevel (0)
 Type[string] = Ellipse
 Size[int] = 72
 Last Modified[dateTime] = 7/31/2018 4:30:00 PM
 Model[string] = 2D Metric Design
 Element ID[long] = 910
 Element Description[string] = Circle
--------- className = EllipseElement, instanceId = :ECDB00000000:158E030000 ---------------
Circle, Level: Default

The above extract shows the element properties of an unadorned DGN ellipse (circle) element. The next listing is the same code applied to a shape element having Item Type properties attached. In this example the properties are the DGN element properties, plus those of AreaAnnotator. The listing shows the Area Feature's ECSchema internal name, which is Area__x0020__Feature …

Shape Element properties...
 altAreaFormatted[string] = 7.18yd²
 altPerimFormatted[string] = 10.94yd
 perimFormatted[string] = 10.000m
 areaFormatted[string] = 6.000m²
 ID[string] = Room 302
 areaType[string] = Enclosure
 purpose[string] = Office
--------- className = Area__x0020__Feature, instanceId = :56FF00000001:1547020000 ---------------
 Perimeter[double] = 10.000m
 Area[double] = 6.000 Sq.m
 Area[double] = 6.000 Sq.m
 Total Length[double] = 10.000m
 Count[int] = 4
 Range High[point3d] = 2.893m, 7.333m
 Range Low[point3d] = -0.107m, 5.333m
 Display Style[int] = (From View Display)
 Complex[boolean] = Not Complex
 Filled[boolean] = Not Filled
 Line Style[int] = ByLevel (0)
 Weight[int] = 2
 Color[int] = ByLevel (1)
 Type[string] = Shape
 Property List[string] =
 XAttributes[int] = 1
 Size[int] = 96
 Last Modified[dateTime] = 6/8/2017 10:55:23 AM
 Model[string] = 2D Metric Design
 Element ID[long] = 583
 Level[int] = Areas 2
--------- className = ShapeElement, instanceId = :ECDB00000000:1547020000 ---------------
Shape, Level: Areas 2

Building the Element Properties Project

We assume that you are using the MicroStation development environment to build this project. Consult the MicroStation Software Development Kit (SDK) help for more information, or take a look at our guide to setting up Windows to build MicroStation applications.

As this is a C++ project, you'll need Visual Studio installed. The project builds from a Bentley make (bmake) file, so the purpose of Visual Studio is to provide a compiler and linker rather than an IDE.

As with any application built for native code, the result is in two parts: ElementProps.ma and ElementProps.dll. File ElementProps.ma contains only resource data: in this case, the information MicroStation requires to load the DLL, and a command table. ElementProps.dll is the implementation file. When a user types mdl load ElementProps MicroStation first loads ElementProps.ma and finds the resource directive (the DllMdlApp in ElementPropsCmd.r) that instructs it to load a DLL, then it loads ElementProps.dll.

Download the ElementProps Project

Download ElementProps.

Download the ElementProps project. This ZIP file contains C++ source code header and implementation files, and a bmake (.mke) file to build the project. You need Visual Studio 2015 to be installed in order to compile this project for MicroStation CONNECT.

Questions

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