MFC Dialog And Native Window Support


MicroStation's Dialog Manager and GUI core subsystem were developed in the early 1990s when MicroStation supported various operating systems. The dialog manager made it possible for MDL application developers to specify a dialog layout and its processing once, and the application would run on the different supported operating systems in a very similar fashion. Although MicroStation is only supported on Windows now, the Dialog Manager is still in place (and will be for the foreseeable future).

In addition to the Dialog Manager resources and code familiar to MDL application developers, support for MFC dialogs and native windows was added in MicroStation V8.1. This enables developers to use existing dialog and window development tools, such as Microsoft's Visual Studio product, to build MicroStation dialogs. The goal was to support MFC dialogs and native windows as seamlessly as possible in MicroStation.

Seamless Support

Certain functionality is expected of dialogs displayed in MicroStation. To achieve this functionality for MFC dialogs and native windows, the following support was added in V8.1:

What Is Provided

Support of MFC dialogs and native windows is provided in two distinct layers:

The Native Window functions, all prefixed with mdlNativeWindow_..., are accessible by linking an application with nativewindow.lib. Both the .lib file and the associated nativewindow.dll are delivered with MicroStation. The nativewindow.dll supports processing both in MicroStation (or another core Bentley product) and outside. For instance, the License Check Out utility found in MicroStation under the Utilities menu may also run outside of MicroStation since it only needs the Bentley License Manager .dll file and no other MicroStation services. When running within MicroStation, the mdlNativeWindow_initialize function gets a handle to the ustation.dll then gets the procedure address of core functions associated with each mdlNativeWindow function.

The Bentley MFC classes are accessible by linking with the static link library nativewinmfc.lib. The current Bentley dialogs are all subclasses of CDialog. Support will be added as needed for other MFC base classes. The dialog types currently supported include:

mdlNativeWindow Functions

If an application developer uses the Bentley MFC classes, the mdlNativeWindow should not be needed. If, however, you are writing a new MFC class to support a unique type of dialog or you are not using MFC but want to add support for a native window, then the mdlNativeWindow functions may be called to achieve these tasks. The mdlNativeWindow functions are grouped into the following categories:

The prototypes for the mdlNativeWindow functions are in msnativewindow.h, and the functions are accessible by linking an application with nativewindow.lib. Both the .lib file and the associated nativewindow.dll are delivered with MicroStation. The nativewindow.dll supports processing both in MicroStation and outside.

Initialize - Establishes Native Window support

mdlNativeWindow_initialize
Initializes the support system for native windows. The only argument is an arbitrary name to be assigned to your application for internal purposes.

/* Initialize Native Window support */
mdlNativeWindow_initialize ("windowTest");

Environment - Determine the runtime environment

These functions are runtime environment query functions.

mdlNativeWindow_isBentleyProductEnv
Determines whether MicroStation or another core Bentley product, such as MicroStation PowerDraft, is running.

if (mdlNativeWindow_isBentleyProductEnv())
{
// Handle MicroStation case
.. . .
}
else
{
// Handle non-MicroStation case
... . .
}

mdlNativeWindow_isTwoApplicationWindows
Determines whether MicroStation is operating in Two Application Screen mode. This mode is changed within MicroStation via the Workspace | Preferences menu followed by the Operations option.

if (mdlNativeWindow_isTwoApplicationWindows())
{
// Move the window from one application window to the other
mdlNativeWindow_changeScreen (m_pParent);
}

Main Window - Get Window Handle, Icon, Instance, Set as Child

To be tightly integrated with MicroStation as the parenting window, certain key pieces of information must be available to the application. These include MicroStation's Main Window Handle, the main application icon, and MicroStation's Instance Handle. To set your application's window as a child of MicroStation, the mdlNativeWindow_setAsChild function should be called.

mdlNativeWindow_getMainHandle
Gets the HWND of MicroStation's main window

HWND parent = mdlNativeWindow_getMainHandle(0);

mdlNativeWindow_getMainIcon
Gets the HICON of MicroStation's main icon

HICON hIcon = mdlNativeWindow_getMainIcon();

mdlNativeWindow_setAsChild
Sets the native window as a child of MicroStation's main window

mdlNativeWindow_setAsChild( m_hWnd, screen );

