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.
An application that enables a user to create graphic elements interactively is, in MicroStation terminology, a primitive command. A primitive command uses MicroStation's state engine to draw temporary elements (rubber banding) as the command progresses, and to add the completed element to the active DGN model. It also records the transaction. The recorded transaction is visible to a user via the undo buffer. The user can choose Undo from MicroStation's Edit menu to roll back a transaction, or undo the primitive command.
Sometime we want to create multiple graphic elements by importing data from an external source. That source might be an XML file, CSV file, TIN file, database or some other structure data that contains coordinates and other information.
Usually a bulk import will prompt the user to choose a data source: for example, open a file or database connection. The application then reads the data source and extracts the information needed to make each graphic element, adds the element to a DGN model, and reads the next chunk of data until the data source is exhausted.
What happens if user decides, after importing data, that she wants to undo that import? That is, if she chooses menu Edit|Undo, will that action roll back the import and leave the DGN model in the state it was in before the elements were created? How do we integrate this bulk import transaction with MicroStation's state engine?
It turns out that the solution is simple …
mdlState_startPrimitive
mdlState_startDefaultCommand
Here's some pseudo-code that illustrates an obsolete MDL solution. The code that imports data is bracketted by two calls that influence MicroStation's state engine …
void BulkImportFunction (char const* fileName) { mdlState_startPrimitive (nullptr, nullptr, cmdId, promptId); // open file for read while (moreData) { // create DGN element } // close file mdlState_startDefaultCommand (); }
The observant reader (that's you) asks the question:
"What are those variables cmdId
and promptId
?"
They are the numeric IDs of messages in your MDL message resource file.
Using a message list in this situation means that MicroStation's Edit|Undo
menu will be modified to read something like Edit|Undo Bulk Import,
where Bulk Import is your command message.
In order for those strings to work properly, you must register the message lists
with MicroStation using mdlState_registerStringIds
.
Typically, you call mdlState_registerStringIds
in your application's main
function.
If you're writing C++ then you can be a little smarter.
Use a class to handle the state functions automatically.
In your class constructor, call mdlState_startPrimitive
and in your class
destructor call mdlState_startDefaultCommand
.
Something like this …
// In BulkImportStateManager.hpp
struct BulkImportStateManager
{
BulkImportStateManager (UInt32 cmdId, UInt32 promptId)
{
mdlState_startPrimitive (nullptr, nullptr, cmdId, promptId);
}
~BulkImportStateManager ()
{
mdlState_startDefaultCommand ();
}
};
Use your BulkImport
class like this …
#include <BulkImportStateManager.hpp> void BulkImportMethod (char const* fileName) { BulkImportStateManager stateManager (cmdId, promptId); // open file for read while (moreData) { // create DGN element } // close file }
Return to MicroStationAPI articles index.
Post questions about C++ and the MicroStationAPI to the MicroStation Programming Forum.