Dynamic bar site

Professional User Interface Suite, Copyright FOSS Software Inc. Help Published with Permission.

Dynamic control bars (the CExtDynamicControlBar class) are created, fully controlled, and serialized by the dynamic bar site object (the CExtDynamicBarSite class). In most cases it is convenient to inherit the CMainFrame (which is always CMDIFrameWnd/CFrameWnd-derived) class from CExtDynamicBarSite so that you can use methods of the dynamic bar site as the methods of CMainFrame. For example,

class CMainFrame
    : public CMDIFrameWnd
    , public CExtDynamicBarSite
{
...
}

or

class CMainFrame
    : public CFrameWnd
    , public CExtDynamicBarSite
{
...
}

Before you start working with the dynamic bar site, it needs to be initialized. The appropriate place for this is the CMainFrame::OnCreate() method:

CExtDynamicBarSite::Install( this );

The dynamic bar site keeps an inner collection of dynamic control bars. This collection can be populated in two ways:

1) The application starts for the first time and that means that the Windows registry, a file, a database or other source does not keep any information about the previous GUI state of the application and control bars in particular. In this case, each dynamic control bar should be created (allocated) with the CExtDynamicBarSite::BarAlloc() method.

2) The CExtDynamicBarSite::StateLoad() static method successfully loads the previously saved GUI state and in this case the entire collection of dynamic control bars is populated by Prof-UIS internally. You can get an array of pointers to dynamic control bars with CExtDynamicBarSite::BarEnumGetArray().

Here is a code snippet from the CMainFrame::OnCreate() method that demonstrates how dynamic control bars can be allocated/initialized:

// allocate and initialize dynamic bars
if( ! CExtDynamicBarSite::StateLoad(
        pApp->m_pszRegistryKey,
        pApp->m_pszProfileName,
        pApp->m_pszProfileName
        )
)
{ // if all bars were not loaded from registry, then allocate them
    HICON hIcon = (HICON)
        ::LoadImage(
            ::AfxGetInstanceHandle(),
            MAKEINTRESOURCE(IDR_MAINFRAME),
            IMAGE_ICON,
            16,
            16,
            0
            );
    ASSERT( hIcon != NULL );
    CExtCmdIcon icon;
    icon.AssignFromHICON( hIcon, false );
    int i;
    for( i = 0; i < __DEMO_BARS_COUNT_ALL; i++ )
    {
        CString strBarCaption;
        strBarCaption.Format(
            _T("Dynamic Bar %d"),
            i
            );
        m_arrAllDynamicBars.Add(
            CExtDynamicBarSite::BarAlloc(
                strBarCaption,
                icon,
                0,
                RUNTIME_CLASS(CSimpleControlBar) //inherited from CExtDynamicControlBar
                )
            );
        ASSERT( m_arrAllDynamicBars[i] != NULL );
        m_arrAllDynamicBars[i]->m_nMdiMenuResourceID =
            IDR_DYNAMIC_BAR;
        m_arrAllDynamicBars[i]->m_nMdiAccelTableResourceID =
            IDR_MAINFRAME;
    } // for( i = 0; i < __DEMO_BARS_COUNT_ALL; i++ )
} // if all bars were not loaded from registry, then allocate them
else
{ // else just get them
    CExtDynamicBarSite::BarEnumGetArray( m_arrAllDynamicBars, false, true );
} // else just get them

Please note that each dynamic control bar has its unique command identifier. It is used when you click a menu item associated with the control bar which causes the control bar to be shown and get focused. Prof-UIS itself generates an appropriate identifier if you set the third argument of the CExtDynamicBarSite::BarAlloc() to 0. Alternatively you can set this command identifier explicitly yourself. To make the menu items correctly updated, CMainFrame::OnCmdMsg() should contain a call of a similar handler of the CExtDynamicBarSite class (otherwise all these menu items will be disabled):

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
{
    if( CExtDynamicBarSite::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ) )
        return TRUE;
...
}

The CExtDynamicBarSite class has an m_nBarListInMenusCmdID property, which allows you to create a pop-up menu with a list of all dynamic control bars (see Figure 6). You add a pop-up menu marker to the appropriate menu resource (see Figure 7) and then just assign its ID to the m_nBarListInMenusCmdID property:

CExtDynamicBarSite::m_nBarListInMenusCmdID = ID_DYNAMIC_BARS_LIST;

Prof-UIS constructs this menu dynamically but using virtual functions of the CExtDynamicControBar class (OnInitDbsMenu() or OnInsertDynamicBarCommandIntoPopupMenu()), you can modify it.


Figure 7 Pop-up menu marker

Before the application terminates, dynamic control bars should be serialized to the registry, file or some other data source and the CMainFrame::DestroyWindow() method is a good place for this:

VERIFY(
    CExtDynamicBarSite::StateSave(
        pApp->m_pszRegistryKey,
        pApp->m_pszProfileName,
        pApp->m_pszProfileName
        )
);