mdlNativeWindow_getInstance
Gets the HINSTANCE of MicroStation

HINSTANCE hInstance = mdlNativeWindow_getInstance();

MSWindow object - Create, Destroy, Get Handle

Many mdlNativeWindow functions take an MSWindow pointer as an argument. To create an MSWindow object to represent a native window or dialog, call the mdlNativeWindow_createMSWindow function passing the HWND of your window or dialog. For a given MSWindow object, the HWND can be retrieved and the object can be destroyed. Note that destroying the MSWindow object does not close or destroy the native dialog or window.

mdlNativeWindow_createMSWindow
Creates an instance of an MSWindow to reflect the application's native window. This MSWindow is then used in many other mdlNativeWindow_* function calls.

/* Create a MSWindow instance based on the frame's hWnd */
mdlNativeWindow_createMSWindow (&m_pWindow, m_hWnd, FALSE, TRUE, 1);
mdlNativeWindow_getWindowHandle
Gets the HWND associated with a given MicroStation's window
if (NULL != m_pParent)
m_hParent = mdlNativeWindow_getWindowHandle(m_pParent);

mdlNativeWindow_destroyMSWindow
Destroys the MSWindow instance. This function does not close or destroy the native window. It only destroys the MSWindow object associated with a native window.

/*
Remove the window from the list
Destroy the MSWindow instance
*/
mdlNativeWindow_removeFromWindowList (m_pWindow);
mdlNativeWindow_destroyMSWindow (m_pWindow, FALSE);
m_pWindow = NULL;

mdlNativeWindow_hasFocus
Determines whether a given MicroStation window has focus

BoolInt bHasFocus = mdlNativeWindow_hasFocus (m_pWindow);

mdlNativeWindow_setSecondaryDialogHook
Establishes a secondary dialog hook for a MicroStation window. Secondary dialog hooks are useful for capturing events about a MicroStation window even if the window already has another dialog hook. MicroStation's dialog messages are described elsewhere in this guide.

/* Establish a secondary Dialog Hook for a MicroStation dialog */
DialogHookInterests interests;
memset (&interests, 0xff, sizeof interests);
mdlNativeWindow_setSecondaryDialogHook (m_pParent,
CBDockableDialog_SecondaryDialogHook,
&interests);
/* Dialog Hooks have the following signature */
Private void CBDockableDialog_SecondaryDialogHook
(
DialogMessage *dmP
)
{
. . .

Window Menu List - Add, Remove

Similar to most Windows applications, MicroStation has a Window menu listing the available windows to obtain focus. To update this list with your native windows, the mdlNativeWindow_addToWindowList and mdlNativeWindow_removeFromWindowList functions should be called.

mdlNativeWindow_addToWindowList
Adds a native window to MicroStation's window list for menu selection

/* Add this MSWindow to MicroStation's Window List */
mdlNativeWindow_addToWindowList (m_pWindow);

mdlNativeWindow_removeFromWindowList
Removes a native window from MicroStation's window list

void CMainFrame::OnDestroy( )
{
/*
Remove the window from the list
Destroy the MSWindow instance
*/
mdlNativeWindow_removeFromWindowList (m_pWindow);
mdlNativeWindow_destroyMSWindow (m_pWindow, FALSE);
m_pWindow = NULL;
CWnd::OnDestroy();
}

Position - Get Previous, Save

In order to restore and save window and dialog positions from one use to the next, the mdlNativeWindow_getPreviousPosition and mdlNativeWindow_savePosition functions should be called.

mdlNativeWindow_getPreviousPosition
Gets the previous position, size and screen from the preferences

/* get previous position, size and screen */
BSIRect prevRect;
Int screen;
mdlNativeWindow_getPreviousPosition (&prevRect, &screen, m_pWindow);

mdlNativeWindow_savePosition
Saves the current position, size and screen to the preferences

/* Save the position before hiding or closing */
mdlNativeWindow_savePosition (m_pWindow);

Sizing - Minimize, Maximize, Restore, Resize

In order for a native window or dialog to be a "good MicroStation citizen", the application needs to notify MicroStation of certain dialog sizing events. These include minimize, maximize and restore events. The application should also resize the hosting window via the mdlNativeWindow_resize function.

mdlNativeWindow_minimize
Minimizes a native window within the MicroStation windowing framework

mdlNativeWindow_maximize
Maximizes a native window within the MicroStation windowing framework

mdlNativeWindow_restore
Restores a minimized or maximized native window within the MicroStation windowing framework

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
/* Let MicroStation handle the minimize, maximize and restore */
if (nType == SIZE_MINIMIZED)
{
mdlNativeWindow_minimize (m_pWindow);
}
else if (nType == SIZE_MAXIMIZED)
{
mdlNativeWindow_maximize (m_pWindow);
}
else if (nType == SIZE_RESTORED)
{
mdlNativeWindow_restore (m_pWindow);
}
}

