Contrary to what some developers may have heard or thought, the MDL Dialog Manager and support for WinForms and MFC are still in place. We have added support for WPF, but support for the other three UI technologies remains. Another misconception is that all MDL dialogs are being converted to WPF. That is also not the case. There are 700+ MDL dialogs in MicroStation alone, and we cannot possibly convert all of those dialogs and hook functions to use WPF, at least in the short term.
The Dialog and Item Resources in .r files remain mostly the same. Even with the expanded Unicode support, most of the text strings in .r and .h files remain multi-byte. They are actually treated as UTF-8 internally and are converted to Unicode/WChar, and vice-versa, as needed.
Dialog and Item Hooks can remain structurally intact. We have added support for "C++ Hook Handlers", but adoption of these is optional.
The DialogItem and RawItemHdr structs still exist and still have most of the members they had before. With the Unicode port, some of the members are now WChars or WStrings, and some of the names of the members have changed to reflect the datatype changes. But the structs still exist.
Most of the mdlWindow_ and mdlDialog_ related functions still exist. With the Unicode port, some of the parameter types have changed to WCharCP or WStringR /CR. If a function has been removed, it it listed here: VancouverRemovedAPIFunctions
Most of the Dialog Items or Controls still exist. Those that have been removed are listed below in the "What Was Removed?" section.
The Docking Systems for both toolboxes and dialogs are still in place.
Support for Windows Forms, or WinForms, still exists. The Adapter class, which is a subclass of Form, is still used as an interop layer between WinForms and the Dialog Manager. The different "Attachment Types" (TopLevel, ToolSettings, GuiDockable, Popup) are still in place. All of the controls in Bentley.MicroStation.WinForms.Controls.dll, Bentley.MicroStation.WinForms.ECPropertyPane.dll and Bentley.UI.dll still exist. The various EC Controls are all still there.
The Bentley MFC base classes and the mdlNativeWindow_ functions are still in place. The mdlNativeWindow_ functions have actually increased in number to support WPF. However, MFC support is being "de-emphasized", meaning that it will not be included as we make enhancements such as overall product styling, and PowerPlatform itself will no longer include any MFC based applications. As a result, there will be no certification of the underlying MFC support in PowerPlatform.
Most of the mdlDialog_/mdlWindow_*W functions have been removed, and in the rare case where there were *A functions, they have also been removed. For a list of functions that no longer exist, see VancouverRemovedAPIFunctions
Functions that were added in V8 that took a ValueDescr to support both Multi-byte and Unicode have been removed. The functions that did take a char* have been changed to take WChar* or WStringR /CR. Again, for a list of functions that no longer exist, see VancouverRemovedAPIFunctions </P.
The following Dialog Items / Controls have been removed:
The ability to switch between Windows, Motif and Mac drawing modes has been removed. Support for this switching was never implemented in WinForms and MFC and was outdated.
The Auxiliary Messages (AuxMessages) that were passed to the Item Handlers from item specific functions have mostly been removed. Only a handful of these messages remain. The item specific functions are now implemented in the item handler source files and are now capable of calling item handler functions directly. The AuxMessage IDs and associated structs have been removed from <Mstn\MdlApi\dlogitem.h>.
The ability to support both Multi-byte and Unicode labels and values was added to the Dialog Manager in V8 via the ValueDescr struct. The Multi-byte, or Char[], part of that support has been removed in most places. The ValueDescr FMT_STRING formatType and the ValueUnion charPFormat member have been removed. As stated earlier, the functions that took ValueDescr to support both Multi-byte and Unicode have also been removed.
The GuiWindow, DialogBox and GuiDialog type names have been changed.
There were some guiding reasons for these changes:
To help with the name changes, there are several Remap helpers located in VancouverUpgradeTools.
In order to better support Aspect Ratios in Transkits and LangPacks, we needed to enhance the Resource Manager and the LangPack extraction and generation utilities. The Aspect Ratios, as well as any localizable strings, are now stored as bytecodes in the resource file as opposed to static data. As we extract information from resource files for the Transkit, we transfer Aspect Ratio information and source strings to the generated XLIFF files (XML Localisation Interchange File Format). After receiving localized XLIFF files from the translators, localized Aspect Ratio values and target strings are transferred to the generated localized MUI files in the LangPack.
There is one syntax change required in the application header file to accommodate this.
The MSValueDescr struct has been introduced and is a C++ wrapper for the older ValueDescr struct introduced in V8. The MSValueDescr struct contains the data type and the value and also has methods that operate on that value. The struct is defined in <Mstn\MdlApi\MSValueDescr.h>. Any existing usages of ValueDescr, or any combination of a format type plus a ValueUnion, should be replaced with an MSValueDescr. Any functions that took a ValueDescr* should now take a MSValueDescrP.
The data types supported by MSValueDescr include:
MSValueDescr has multiple constructors which take specific data types. There are also copy methods and an = operator. There are numerous "Is", "Get", "Set" and "Compare" methods. Some of the "Get" methods will perform necessary numeric conversions, but will complain about signed/unsigned mismatches and possible data loss.
Any instance of ValueDescr or a formatType/ValueUnion combination has been replaced by an MSValueDescrP in the dialog hook and dialog item hook message structs, which are defined in <Mstn\MdlApi\dlogitem.h>. As an example, here is the old DialogItemMessage.u.value followed by the new version. Note that the following variables in the 8.11 version have been replaced by a single MSValueDescrP in the CONNECT Edition:
Here are some example usages showing MSValueDescr "Get" and "Set" calls:
A few "major" features have been added in the CONNECT Edition PowerPlatform and these are explained in dedicated sections below.
Other features have also been added, including Double-Buffering, Color Schemes and New Dialog Items.
Double-buffering has been added for MDL windows and dialogs, which greatly reduces any flickering, or "flishy-flashy", behavior. This feature is free - there is nothing extra you must do to turn this feature on. However, if you're doing some Generic dialog item drawing or GDI/GDI+ drawing into the window and there is still some flickering, an mdlWindow_doubleBuffer* API is available and is prototyped in <Mstn\MdlApi\mswindow.fdf>. There is also a GuiDoubleBufferRef helper class that wraps some of those C functions.
Some color schemes have been introduced that mimic the Office 2007 Silver, Blue and Black (Dark Gray) themes. This can be set via "Workspace menu > Preferences > Look and Feel". More color themes will be added and we will work on applying those themes across MDL, WinForms and WPF windows and controls.
A couple of new dialog items have been added:
C++ APIs for the MSDialog, MSWindow and DialogItem structs and various dialog items have been introduced. These APIs will help those C++ developers who want a more object-oriented application and also those who are using Visual Studio IntelliSense. Adoption of the C++ APIs is optional and they may be introduced into your code gradually. The equivalent mdlWindow and mdlDialog API functions will remain in place, and those functions are listed below in the Method/Function tables. Not all of the dialog items have a C++ API, and we are evaluating the cost-benefit ratio to determine whether we should add more.
The MSDialog struct is defined in <Mstn\MdlApi\MSDialog.h> and is a subclass of MSWindow. MSDialog is the new name for DialogBox and GuiDialog. The table below lists the MSDialog methods and the C-based mdlDialog functions they equate to.
MSDialog Method | Equivalent mdlDialog Function |
---|---|
Find | mdlDialog_findByTypeAndId |
Open | mdlDialog_openWithMD |
OpenMessageBox | mdlDialog_openMessageBox |
OpenModal | mdlDialog_openModalWithMD |
QueueCommandNumber | mdlDialog_cmdNumQueueExt |
MSDialog Method | Equivalent mdlDialog Function or Member |
---|---|
AddHookHandler | mdlDialog_addHookHandler |
Close | mdlDialog_close |
CloseCommandQueue | mdlDialog_closeCommandQueue |
FindItemAtPoint | mdlDialog_findItemIndex |
GetCancelItem | mdlDialog_itemGetCancel |
GetDefaultItem | mdlDialog_itemGetDefault |
GetFontHeight | fontHeight member or mdlDialog_fontGetHeight |
GetFontIndex | mdlDialog_fontIndexGet |
GetFontInfo | mdlDialog_fontGetInfo |
GetItemByIndex | mdlDialog_itemGetByIndex |
GetItemByTypeAndId | mdlDialog_itemGetByTypeAndIdEx |
GetItemPtrByTypeAndId | GetItemByTypeAndId method & DialogItem.GetTypePtr |
GetItemCount | mdlDialog_itemsGetNumberOf |
GetLayoutHelper | mdlDialog_getLayoutHelper |
GetOwnerMD | mdlDialog_ownerMDGet |
GetResourceId | mdlDialog_getResourceId |
GetRootRawItem | mdlDialog_rItemRootGet |
GetStringWidth | mdlDialog_stringWidth |
GetStringNWidth | mdlDialog_stringnWidth |
GetUserData | mdlDialog_userDataPtrGet |
HasFocus | mdlDialog_hasFocus |
ItemSetEnabledByTypeAndId | mdlDialog_itemSetEnabledByTypeAndId |
ItemSetValueByTypeAndId | mdlDialog_itemSetStringValueByTypeAndId |
ItemSynchByTypeAndId | mdlDialog_itemSynchByTypeAndId |
PopupClose | mdlDialog_popupClose |
QueueCommandNumberByDb | mdlDialog_cmdNumQByDbExt |
Refresh | mdlDialog_refresh |
SendUserMessageToHook | mdlDialog_hookDialogSendUserMsg |
SetCancelItem | mdlDialog_itemSetCancel |
SetDefaultItem | mdlDialog_itemSetDefault |
SetLayoutHelper | mdlDialog_setLayoutHelper |
SetLastActionType | mdlDialog_lastActionTypeSet |
SetUserData | mdlDialog_userDataPtrSet |
Show | mdlDialog_show |
The MSWindow struct is defined in <Mstn\MdlApi\MSWindow.h> and is a subclass of BaseWindow. MSWindow is the new name for GuiWindow. The table below lists the MSWindow methods and the C-based mdlWindow functions they equate to.
MSWindow Method | mdlWindow Function or Member |
---|---|
Activate | mdlWindow_setInputFocusExt |
ClearRect | mdlWindow_rectClear |
Close | mdlWindow_close |
GetAttributes | mdlWindow_attributesGet |
GetContentRectGlobal | mdlWindow_contentRectGetGlobal |
GetContentRectLocal | mdlWindow_contentRectGetLocal |
GetGlobalRectGlobal | mdlWindow_globalRectGetGlobal |
GetGlobalRectLocal | mdlWindow_globalRectGetLocal |
GetViewport | m_viewPort member |
GetDialogP | (MSDialogP) this if mdlWindow_isDialogBox |
Hide | mdlWindow_hide |
IsActive | mdlWindow_isActiveAndVisible |
IsFocusable | attributes.isFocusable Member |
IsObscured | guiWindow_isObscured |
IsVisible | mdlWindow_isVisible |
Show | mdlWindow_show |
The BaseWindow struct is defined in <Mstn\MdlApi\BaseWindow.h> and is a subclass of WindowInfo.
BaseWindow Method | mdlWindow Function or Member |
---|---|
GetDockExtent | dockExtent member |
GetDockPosition | mdlWindow_getDocked |
GetDockPriority | mdlWindow_getDockPriority |
GetTitle | mdlWindow_titleGet |
GetTitleCP | name member |
IsDisplayed | mdlWindow_isDisplayed |
Maximized | mdlWindow_isMaximized |
Minimized | mdlWindow_isMinimized |
SetTitle | mdlWindow_titleSet |
The WindowInfo struct is also defined in <Mstn\MdlApi\BaseWindow.h>.
WindowInfo Method | mdlWindow Function or Member |
---|---|
GetNext | mdlWindow_getNext |
GetPrevious | mdlWindow_getPrevious |
GetGraphHandle | graphHandle member |
GetScreenNumber | mdlWindow_screenNumGet |
The DialogItem struct is defined in <Mstn\MdlApi\DialogItem.h>. The table below lists the DialogItem methods and the C-based mdlDialog functions they equate to.
DialogItem Method | mdlDialog Function or Member |
---|---|
Draw | mdlDialog_rItemDrawEx |
GetAttributes | attributes member |
GetColor | mdlDialog_rItemGetColor |
GetDialog | rawItemP->ownerDialogP member |
GetId | id member |
GetLabel | mdlDialog_rItemLabelGet |
GetLabelLength (# characters) | mdlDialog_rItemLabelLengthGet |
GetLabelWidth (# pixels) | GetLabelWidth |
GetNextVisible | mdlDialog_itemGetNextVisible |
GetOwnerItem | mdlDialog_rItemOwnerItemGet |
GetPopupMenuText | mdlDialog_rItemPopupMenuLabelGet |
GetRawItem | rawIPtemP member |
GetRect | rect member |
GetType | type member |
GetState | mdlDialog_rItemStateGet |
GetTypePtr | static_cast<T> if (itemType == this->type) |
GetValue (MSValueDescrR) | mdlDialog_rItemValueGet |
GetValue (WStringR) | mdlDialog_rItemStringValueGet |
HasFocus | attributes.hasFocus member |
Hide | mdlDialog_rItemHide |
IsEnabled | attributes.enabled member |
IsFocusable | mdlDialog_rItemIsFocusable |
IsDisplayable | mdlDialog_rItemIsDisplayable |
Move | mdlDialog_rItemMove |
Obscure | mdlDialog_rItemObscure (true) |
PopupClose | mdlDialog_rItemPopupClose |
PopupOpen | mdlDialog_rItemPopupOpen |
ReloadData | mdlDialog_rItemReloadData |
SetBalloonText | mdlDialog_rItemBalloonTextSet |
SetColor | mdlDialog_rItemSetColor |
SetDisabledBalloonText | mdlDialog_rItemDisabledBalloonTextSet |
SetEnabled | mdlDialog_rItemEnabledStateSet |
SetExtent | mdlDialog_rItemExtentSet |
SetFlyoverText | mdlDialog_rItemFlyoverTextSet |
SetLabel | mdlDialog_rItemLabelSet |
SetLabelFont | mdlDialog_rItemLabelFontSet |
SetPopupMenuText | mdlDialog_rItemPopupMenuTextSet |
SetState | mdlDialog_rItemStateSet |
SetValue (MSValueDescrCR) | mdlDialog_rItemValueSet |
SetValue (WCharCP) | mdlDialog_rItemStringValueSet |
Show | mdlDialog_rItemShow |
Synchronize | mdlDialog_rItemSynch |
SynchornizeOthers | mdlDialog_rItemSynchOthers |
Unobscure | mdlDialog_rItemObscure (false) |
Some of the MDL Dialog Items have been exposed as new structs with methods. The <Mstn\MdlApi\DialogItems.h> header includes a header per Dialog Item that has an associated struct. As mentioned before, we are evaluating the cost-benefit ratio to determine whether we should add more. So other items will be added on an as-needed basis.
The ability to develop Dialog Hooks and Dialog Item Hooks in C++ has been added. The C++ version of a hook is known as a "Hook Handler". There is a base class for the hook handlers: DialogHookHandler and DialogItemHookHandler. These are defined in <Mstn\MdlApi\dlogitem.h>. There are virtual methods for each of the hook message types, and there is a structure for most of the message types. The same structures from the DialogMessage and DialogItemMessage "u" unions are used as arguments to the hook handler methods. This introduces a level of type safety that did not exist with the "u" unions. The only limitation to this new architecture is that switch case "fall-through" is no longer possible. However, this limitation can easily be compensated for with a private method that one or more hook handler methods call.
The Message Type struct examples below are in <Mstn\MdlApi\dlogitem.h>. The structs that were defined directly in the DialogMessage and DialogItemMessage "u" unions in V8i were split out into separate structs in CONNECT Edition, as you see below. Those structs are then referenced in DialogMessage, DialogItemMessage and the various hook handler methods.
Each dialog hook handler is a subclass of DialogHookHandler. Hook IDs are still supported and can be referenced in a resource file. A static method within the hook handler serves as the function published as the dialog hook. As a convention, this method should be named "HookResolve". When a dialog is being created and the dialog hook ID to function association is being resolved, the Dialog Manager sends a DIALOG_MESSAGE_HOOKRESOLVE message to the dialog hook. The "HookResolve" method is responsible for instantiating the dialog hook handler instance, setting the dmP->u.hookResolve.hookHandlerP member to that handler object, and setting dmP->msgUnderstood to true. Thereafter, virtual method overrides on the dialog hook handler object will be called for each message.
Similar to the DialogHookHandler, each dialog item hook handler is a subclass of DialogItemHookHandler. The item hook IDs are still supported and can be referenced in a resource file. A static method within the item hook handler serves as the function published as the item hook. As a convention, this method should be named "HookResolve". When a dialog item is being created and the item hook ID to function association is being resolved, the Dialog Manager sends a DITEM_MESSAGE_HOOKRESOLVE message to the item hook. The "HookResolve" method is responsible for instantiating the item hook handler instance, setting the dimP->u.hookResolve.hookHandlerP member to that handler object, and setting dimP->msgUnderstood to true. Thereafter, virtual method overrides on the item hook handler object will be called for each message.
Dialog hook IDs and item hook IDs are still supported and can be referenced in a resource file. A hook function per ID is still required and is still published by calling mdlDialog_hookPublish. But when using dialog and/or item hook handlers, that function is usually simply a static method in the hook handler, and by convention is named "HookResolve". The example below shows the ID to HookResolve static method association.
In an MDL Dialog Box item list specification, you can only specify a static X and Y position and a width and height for a dialog item. In code, you can alter those positions and sizes, especially when the dialog is being resized. But implementing a resizable dialog can be tedious. In addition, adjusting aspect ratios by localization teams is rather expensive. As stated before, we will not be converting all MDL dialogs to WPF in the CONNECT Edition release.
A dialog layout system provides a simple and powerful way of automatically arranging child controls within a dialog to ensure that they make good use of the available space. For the CONNECT Edition release, we have added a layout system to the MDL Dialog Manager. We implemented an independent layout engine library and integrated it into the MDL Dialog Manager via a C++ API. We have also added the ability to specify layout parameters in a dialog resource. The inspiration for our Layout Manager came from the layout systems in Qt, WPF and Java. Those layout systems are used to describe how controls are laid out in an application's user interface. They automatically position and resize controls when the amount of space available for them changes, ensuring that they are consistently arranged and that the user interface as a whole remains usable. Different label widths are automatically accommodated. Since the layout engine is independent, we can also use it in MFC dialogs.
There are 5 different layout types in the Layout Manager.
The independent layout engine library source is located in the UIFramework repository. The layout engine is integrated into the MDL Dialog Manager via a set of C++ classes that are defined in <Mstn\MdlApi\GuiLayout.h>.
The GuiLayoutHelper maintains the top-level layout for the dialog. GuiLayoutControls are used as wrappers for each of the dialog items on the dialog. When an item is added to a layout using the GuiLayoutControl class, the caller specifies size policies and optional margins and spacing. A size can be specified as fixed or a minimum, maximum and preferred size can be specified via method overrides. The RawItemHdr for each dialog item has a 'layoutPropertiesP' member which points to a GuiLayoutProperties struct. Layout properties such as Size Policy, Margins and Minimum Size are located in this struct. Numerous layouts can be nested to achieve the overall layout for the dialog.
More information on the MDL Dialog Layout Manager can be found on the following pages:
Windows Presentation Foundation, or WPF, is the newest Windows desktop UI framework offered by Microsoft. It was introduced in .NET 3.0 in late 2006. At the request of the Visual Studio 2010 team, some major performance and visual improvements were introduced in .NET 4.0 in 2010. The development languages used are XAML (eXtensible Application Markup Language), which is an XML-based declarative language used to specify the UI elements and layout, and either C# or VB.NET. WPF renders using DirectX instead of GDI/GDI+, and it aims to unify a number of common user interface elements, such as 2D/3D rendering, fixed and adaptive documents, typography, vector graphics, animation and media.
Two of WPF's main strengths are: