Professional UI Solutions
Site Map   /  Register

Getting Started with Prof-UIS



The article is intended to help you start using Prof-UIS. Although Prof-UIS is an MFC extension library and follows MFC standards to some extent, the article puts emphasis on difference issues rather then what the libraries have in common.

We recommend you refer to the following samples while reading this article: SDI, SDIDOCVIEW, MDI and MDIDOCVIEW. The ProfUIS Controls sample may also be useful if you are interested in how to work with a menu bar and/or toolbars inside dialog-based applications.

1. Setting Paths and Compiling

After completing the installation, you need to set up the required paths. This can be done either with the Prof-UIS Integration Wizard, or manually. The first way is simple and straightforward: Just select the check box Set Prof-UIS paths in Microsoft Visual Studio Environment Variables and click on the Next button. The second is described below.

Select Options from the Tools menu. Open Directories tab in Visual Studio 6 or open the Projects folder and, then, select Visual C++ in Visual Studio 7.0/7.1/8.0. In the Show directories for drop-down list, specify file types and corresponding paths according to the following table:

File types Paths Visual Studio
Include files .../Prof-UIS/Include 6.0 - 12.0
Source files .../Prof-UIS/Include
Library files .../Prof-UIS/Bin_600 6.0
.../Prof-UIS/Bin_700 7.0
.../Prof-UIS/Bin_710 7.1
.../Prof-UIS/Bin_800 8.0
.../Prof-UIS/Bin_900 9.0
.../Prof-UIS/Bin_1000 10.0
.../Prof-UIS/Bin_1100 11.0
.../Prof-UIS/Bin_1200 12.0

Use the Prof-UIS Integration Wizard or Visual Studio's Batch build (or Configuration manager) to compile Prof-UIS and its samples to any of the available build configurations. Prof-UIS samples serve on one hand as an example of how your application may look, and on the other, they should help you implement library's features in your products.

2. Prof-UIS Application Wizard

You may take advantage of creating a new application with the Prof-UIS Application Wizard, which can be added/removed from Visual Studio 6.0/7.0/7.1/8.0 with the Pros-UIS Integration Wizard. When creating a new project, select the ProfUISAppWizard template in the Visual C++/Prof-UIS folder. The wizard will pass you through the steps of creating a standard MFC application and, then, through the steps relating to Prof-UIS.

3. SDI/MDI Applications

In this section, we will outline some issues related to migrating from already existing MFC SDI/MDI applications to those based on Prof-UIS. Before starting to use Prof-UIS, do not forget to add the following line to your StdAfx.h file:

#include < Prof-UIS.h > // Prof-UIS library 

Make also sure you set appropriate .\lib, .\bin and .\include paths in the Visual Studio settings (see Setting Paths and Compiling).

3.1 Menu Bar and Toolbars

Make the following changes in your code:

  • Replace the toolbar names with CExtToolControlBar
  • Use CExtMenuControlBar for your menu bar

There can be many CExtToolControlBar toolbars in your applications and only one menu bar. You may initialize the menu bar in the CMainFrame::OnCreate() method with this code:

if(!m_wndMenuBar.Create(     NULL, // _T("Menu Bar"),     this,     ID_VIEW_MENUBAR     ) {     TRACE0("Failed to create menubar\n");     return -1;  } 

Make some changes in CMainFrame::PreTranslateMessage(MSG* pMsg) to allow the menu bar to work correctly:

BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)  {     if( m_wndMenuBar.TranslateMainFrameMessage(pMsg) )         return TRUE;     return CMDIFrameWnd::PreTranslateMessage(pMsg); }

Replace the current code for creating Prof-UIS toolbars with the following code snippet:

if( !m_wndToolBar.Create(         _T( "Toolbar name" ),         this,         AFX_IDW_TOOLBAR     )     || !m_wndToolBar.LoadToolBar( IDR_MAINFRAME )     ) {     TRACE0( "Failed to create toolbar" );     return -1; } 

The menu bar and each toolbar should have correspondent entries in the message map of the main frame window:


To enable Prof-UIS control bars (including the menu bar and toolbar) to be docked correctly, you should use CExtControlBar::FrameEnableDocking(this) instead of the MFC's EnableDocking() method:

if( !CExtControlBar::FrameEnableDocking(this) ) {     ASSERT( FALSE );     return -1; } 

3.2 Resizable Control Bars

Add the m_wndResizableBar bar property of CExtControlBar type to your frame window declaration:

CExtControlBar m_wndResizableBar; 

Add the resizable bar creation code to the OnCreate() method:

if( ! m_wndResizableBar.Create(         _T( "Resizable bar name" ),         this,         ID_YOUR_RESIZABLE_BAR         )     ) {     TRACE0( "Failed to create resizable bar" );     return -1; } 

Create any window that you want to insert into the resizable bar and specify m_wndResizableBar as the parent of this window.

Now we need to enable the resizable bar to be docked. This can be done with two methods:

EnableDocking( &m_wndResizableBar ) //enables control bar to be docked CExtControlBar::FrameEnableDocking(this)//single call for entire frame                                         //window; enables drag-n-drop                                         //of control bars inside frame 

You can set the initial state of a resizable bar (docked, floating, or placed inside a tab container? if docked, then how exactly it should be docked?) with the following methods of CExtControlBar: DockControlBar(), DockControlBarIntoTabbedContainer() and FloatControlBar().

DockControlBar() allows you to dock a resizable bar with one of the frame sides: top, bottom, left, or right. Since resizable bars can be docked in a nested way, you should also specify a nested level with the second parameter, which must be equal to or greater than 1 (read the article Docking Mechanism Explained for details):

m_wndResizableBar.DockControlBar( AFX_IDW_DOCKBAR_LEFT, 1, this, false );

The second overload of DockControlBar() enables you to arrange a resizable bar relative to others, which are already docked. In the code below, first, the OtherBar bar is docked, and then it is placed next to the bar specified with m_wndResizableBar:

OtherBar.DockControlBar( AFX_IDW_DOCKBAR_LEFT, 1, this, false ); OtherBar.DockControlBar( &m_wndResizableBar, true, false, NULL, false );

The DockControlBarIntoTabbedContainer method, as it is obvious from its name, allows you to place resizable bars inside the Prof-UIS tab container and FloatControlBar() makes resizable bars initially floating.

You may implement a Show or Show/Hide command for your resizable bar. For example, to toggle between the visible and invisible states, you need to add the following lines to the main frame window's message map:


To enable the auto hide feature for control bars, add the following lines:

if( !CExtControlBar::FrameInjectAutoHideAreas(this) ) {     ASSERT( FALSE );     return -1; }

You may also add declaration and implementation code for the OnUpdateControlBarMenu and OnBarCheck methods. For example, if you use the auto hide feature and want to implement the ID_YOUR_RESIZABLE_BAR command, then you should add the following code to your application.

//declaration: afx_msg void OnUpdateControlBarMenu(CCmdUI* pCmdUI); afx_msg BOOL OnBarCheck(UINT nID); //implementation: void CMainFrame::OnUpdateControlBarMenu(CCmdUI* pCmdUI) {     // CFrameWnd::OnUpdateControlBarMenu( pCmdUI );     CExtControlBar::DoFrameBarCheckUpdate(             this,             pCmdUI,             false         ); } BOOL CMainFrame::OnBarCheck(UINT nID) {     // return CFrameWnd::OnBarCheck( nID );     return         CExtControlBar::DoFrameBarCheckCmd(             this,             nID,             false         ); }

In this case, the ID_YOUR_RESIZABLE_BAR command will only activate (or show) the resizable bar. You cannot hide it with the correspondent menu items. This behavior is implemented in the Visual Studio .NET IDE.

3.3 MDI Tabs

Prof-UIS allows you to easily group your MDI child windows with tabs. Just declare the variable m_wndMdiTabs of CExtTabMdiWnd type in your main frame window class and add the following code to the OnCreate() method:

if( !m_wndMdiTabs.Create(this) ) {     TRACE0("Failed to create m_wndMdiTabs\n");     return -1; }

3.4 GUI Persistence

In most cases it is user friendly to store the state of the application's GUI elements between launches. Add to the header of the CMainFrame class the WINDOWPLACEMENT m_dataFrameWP variable. To the CMainFrame's constructor, add the initialization code below:

::memset( &m_dataFrameWP, 0, sizeof(WINDOWPLACEMENT) ); m_dataFrameWP.length = sizeof(WINDOWPLACEMENT); m_dataFrameWP.showCmd = SW_HIDE; 

To restore the state of the main frame window, overload the CMainFrame::ActivateFrame method with:

void CMainFrame::ActivateFrame(int nCmdShow)  {     if( m_dataFrameWP.showCmd != SW_HIDE )     {         SetWindowPlacement( &m_dataFrameWP );         CMDIFrameWnd::ActivateFrame( m_dataFrameWP.showCmd );         m_dataFrameWP.showCmd = SW_HIDE;         return;     }     CMDIFrameWnd::ActivateFrame(nCmdShow); } 

The invoke of the CExtControlBar::ProfileBarStateSave function in the the DestroyWindow() method of CMainFrame saves the state of all control bars.

CWinApp * pApp = ::AfxGetApp(); ASSERT( pApp != NULL ); ASSERT( pApp->m_pszRegistryKey != NULL ); ASSERT( pApp->m_pszRegistryKey[0] != _T('\0') ); ASSERT( pApp->m_pszProfileName != NULL ); ASSERT( pApp->m_pszProfileName[0] != _T('\0') ); VERIFY(     CExtControlBar::ProfileBarStateSave(         this,         pApp->m_pszRegistryKey,         pApp->m_pszProfileName,         pApp->m_pszProfileName         )     ); 

To load the application's saved state when starting the application, add the call of CExtControlBar::ProfileBarStateLoad to the OnCreate() method:

if(!CExtControlBar::ProfileBarStateLoad(     this,     pApp->m_pszRegistryKey,     pApp->m_pszProfileName,     pApp->m_pszProfileName,     &m_dataFrameWP     ) ) {     // if the state is not loaded, dock the initial layout     // ..............  } 

3.5 Command Manager

When running most Prof-UIS sample applications, you may have noticed that popup menus display icons for some commands. The very same icons are set for correspondent commands in toolbars. This feature is automatically provided by the Prof-UIS command manager, which is an object of the CExtCmdManager type and can be accessed from within the entire application with the g_CmdManager smart pointer variable.

The command manager is a named collection of command profiles. Each profile is an object of the CExtCmdProfile class. Each profile has its own unique name and keeps a list of HWND handles. This allows a window to "know" which profile it belongs to.

The most important role of the command profile is to keep descriptions of the commands. The command description is a CExtCmdItem object, which keeps information related to a single command:

  • identifier
  • text strings for the menu item, toolbar button, tooltip, and status pane
  • icon
  • command usage statistics required for supporting expandable popup menus

Most applications are based on a single profile in the command manager. This profile keeps HWND of the main frame window or main dialog, which allows the main window and all its child controls to find a required command description automatically.

When starting up the application, you should initialize the command manager. Add your command profile to the command manager and then put all the command descriptions into this profile. You may do this at the beginning of the OnCreate() method of the main frame window or in the OnInitDialog() of the main dialog window:

VERIFY(     g_CmdManager->ProfileSetup(         "name of the command profile",         GetSafeHwnd() // HWND of the frame window         )     ); 

If you register your menu bar and/or toolbar resources in the command manager, all their data will be added to the command manager automatically:

VERIFY(     g_CmdManager->UpdateFromMenu(         "name of the command profile",         IDR_MAINFRAME         )     ); VERIFY(     g_CmdManager->UpdateFromMenu(         "name of the command profile",         IDR_YourMdiProjectsDOCTYPE         )     ); VERIFY(     g_CmdManager->UpdateFromToolBar(         "name of the command profile",         IDR_TOOLBAR1         )     ); 

Finally, notify the command manager about destroying the frame window in CMainFrame::DestroyWindow() (or about the main dialog window in OnOK() and OnCancel()) so that it can release HWND of the window:

g_CmdManager->ProfileWndRemove( GetSafeHwnd() ); 

3.6 Command Manager Persistence

If menus in your application are expandable (i.e. not all menu items are visible when you run the application for the first time), the command manager should also be serialized: at startup specify the list of basic commands (menu items corresponding to these commands are always visible) and load the state of non basic commands (their visibility depends on how often particular commands are used). Please note that this should be done before the UI state of control bars is loaded from the registry or from a file:
static UINT g_statBasicCommands[] = {     ID_COMMAND_0,      ID_COMMAND_1,      ID_COMMAND_2,      . . .     0, // end of list }; CWinApp * pApp = ::AfxGetApp(); VERIFY(     g_CmdManager->SetBasicCommands(         pApp->m_pszProfileName,         g_statBasicCommands         )     ); g_CmdManager->SerializeState(     pApp->m_pszProfileName,     pApp->m_pszRegistryKey,     pApp->m_pszProfileName,     false     );
You can save the command usage statistics with the following code:
// Use this code before saving the UI state of your control bars CWinApp * pApp = ::AfxGetApp(); VERIFY(     g_CmdManager->SerializeState(         pApp->m_pszProfileName,         pApp->m_pszRegistryKey,         pApp->m_pszProfileName,         true         )     );

4. Dialog-Based Applications

To provide your dialog-based application with any of available visual styles (Microsoft Office 2000, XP or 2003) and/or to use the anchoring for its controls, you should inherit the main dialog from the CExtResizableDialog class.

The Prof-UIS dialog has a resizing gripper, which can be on or off with the ShowSizeGrip() method. For example, you may pass FALSE to it in the OnInitDialog handler to turn it off.

As in the standard MFC dialog application, the resizing of the dialog is enabled/disabled in the Border field of the dialog resource's properties.

If you use a menu and want to replace it with that of Prof-UIS, follow the steps below.

Add a custom control to your dialog resource and specify ProfUIS-ControlBar as its window class, IDC_MY_MENUBAR as its control identifier, the value 0x50402034 as its window style and the zero value as its extended style.

Add the CExtMenuControlBar m_wndMenuBar member variable to your dialog and the DDX_Control(pDX, IDC_MY_MENUBAR, m_wndMenuBar) line to the DoDataExchange() method's body.

To assign the required menu resource to your menu bar, you should put the following lines into OnInitDialog():

ASSERT( m_wndMenuBar.GetSafeHwnd() != NULL ); if( !m_wndMenuBar.LoadMenuBar( IDR_MY_MENU_FOR_MENUBAR ) ) {     ASSERT( FALSE );     return FALSE; } 

To stretch your menu bar to the dialog border, you should put the following line somewhere at the end of the OnInitDialog() method:

If your application is dialog-based, you should implement the WM_SIZE message handler in this way:


void CYourDlg::OnSize(UINT nType, int cx, int cy)  {     CExtResizableDialog::OnSize(nType, cx, cy);     if( nType != SIZE_MINIMIZED )     CWnd::RepositionBars(0,0xFFFF,0); } 

The Prof-UIS Controls sample demonstrates how to use the menu bar as a dialog control.

Back To Top Other Articles...