mdlNativeWindow_resize
Resizes a window based on the width and height provided.

mdlNativeWindow_resize (m_pWindow, iWidth, iHeight);

Native Content - Set As, Attach, Detach, Get, GetFocused

Native content means that MicroStation is providing a window, which is hosting a native window or dialog as content. Currently, a MicroStation window may only host one native window or dialog.

Native Content is first set into the hosting window by calling mdlNativeWindow_setAsContent, but this does not actually attach the content to the hosting window. The mdlNativeWindow_attachContent attaches the content to the hosting window in order to display the native window or dialog. The content may be detached from hosting window by calling mdlNativeWindow_detachContent. When the dialog is being destroyed, the application should reset the native content for the hosting window by calling mdlNativeWindow_setAsContent with 0/NULL values.

mdlNativeWindow_setAsContent
Sets the HWND and C++ object as native content of the MicroStation parent window. The content is not attached to the window and shown until after the content is attached via the mdlNativeWindow_attachContent function. The content may be detached when hiding the window using the mdlNativeWindow_detachContent function.

/* Set my HWND as content for my MicroStation window parent */
mdlNativeWindow_setAsContent(m_hWnd, this, m_pParent);
/* Attach myself as the content. I can later detach myself but still
be set as the content. */
mdlNativeWindow_attachContent(m_pParent, FALSE);
/* To detach myself as content of a MicroStation window,
set the content to nothing. */
void CBDockableDialog::OnDestroy()
{
mdlNativeWindow_setAsContent(0, NULL, m_pParent);
CBModelessDialog::OnDestroy();
}

mdlNativeWindow_attachContent
Sets the HWND and C++ object as content of the MicroStation parent window

/* Attach myself as the content. I can later detach myself but still
be set as the content. */
mdlNativeWindow_attachContent(m_pParent, FALSE);

mdlNativeWindow_getContent
Retrieves the native content, or MFC C++ object pointer of the child modeless dialog, from a given window.

/* Get the native content from a MicroStation window */
CBDockableDialog *pDockableDialog;

pDockableDialog = (CBDockableDialog *) mdlNativeWindow_getContent(dmP->db);
if (NULL == pDockableDialog)
return;

mdlNativeWindow_getFocusedContent
If the focused MicroStation window contains native content, this retrieves the MFC C++ object pointer of the child modeless dialog.

/* If the current focus window has native content, get it */
CBModelessDialog *pModelessDialog;

pModelessDialog = (CBModelessDialog *) mdlNativeWindow_getFocusedContent();

if (NULL == pModelessDialog)
return true;

mdlNativeWindow_detachContent
Detaches the native dialog content from the hosting MicroStation window.

mdlNativeWindow_detachContent(m_pParent);
mdlNativeWindow_setAsContent(NULL, 0, m_pParent);

On Event - Escape Key, Set/Kill Focus, Mouse, SysCommand

In order for a native window or dialog to be a "good MicroStation citizen", the application needs to notify MicroStation of certain dialog events. These include focus, activate, certain key and mouse events, and the system command events.

mdlNativeWindow_onSetFocus
Should be called in response to a WM_SETFOCUS event. This allows for proper focus handling in MicroStation.

/* In the modeless frame processing, tell MicroStation about a focus change */
void CNativeDialogFrame::OnSetFocus( CWnd* pOldWnd )
{
CWnd::OnSetFocus( pOldWnd );
if( pOldWnd != NULL )
mdlNativeWindow_onSetFocus( m_windowP, pOldWnd->m_hWnd );
}

mdlNativeWindow_onMouseActivate
Should be called in response to a WM_MOUSEACTIVATE event.

