Almost all applications that run on MicroStation V8 2004 Edition should run in MicroStation V8 XM Edition without modification. The tools used to compile "Native Code" are updated to the latest released Microsoft VisualStudio .NET 2003. Applications that use "Native Code" should be recompiled for the MicroStation V8 XM Edition. Applications that are built with MicroStation V8 XM Edition API are not guaranteed to be backwards compatible and should be built with the mlink -uoption to set the version to 89. Java/JMDL and MicroCSL have been completely removed from the product and are no longer supported.
mlink -u
Source code that refers to ULong data types should be converted to UInt32 which is the more accepted standard for 32-bit unsigned integers and is more compatible with 64-bit computing in the future. This may affect some function signatures.
ULong
UInt32
In MicroStation V8 XM Edition, there is an ability to see some combination of name/description/code. It is controlled by the MS_LEVEL_DISPLAY_FORMAT environment variable, which specifies the level name formatting to use
MS_LEVEL_DISPLAY_FORMAT
More than one value can be specified. Example: N(C); Default: N
If a level had a name of "FDoors", a description of "Grade 1 Fire Doors", and a code of 37, setting the MS_LEVEL_DISPLAY_FORMAT variable to D[C], would result in "Grade 1 Fire Doors[37]" showing up in the various level lists.
mdlLevel_getName
mdlLevel_getDisplayName
There are situations where this could cause problems. In the pentable application, a list of levels is displayed to the user to choose from and the selected names written to a file. If the names are the ones obtained from mdlLevel_getDisplayName and those names are written to a file, it would not be possible to match those names to actual levels when the file is read back (the value of the MS_LEVEL_DISPLAY_FORMAT variable could change, ...)
Almost all pre-V8 MDL applications will need to be modified to run with MicroStation V8. The amount of work required to adapt an application depends upon the technology that it uses, the degree to which it interacts with DGN file graphical or control elements, and the method that it uses to interact with such elements. At a minimum, all applications must be recompiled. In extreme cases, where elements are directly manipulated without the aid of MicroStation's API, substantial rework may be necessary. Bentley anticipates that most applications can be adapted with relatively simple changes to data types, with no change to program flow or logic.
The MicroStation V8 XM Edition development environment requires the following environment variables be set for successful MDL compilation:
MS
BMAKE_OPT
-IC:\Program Files\Bentley\Program\MicroStation\mdl\include
MLINK_STDLIB
builtin.dlo
toolsubs.dlo
dgnfileio.dlo
PATH
These variables are automatically set when you use the Development Shell delivered with the MicroStation SDK. For your convenience, the Developer Shell also sets the environment variable MSMDE to the root location of the MicroStation SDK development tools (for example, C:\Program Files\Bentley\MicroStation\).
MSMDE
NOTE: Bentley highly recommends that you use this Development Shell and encourages its use as the basis for any custom development environments.
The MDL compiler in MicroStation V8 provides significant assistance in the upgrading of MDL applications. By default, the compiler is set to be strict, meaning that all functions are required to have prototypes. MicroStation's prototypes can be found in .fdf or .h files located in the MDL include directory. Also, the MDL compiler checks for unused and un-initialized variables. And as part of the language update, MDL supports the const keyword and enum types.
.fdf
.h
const
enum
In MicroStation V8, the global TCB structure has changed. Some previously accessible structures are no longer public, some have been removed, and some have been changed. If your application accessed information about MicroStation directly through the TCB, you may have to make some code changes.
There are various API calls that provide information previously accessible only through public structures (like TCB). For example, view information that used to come directly from the TCB is available by calling mdlView_getParameters(), and can be modified by calling other mdlView_... functions. The TCB members uorpersub and subpermast are now accessible through the functions mdlModelRef_getUorPerSub() and mdlModelRef_getSubPerMaster().
mdlView_getParameters()
mdlView_...
uorpersub
subpermast
mdlModelRef_getUorPerSub()
mdlModelRef_getSubPerMaster()
As a general rule to follow: it is always safer and more preferable to accomplish a task using API functions rather than directly accessing public static structures. The public static structures you access directly in this version of MicroStation may not be present in a later version.
MicroStation stores all strings internally as Unicode (using the type "MSWChar *" rather than "char *"). This provides support for character sets necessary for many foreign languages.
The API for the following MDL function areas have changed:
The primary change to these calls is to take MSWChar * strings instead of char * strings. This enables you to store Unicode names in the DGN file for all entities with names. Also, these functions have been added to aid in the conversion process:
MSWChar *
char *
There are also standard C functions available for swscanf, wtoi, wtol, wcscpy, wcscmp, mdlwcscmpi among others which can be called for string manipulation. For MDL, a version of swprintf and the ability to do L"name" to create a wide character string is being developed.
swscanf
wtoi
wtol
wcscpy
wcscmp
mdlwcscmpi
swprintf
The user interface for entering text does not support inputting strings in Unicode format, so strings must be converted to Unicode. The mdlCnv_convertMultibyteToUnicode() function does this nicely, and conversely mdlCnv_convertUnicodeToMultibyte() does the reverse. Also, TrueType fonts can be stored. Since a text element can be significantly larger that previous versions it might be useful to allocate the buffer for the actual character string at runtime as opposed to a statically defined buffer. To do this you can get the number of characters from the text element. This number of characters can then be multiplied by two and then add one to get the max size in bytes of the string.
mdlCnv_convertMultibyteToUnicode()
mdlCnv_convertUnicodeToMultibyte()
The Dialog Manager and Resource Manager have been enhanced to support Unicode strings, in addition to Multibyte strings, as Text item values, ListCell and GuiTreeCell values, and GUI item label, flyover, balloon, disabledBalloon and popupMenu text. Outstanding enhancements include window titles and MLText item values. This was accomplished by either adding ValueDescr variables or replacing char * variables with ValueDescr variables. The ValueDescr structure is defined in vartypes.h and contains a format type and value union. Multibyte strings have a format type of FMT_STRING; Unicode strings have a format type of FMT_MSWCHAR. The MDL API has been enhanced to provide functions for this new feature.
Text
ListCell
GuiTreeCell
GUI
flyover
balloon
disabledBalloon
popupMenu
MLText
ValueDescr
vartypes.h
FMT_STRING
FMT_MSWCHAR
MicroStation automatically converts elements from V7 DGN to V8 DGN format when a V7 file is opened. However, application-specific user attribute linkages on elements are not converted because MicroStation can not interpret their literal meaning. MDL applications should convert these linkages in a manner that best suits them. For instance, when a V8 MicroStation Modeler solid containing V7 linkages is edited by the user, Modeler removes the old linkage and replaces it with a newer version. Typically, the difference between V8.x and pre-V8 linkages exists due to:
MSWChar
For example:
/* V7 ... note color, weight, style are certain bits of a Ulong */typedef struct symbologyLinkageData_v7 { ElementID tag; struct { ULong weight:5; ULong style:3; ULong color:8; ULong unused:16; } symb; } SymbologyLinkageData_v7;/* the MicroStation V8 color, weight, style are assigned larger sizesand tag, which is an element assoc id, is larger */typedef struct symbologyLinkageData { ElementID tag; ULong weight; long style; ULong color; } SymbologyLinkageData;
In MicroStation V8, DGN files can contain more than one model. Applications can take advantage of multiple models, but most applications can work only on the active model and its attached references.
In pre-V8 MicroStation, the two pieces of information that an application needed to refer to an element was its "file position" and "file number". The file position was an offset into the DGN file, and the file number was an index into an array of opened files (filenum 0 was the master file and 1-255 for the attached reference files.) That system could not be used in MicroStation V8, since it allows unlimited hierarchical reference file attachments. In MicroStation V8, a "file position" is simply a "sequence number" and generally works with existing source code. The replacement for the file number is the DgnModelRefP. This is an opaque pointer to an object that MicroStation maintains for each open Model. There is a DgnModelRefP for the Active Model (the analog to the Master File in MicroStation V8), that can be obtained by calling mdlModelRef_getActive(). There is a DgnModelRefP for each reference that is currently open. A DgnModelRefP is also returned by the mdlWorkDgn_openFile and mdlWorkDgn_createFile functions.
DgnModelRefP
mdlModelRef_getActive()
mdlWorkDgn_openFile
mdlWorkDgn_createFile
Generally, converting from the previous system of "file" identification to the DgnModelRefP system of identifying models requires some source code changes. Most of these changes are fairly mechanical and easily accomplished.
All MDL functions that previously accepted a file number or reference file slot now accept a DgnModelRefP. To make the transition to DgnModelRefP's as easy as possible, functions that accept a DgnModelRefP also accept the value NULL to indicate the Active Model. This means that programs that only manipulate the Active Model (Master File for pre-V8) may require no source code changes at all. Applications that operate on elements from references, particularly if they iterated through all attached references, will require more changes.
DgnModelRefP's
NULL
The most common way applications obtained a file number in previous versions, was to use tcb->curefl (the file number of the most recently located element.) That member of the TCB has been removed, and the new mdlLocate_... API that returns DgnModelRefP replaces it. In general, modifying an application to use DgnModelRef's instead of file numbers consists of attempting to compile it and correcting the compilation errors. Since the type has changed, the compiler will readily point the errors out to you. To speed things along, you can often search for variables named fileNumber, fileNum, and fileNo and replace them with "modelRef", properly changing the type declaration from int to DgnModelRefP.
mdlLocate_...
DgnModelRef's
fileNumber
fileNum
fileNo
modelRef
int
Please also note that there are many instances where pre-V8 applications test against a value of 0 for "file number" to determine whether it is a master file or a reference file. For example:
if (0 == fileNumber)
if (MASTERFILE == fileNo)
if (0 < fileNum)
These should be changed to use one of the mdlModelRef_... functions that characterize a DgnModelRefP, usually mdlModelRef_isActiveModel, mdlModelRef_isReference, or mdlModelRef_isReadOnly. All mdlModelRef_... functions are defined in msdgnobj.fdf.
mdlModelRef_...
mdlModelRef_isActiveModel
mdlModelRef_isReference
mdlModelRef_isReadOnly
msdgnobj.fdf
All view information is accessible through the MDL API.
Since MicroStation users can create new levels in a DGN file, the nature of levels has changed dramatically. Levels are elements and are stored as entries within a LevelTable element. Functions are used to get a LevelEntry from the LevelTable, and to get particular settings for the level, such as color, weight, style, display and plot, among others. The entries in a LevelTable can be treated like elements within a complex element descriptor, using mdlLevelIterator_getFirst() and mdlLevelIterator_getNext() to iterate through a list of levels.
LevelTable
LevelEntry
mdlLevelIterator_getFirst()
mdlLevelIterator_getNext()
A LevelList dialog item replaces the LevelMap dialog item used previously. A LevelList item defaults to the same size as a LevelMap, and will provide horizontal scrollbars to navigate through the level fields. The options on the LevelList item allow display of multiple columns. The LevelList item can have a hook function attached, unlike the LevelMap item. There are two access strings for the LevelList, like the LevelMap, except that the levels are represented by a BitMask type item. Correct initialization of the BitMask is shown in the example below.
LevelList
LevelMap
BitMask
To build the user interface for level combo box item:
Private void initialize (void) { ULong highestLevelId; if (NULL == myStruct.pLevelMask) mdlBitMask_create(&myStruct.pLevelMask); mdlLevelTable_getHighestLevelId(&highestLevelId, MASTERFILE); mdlBitMask_ensureCapacity(myStruct.pLevelMask, highestLevelId, 0); return ; }
Functions for accessing the properties of the LevelItem item and customizing its behavior are also provided. The API also allows access to the item structure so the standard dialog functions can be used.
LevelItem
The function mdlLevel_setFillColor has been removed from the API, as it performed no operation.
mdlLevel_setFillColor
The Scanning API provides a convenient mechanism for applications to filter the elements of a model, to operate on just the subset of them that meet a certain criteria or combination of criteria. For programmers familiar with relational database concepts, the Scanner fills the same role for DGN elements that SQL fills for relational tables.
In MicroStation V8, the Scanning API has been substantially improved. However, the pre-V8 API is also maintained for compatibility.
The new API consists of the mdlScanCriteria_... functions, and is described in msscancrit.fdf. The MicroStation V8 mdlScanCriteria_ API provides two ways for applications to filter the elements of a model. The first way is to allocate a buffer. The scan can then use a new way of processing the file by using an iterator to process all the elements at one time. For examples, see the Scan and WorkDgn examples.
mdlScanCriteria_...
msscancrit.fdf
mdlScanCriteria_
To take advantage of new capabilities in the V8 DGN file format, scanning routines need two categories of change. The first change is to ensure your buffers are large enough to hold the elements returned from the scanner. One way to optimize the memory allocation is to use the alloca() function to allocate memory on the stack that is automatically released when your function exits.
alloca()
The second change requires adapting scan request to use the new mdlScanCriteria_... functions. This process involves creating a ScanCriteria object, initializing it with the mdlScanCriteria_... functions, calling mdlScanCriteria_scan, and then freeing the ScanCrieria object by calling mdlScanCriteria_free.
ScanCriteria
mdlScanCriteria_scan
ScanCrieria
mdlScanCriteria_free
The global variable, RefFileP has been removed. Use mdlRefFile_getInfo to get a reference pointer that can be passed into the various functions that query for information, such as update sequence, etc. The correct way to iterate through the active file and references is to use the new mdlModelRefIterator_... functions (see msdgnobj.fdf). For example:
RefFileP
mdlRefFile_getInfo
mdlModelRefIterator_...
DgnModelRefP modelRef; ModelRefIteratorP iterator; mdlModelRefIterator_create (&iterator, MASTERFILE, MRITERATE_Root | MRITERATE_PrimaryChildRefs, 0); while (NULL != (modelRef = mdlModelRefIterator_getNext (iterator))) { ... do something to each modelRef. } mdlModelRefIterator_free (&iterator);
In this case, the code iterates through the DGN file and its primary references. To get just the references, change the third argument to MRITERATE_PrimaryChildRefs. The fourth argument is the nesting depth. Setting it to zero gets only the primary references, setting to -1 goes through all nesting no matter how deep. Remember to call mdlModelRefIterator_freeto free the iterator.
MRITERATE_PrimaryChildRefs
mdlModelRefIterator_free
The Raster Manager API, mdlRaster, supercedes any previous version of mdlRastRef. Additionally, all code created for mdlRastRef WILL NOT RUN under the mdlRaster API. Any code created for mdlRastRef must be ported to mdlRaster API.
mdlRaster
mdlRastRef
Many dimension settings have been moved from the TCB. Most of the variables can be retrieved using mdlDimStyle_... functions. Dimension style elements are table entry elements.
mdlDimStyle_...
mdlCell_extract, mdlCell_extractName, etc. return the cell name as MSWChar *. To convert the returned wide-string Unicode cell name to an array of chars, mdlCnv_convertUnicodeToMultibyte() should be used. To convert an array of chars to Unicode, then mdlCnv_convertMultibyteToUnicode()should be used first.
mdlCell_extract
mdlCell_extractName
There are currently a number of #defines for name lengths (e.g. MAX_CELLNAME_LENGTH), and there is also an equivalent define for MAX_CELLNAME_BYTES. This is because the conversion from Unicode to Multibyte can take 2x the number of bytes as letters in the wide string name. So when converting from Unicode to Multibyte, your Multibyte buffer should be declared to be the _BYTES length. If on a single byte code page operating system (i.e. English Windows), you fill up the char buffer with characters and then convert to Unicode, your string will be truncated to the _LENGTH size.
#defines
MAX_CELLNAME_LENGTH
MAX_CELLNAME_BYTES
_BYTES
char
_LENGTH
If you write names out to ASCII files you will need to use the mdlCnv_unicodeToUTF functions to create a null-terminated ASCII string of the name so that the ASCII file is portable across different localized versions of Windows.
mdlCnv_unicodeToUTF
Cell libraries are DGN files with each cell being a design model in that file.
Sample code for generating a list of cells in a Cell Library:
{ DgnIndexIteratorP cellIterator; DgnIndexItemP cellIndexItem; DgnFileObjP pLibObj; if (0 != tcb->celfilenm[0]) { MSWChar wCellName [MAX_CELLNAME_LENGTH]; int iStatus; int cellType; BoolInt isThreeD; iStatus = mdlCell_getLibraryObject (&pLibObj, tcb->celfilenm, TRUE); cellIterator = mdlModelIterator_create (pLibObj); mdlModelIterator_setAcceptCellsOnly (cellIterator, TRUE); while (NULL != (cellIndexItem = mdlModelIterator_getNext (cellIterator))) { char mbCellName[MAX_CELLNAME_BYTES]; MSWChar wCellDescription[MAX_CELLDSCR_LENGTH]; // Get the cell name mdlModelItem_getName (cellIndexItem, wCellName, MAX_CELLNAME_LENGTH); // Convert the name to multibyte mdlCnv_convertUnicodeToMultibyte (wCellName, -1, mbCellName, sizeof(mbCellName)); // Get the description mdlModelItem_getDescription (cellIndexItem, wCellDescription, MAX_CELLDSCR_LENGTH); // Get other information mdlModelItem_getData (cellIndexItem, NULL, &isThreeD, NULL, NULL, NULL); cellType = mdlModelItem_getCellType (cellIndexItem); printf ("the cellname is '%s' and the description is '%S' \n", mbCellName, wCellDescription); } mdlModelIterator_free (cellIterator); } }
MicroStation provides equivalent functions for manipulating solid elements using the Parasolids Solid Modeling Kernel and the ACIS Solids Modeling Kernel. A third API, the Kernel Independent API (KISolids) is appropriate for most cases. This will allow your application to automatically accommodate the workmode chosen by the user without writing specific support for both libraries. MicroStation's preference is for using Parasolids functions, though ACIS functions can be accessed if DWG compatibility is necessary. Most source code will require updating.
The function to open a work file is mdlWorkDgn_openFile. It returns a DgnModelRefP that can be passed to the standard mdlElmdscr_... functions. Also available is the mdlWorkDgn_create function to create a new file. NOTE: Files modified with the WorkDgn_... functions not saved until the mdlWorkDgn_closeFilefunction is called.
mdlElmdscr_...
mdlWorkDgn_create
WorkDgn_...
mdlWorkDgn_closeFile
The functions
mdlTag_hasInternetTagSet
mdlTag_attachURL
mdlTag_createInternetTagSet
have been moved to core MicroStation and webtag.msl is no longer delivered with the product. Applications that linked with webtag.dlo will need to have the reference from the link step in the make file removed. Also, any #include webtag.fdf statements in source files need to be replaced with #include mstagdat.fdf (webtag.fdf has been updated to explain the changes and how to recompile applications).
webtag.msl
webtag.dlo
#include webtag.fdf
#include mstagdat.fdf
webtag.fdf
View update events now require implementing new callback functions in C++. Previous to MicroStation V8 XM Edition, applications used the function mdlView_setFunction with the UPDATE_EACH_ELEMENT event. In MicroStation V8 XM Edition, this way to do this is with the function mdlView_setSubstituteElemFunc. This function accepts one parameter, which is a function pointer of type ViewFunc_SubstituteElemand has the following signature:
mdlView_setFunction
UPDATE_EACH_ELEMENT
mdlView_setSubstituteElemFunc
ViewFunc_SubstituteElem
Private SubstituteElemStatus updateElementHook(MSElementDescrH newEdPP, // <= output if element being replacedint* priorityP, // <= priority if element being deferredIViewportP viewPortP,DrawPurpose drawPurpose,IViewContextP context, // => view contextbool allowDefer, // => whether element can be deferredElemHandleCP elemIterP // => constant pointer to an element iterator pointer for current element if descriptor is needed)
This requires adding references to the interface files which is done through the addition of MicroStationAPI.h, which is located in ..\MicroStation\mdl\MicroStationAPI\ and are documented in the MicroStationAPI help file delivered with the MicroStation SDK. This callback allows applications to replace the element being drawn or postpone the draw of the element. Of particular interest are the parameters elemIterP, viewPortP, and drawPurpose.
MicroStationAPI.h
..\MicroStation\mdl\MicroStationAPI\
elemIterP
viewPortP
drawPurpose
ElemHandles
elementRef
IViewport
DrawPurpose
This callback function is set by using the mdlView_setSubstituteElemFunc:
mdlView_setSubstituteElemFunc ((ViewFunc_SubstituteElem)updateElementHook);
NOTE: This function is declared in the msview.fdf header file, but can only be used in C++ code.
msview.fdf
After updating the callback function, applications need some further changes. One such change is to know the MSWindow that is being drawn to, which can be accomplised using the following code:
MSWindow
mdlWindow_viewWindowGet(viewPortP->GetViewNumber());