/* In the modeless frame processing, tell MicroStation about a mouse activate */
int CBModelessFrame::OnMouseActivate( CWnd* pDesktopWnd, UINT nHitTest, UINT message )
{
int status = CWnd::OnMouseActivate (pDesktopWnd, nHitTest, message);

mdlNativeWindow_onMouseActivate (m_pWindow, nHitTest, message);

return status;
}

mdlNativeWindow_onKillFocus
Should be called in response to a WM_KILLFOCUS event.

/* Before opening a modal dialog from a modeless dialog, tell MicroStation
your modeless dialog is about to lose focus. */
mdlNativeWindow_onKillFocus (m_pParent, 0);

mdlNativeWindow_onEscapeKey
Should be called in response to a WM_KEYDOWN event for a VK_ESCAPE character.

void CNativeDialogFrame::OnEscapeKey(LPMSG lpMsg )
{
mdlNativeWindow_onEscapeKey( m_windowP, lpMsg );
}

mdlNativeWindow_onSysCommand
Should be called in response to a WM_SYSCOMMAND event.

void CBModelessFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
mdlNativeWindow_onSysCommand (m_pWindow, nID, lParam);
CWnd::OnSysCommand(nID, lParam);
}

mdlNativeWindow_onMouse
Should be called in response to a WM_MOUSEMOVE or any Windows Button event such as WM_LBUTTONDOWN.

/*---------------------------------------------------------------**//**
* @description Called when the mouse is moved over the dialog.
* @bsimethod
+----------------+---------------+---------------+---------------+---*/
void CBModelessFrame::OnMouseMove( UINT nFlags, CPoint point )
{
CWnd::OnMouseMove(nFlags, point);
mdlNativeWindow_onMouse (m_pWindow, WM_MOUSEMOVE, nFlags, point.x, point.y);
}
/*---------------------------------------------------------------**//**
* @description Called when the left mouse button is clicked.
* @bsimethod
+----------------+---------------+---------------+---------------+---*/
void CBModelessFrame::OnLButtonDown( UINT nFlags, CPoint point )
{
CWnd::OnLButtonDown(nFlags, point);
mdlNativeWindow_onMouse (m_pWindow, WM_LBUTTONDOWN, nFlags, point.x, point.y);
}
/*---------------------------------------------------------------**//**
* @description Called when the left mouse button is let up.
* @bsimethod
+----------------+---------------+---------------+---------------+---*/
void CBModelessFrame::OnLButtonUp( UINT nFlags, CPoint point )
{
CWnd::OnLButtonUp(nFlags, point);
mdlNativeWindow_onMouse (m_pWindow, WM_LBUTTONUP, nFlags, point.x, point.y);
}
/*---------------------------------------------------------------**//**
* @description Called when the right mouse button is clicked.
* @bsimethod
+----------------+---------------+---------------+---------------+---*/
void CBModelessFrame::OnRButtonDown( UINT nFlags, CPoint point )
{
CWnd::OnRButtonDown(nFlags, point);
mdlNativeWindow_onMouse (m_pWindow, WM_RBUTTONDOWN, nFlags, point.x, point.y);
}
/*---------------------------------------------------------------**//**
* @description Called when the right mouse button is let up.
* @bsimethod
+----------------+---------------+---------------+---------------+---*/
void CBModelessFrame::OnRButtonUp( UINT nFlags, CPoint point )
{
CWnd::OnRButtonUp(nFlags, point);
mdlNativeWindow_onMouse (m_pWindow, WM_RBUTTONUP, nFlags, point.x, point.y);
}
/*---------------------------------------------------------------**//**
* @description Called when the middle mouse button is clicked.
* @bsimethod
+----------------+---------------+---------------+---------------+---*/
void CBModelessFrame::OnMButtonDown( UINT nFlags, CPoint point )
{
CWnd::OnMButtonDown(nFlags, point);
mdlNativeWindow_onMouse (m_pWindow, WM_MBUTTONDOWN, nFlags, point.x, point.y);
}
/*---------------------------------------------------------------**//**
* @description Called when the middle mouse button is let up.
* @bsimethod
++---------------+---------------+---------------+---------------+---*/
void CBModelessFrame::OnMButtonUp( UINT nFlags, CPoint point )
{
CWnd::OnMButtonUp(nFlags, point);
mdlNativeWindow_onMouse (m_pWindow, WM_MBUTTONUP, nFlags, point.x, point.y);
}

Framed Dialog - Get Framed Window from MicroStation

A MicroStation window acts as the host for an MFC dialog or native window. To get an instance of a hosting window from MicroStation, call mdlNativeWindow_getFramedWindow.

mdlNativeWindow_getFramedWindow
Creates a framed window and returns the MSWindow instance for the new window

m_bResizeable = bResizeable;

if (mdlNativeWindow_isBentleyProductEnv())
{
mdlNativeWindow_getFramedWindow (&m_pParent, nID, pTitle, bResizeable,
NULL, NULL);
m_hParent = mdlNativeWindow_getWindowHandle(m_pParent);
CDialog::Create(m_nID, CWnd::FromHandle(m_hParent));
}
else
{
m_pModelessFrame = new CBModelessFrame (nID, pTitle, bResizeable,
iDefaultWidth, iDefaultHeight, this);
m_pParent = m_pModelessFrame->GetMSWindow();
CDialog::Create(m_nID, m_pModelessFrame);
}

Tool Settings - Get MicroStation's Tool Settings Window, Set Native Flag

The MicroStation Tool Settings window can host an MFC dialog or native window during a command. To get the MSWindow instance of the Tool Settings window from MicroStation, call mdlNativeWindow_getToolSettingsWindow.

mdlNativeWindow_getToolSettingsWindow
Gets the MSWindow instance for MicroStation's Tool Settings window

/* Get MicroStation's Tool Settings window, and set into my parent pointer variable */
mdlNativeWindow_getToolSettingsWindow(&m_pParent);
if (NULL != m_pParent)
{
/* Get the parent's (MSWindow) Windows handle (HWND)
then create the MFC dialog */
m_hParent = mdlNativeWindow_getWindowHandle(m_pParent);
CDialog::Create(m_nID, CWnd::FromHandle(m_hParent));
}

mdlNativeWindow_setToolSettingsNative
Tells MicroStation whether the Tool Settings window content is a native dialog or not

/* Notify the Tool Settings window the content is native */
mdlNativeWindow_setToolSettingsNative(TRUE);
/* Notify the Tool Settings window the content is no longer native */
mdlNativeWindow_setToolSettingsNative (FALSE);

Dockable - Get Dockable Window from MicroStation

MicroStation has its own window and toolbox docking system. To get an instance of a dockable hosting window from MicroStation, call mdlNativeWindow_getDockableWindow.

mdlNativeWindow_getDockableWindow
Creates a dockable window and returns the MSWindow instance for the new window

/* Get instance of a dockable window from MicroStation */
mdlNativeWindow_getDockableWindow(&m_pParent, nID, pTitle, NULL, NULL);
if (NULL != m_pParent)
{
m_hParent = mdlNativeWindow_getWindowHandle(m_pParent);
CDialog::Create(m_nID, CWnd::FromHandle(m_hParent));
}

Accelerator Table - Register, Unregister

mdlNativeWindow_registerAcceleratorTable
Associates an accelerator table with a MicroStation window. Since a window may have multiple accelerator tables, this function may be called for each accelerator table.

mdlNativeWindow_unregisterAcceleratorTables
Disassociates all registered accelerator tables from a MicroStation window.

void CMainFrame::OnShowWindow( BOOL bShow, UINT nStatus )
{
/* Hiding the window - save the position */
if (bShow)
{
/* Register accelerator tables before showing */
mdlNativeWindow_registerAcceleratorTable (m_pWindow, m_hAccelTable);
}
else
{
/* Unregister accelerator tables and save the position before hiding */
mdlNativeWindow_unregisterAcceleratorTables (m_pWindow);
mdlNativeWindow_savePosition (m_pWindow);
}
}

Special Processing - Change Screen

mdlNativeWindow_changeScreen
Changes the native window from one MicroStation application window to the other

if (mdlNativeWindow_isTwoApplicationWindows())
{
// Move the window from one application window to the other
mdlNativeWindow_changeScreen (m_pParent);
}

MFC Classes

The prototypes for the Bentley MFC classes are in msmfc.h, and the functions are accessible by linking an application with the static link library nativewinmfc.lib, which is delivered with MicroStation. Note that nativewinmfc.lib is built with the following definitions: _AFXDLL and _DLL. If this is not valid for your application, we can build another static link library with the appropriate definitions unique to your application. The source code for the Bentley MFC classes is available in a separate download for Bentley Developer Network members. NOTE: Please find attached a helpful MFC Presentation and Source code Example.

The current Bentley dialogs are all direct or indirect subclasses of CDialog. Support will be added as needed for other MFC base classes. The dialog types currently supported include:

Please note that since framing windows parent the modeless dialogs, the modeless dialog resources should be defined with the Child style and "None" border. Modal dialogs are not framed by another window; therefore, the modal dialog resources should use the Overlapped style and Dialog Frame border.

Modal - CBModalDialog

CBModalDialog is derived from CDialog. Dialogs derived from CBModalDialog are parented by MicroStation's main window. The modal dialog resource should use the Overlapped style and Dialog Frame border.

Modeless - CBModelessDialog

CBModelessDialog is the base class for the other modeless dialog classes. Applications usually need not derive their own class from CBModelessDialog, but rather will derive from CBFramedModelessDialog, CBToolSettingsDialog, CBDockableDialog or CBHostedDialog. If the functionality in the aforementioned classes is not sufficient for an application's needs, then CBModelessDialog could be used as the base class for your new dialog class.

Framed Modeless - CBFramedModelessDialog

CBFramedModelessDialog is the modeless dialog class that will probably be used the most. A subclass of CBFramedModelessDialog is a normal modeless dialog, which may be resizable or not.

Modeless Dialog Frame - CBModelessFrame

When running within MicroStation or another core Bentley product, the host window for a CBFramedModelessDialog is obtained by calling mdlNativeWindow_getFramedWindow. When running outside MicroStation, the hosting window is obtained by instantiating CBModelessFrame, which is a subclass of CWnd. CBModelessFrame sets up and registers a window class, creates a window, then proceeds to call several mdlNativeWindow functions to create an MSWindow object for the frame, gets the previous position, sets the frame as a child of MicroStation, and shows the window. It also calls mdlNativeWindow functions in several event handlers.

Tool Settings - CBToolSettingsDialog

The CBToolSettingsDialog is unique to the MicroStation environment. Dialogs derived from this class are hosted by MicroStation's Tool Settings window as part of a MicroStation command.

When the command starts, the application's Tool Settings dialog should be instantiated, and the Create method should be called. When the command stops, the object's CloseContent method should be called as part of the command cleanup process.

Dockable - CBDockableDialog

The CBDockableDialog is also unique to the MicroStation environment. MicroStation has its own window and toolbox docking system, and this class allows an MFC dialog to be hosted by a dockable window within MicroStation.

CBDockableDialog is derived from CBModelessDialog. CBDockableDialog adds the GetDockedExtent method.

BOOL CBDockableDialog::GetDockedExtent
(
/* Return TRUE if handled */
int iDockPosition, /* => DOCK_TOP, _LEFT, _BOTTOM, _RIGHT */
int *pExtentFlag, /* <= DOCKEXTENT_DONTCARE, _FULLWIDTHORHEIGHT, or
_SPECIFIED */
Point2d *pDockExtent /* <= extent when in docked state */
)
{
// Example: if application flag says use current height, use it.
// otherwise, use the default height from MicroStation
CRect rc;
GetClientRect (rc);
pDockExtent->x = rc.right - rc.left;
if (bUseCurrentSize)
{
pDockExtent->y = rc.bottom - rc.top;
}
else
{
// Use default docked height
int dockHeight;
mdlWindow_getCommonDockedExtent (NULL, &dockHeight);
pDockExtent->y = dockHeight;
}
*pExtentFlag = DOCKEXTENT_SPECIFIED;
return TRUE;
}

.NET Dockable - CBNETDockableDialog

The CBNETDockableDialog is also unique to the MicroStation environment. This type of docking allows tabbed dialogs and dialogs docked beside one another in a vertical or horizontal fashion.

CBNETDockableDialog is derived from CBDockableDialog and, therefore, has the GetDockedExtent method described in the CBDockableDialog section.

Hosted - Combination with MDL dialog - CBHostedDialog

The CBHostedDialog is also unique to the MicroStation environment. Dialogs derived from this class can share a hosting window with MDL dialog items. The only caveat with using this class is the tab key order; the tab key only circulates through the items in a given environment. If focus is on an MDL dialog item, the user may only tab to another dialog item. If focus is on an MFC control, tabbing will only shift focus to another MFC control.

CBHostedDialog is derived from CBModelessDialog. CBHostedDialog overrides the base OnDialogUpdate method and adds the GetAttachPoint method.

BOOL NativeCombination::GetAttachPoint
(
Point2d *pAttachPoint /* <= offset for attaching the native content */
)
{
/* Any offset may be applied here */
pAttachPoint->x = 0;
pAttachPoint->y = 60;
return TRUE;
}

"Do"s

"Don't"s EXTREMELY IMPORTANT !!!

Examples

mdlNativeWindow examples

MainFrm
The following example shows how the mdlNativeWindow functions can be used to support a window derived from CFrameWnd. Note that the Bentley MFC classes are not used in this example.

MainFrm.h #include
class CMainFrame : public CFrameWnd
{
public:
MSWindow *m_pWindow;
.. . .
MainFrm.cpp int CMainFrame::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
CWnd::OnCreate (lpCreateStruct);
/* Initialize Native Window support */
mdlNativeWindow_initialize ("windowTest");
/* Create a MSWindow instance based on the frame's hWnd */
mdlNativeWindow_createMSWindow (&m_pWindow, m_hWnd, FALSE, TRUE, 1);
/* set up default position and size */
BSIRect prevRect;
UINT nFlags;
int screen;
prevRect.origin.x = 0;
prevRect.origin.y = 0;
prevRect.corner.x = prevRect.origin.x + 400 - 1;
prevRect.corner.y = prevRect.origin.y + 200 - 1;
/* get previous position, size and screen */
mdlNativeWindow_getPreviousPosition (&prevRect, &screen, m_pWindow);
/* Make MicroStation my parent */
mdlNativeWindow_setAsChild (m_pWindow, screen, FALSE);
/* Move the window to the previous position, if any */
nFlags = SWP_NOZORDER | SWP_NOACTIVATE;
if (prevRect.origin.x == 0 && prevRect.origin.y == 0)
prevRect.origin.x = prevRect.origin.y == 50;
SetWindowPos (NULL, prevRect.origin.x, prevRect.origin.y,
prevRect.corner.x-prevRect.origin.x+1,
prevRect.corner.y-prevRect.origin.y+1,
nFlags);
/* Add this MSWindow to MicroStation's Window List */
mdlNativeWindow_addToWindowList (m_pWindow);
return 0;
}
void CMainFrame::OnDestroy( )
{
/*
Remove the window from the list
Destroy the MSWindow instance
*/
mdlNativeWindow_removeFromWindowList (m_pWindow);
mdlNativeWindow_destroyMSWindow (m_pWindow, FALSE);
m_pWindow = NULL;
CWnd::OnDestroy();
}
void CMainFrame::OnShowWindow( BOOL bShow, UINT nStatus )
{
/* Hiding the window - save the position */
if (bShow)
{
/* Register accelerator tables before showing */
mdlNativeWindow_registerAcceleratorTable (m_pWindow, m_hAccelTable);
}
else
{
/* Unregister accelerator tables and save the position before hiding */
mdlNativeWindow_unregisterAcceleratorTables (m_pWindow);
mdlNativeWindow_savePosition (m_pWindow);
}
}
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
/* Notify MicroStation of minimize, maximize and restore and allow it process */
if (nType == SIZE_MINIMIZED)
{
mdlNativeWindow_minimize (m_pWindow);
}
else if (nType == SIZE_MAXIMIZED)
{
mdlNativeWindow_maximize (m_pWindow);
}
else if (nType == SIZE_RESTORED)
{
mdlNativeWindow_restore (m_pWindow);
}
}
void CMainFrame::OnSetFocus(CWnd* pOldWnd)
{
CWnd::OnSetFocus(pOldWnd);
if (NULL != pOldWnd)
mdlNativeWindow_onSetFocus (m_pWindow, pOldWnd->m_hWnd);
}

BDN MFC Session and Code Example

communities.bentley.com/.../MFCSession.zip