dcsimg

Switching Toolbars in MDI

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


The following method displays specific toolbar for each MDI child window CView type, identified by an ID related to that doc/view, while the mainframe toolbar is always displayed.

The idea is to retrieve the toolbar ID from the view class. This is done by identifying the active MDI child, retrieving its document class, and from that document class retrieving the template class which holds the ID. This is done each time a new window is set, by detecting WM_MDISETMENU message in the client window (CMainClient).

The main frame window holds two additional arrays: one of the toolbar pointers and one of the IDs of the already loaded toolbar. When a new menu is set, the main frame searches for the toolbar ID loaded IDs array. If found, the toolbar from the loaded toolbar array, from index if the required ID, is displayed. Otherwise, a new toolbar created, and the toolbar pointer and the ID are stored in the appropriate arrays and that toolbar is displayed.

This code was developed and tested using VC6.0 on NT 4.

The following 3 pictures show the demo application with toolbar 1 (figure 1), toolbar 2 (figure 1) and without toolbar (figure 3). The differences are in the buttons background


Figure 1: Mainframe toolbar and Tolbar 1 are shown.


Figure 2: Mainframe toolbar and Tolbar 2 are shown.


Figure 3: Only mainframe toolbar is shown.

Integration

In order to integrate this method into your code you should do the following:

  • Create a toolbar for each one of your doc/view classes. Give that toolbar the same ID as the menu ID that assigned for that doc/view.
  • Create a new class, say CMainClient, derived from CWnd (generic CWnd), to be used as the MDI client
  • Add the following two handlers to your MDI client class (CMainClient):
  • 
    LRESULT CMainClient::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    { 
    /***************************************************************\ 
    | This function calls the main frame window to switch toolbars  | 
    | when a new MDI menu is set.                                   | 
    \***************************************************************/ 
        LRESULT lRet = CWnd::DefWindowProc(message, wParam, lParam); 
        if (message == WM_MDISETMENU) { 
            CMainFrame *pFrame; 
    
            pFrame = (CMainFrame *) AfxGetMainWnd (); 
            if (::IsWindow (pFrame)) 
                pFrame->SwitchToolbar (); 
        } 
        return (lRet); 
    } 
    
    void CMainClient::OnParentNotify(UINT message, LPARAM lParam) 
    { 
    /***************************************************************\ 
    | This function calls the main frame window to switch toolbars  | 
    | when a all the MDI child windows are closed.                  | 
    \***************************************************************/ 
        CWnd::OnParentNotify(message, lParam); 
        CMainFrame *pFrame; 
        CWnd *pWnd; 
    
        pWnd = AfxGetMainWnd (); 
        if (pWnd->IsKindOf (RUNTIME_CLASS (CMainFrame))) 
            pFrame = (CMainFrame *) AfxGetMainWnd (); 
        else 
            return; // don't crash the application, just leave 
        switch (LOWORD (message)) { 
            case WM_CREATE: 
                m_nChilds++; 
                break; 
            case WM_DESTROY: 
                m_nChilds--; 
                if (m_nChilds == 0) 
                    pFrame->SwitchToolbar (); 
                break; 
            default: 
                break; 
        } 
    } 
    
    
  • Create a new class, say CDocTemplateEx, derived from CDocTemplate. Add the following public method to this class:
  • 
    int CDocTemplateEx::GetResourceID () 
    { 
        return (m_nIDResource); 
    } 
    
    
  • Add the following member variables to CMainFrame class:
  • 
    CArray m_aToolbars; 
    CArray m_idrLoaded; 
    CMainClient m_wndClient; 
    
    
  • Add the following line in CMainFrame::OnCreate function, immediately after the call to CMDIFrameWnd::OnCreate:
  • 
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    { 
         if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) 
            return -1; 
      
     m_wndClient.SubclassWindow (m_hWndMDIClient); // this is what YOU add 
    ... 
    } 
    
    
  • Add the following method to CMainFrame class:
  • 
    #include "DocTemplateEx.h" 
    
    void CMainFrame::SwitchToolbar () 
    { 
    /***************************************************************\ 
    | This function retrive the resource ID from the current view.  | 
    | Then it calls 'SetToolbar' to activate the specified toolbar  | 
    | and to disactivets all the others.                            | 
    | If no view is open the resource ID, 'idResource', is set to 0 | 
    | and all toolbars are disactivated.                            | 
    | External functions used:                                      | 
    | IsWindow (CWnd *pWnd)                                         | 
    \***************************************************************/ 
    
        CView *pView; 
        CDocTemplateEx *pTmpl; 
        CMDIChildWnd *pKid; 
        int idResource = 0; // initialize incase no resource is found 
    
        pKid = MDIGetActive (); 
        if (::IsWindow (pKid)) { 
            pView = pKid->GetActiveView (); 
            if (::IsWindow (pView)) { 
                pTmpl = (CDocTemplateEx *) pView->GetDocument ()->GetDocTemplate (); 
                idResource = pTmpl->GetResourceID (); 
            } 
        } 
        SetToolbar (idResource); 
    } 
    
    void CMainFrame::SetToolbar (int nIdr) 
    /***************************************************************\ 
    | This function gets the toolbar index to the toolbars array,   | 
    | 'm_vToolbars'. The it loops over all the toolbars. If the     | 
    | toolbar the one to be displayed it is closed.                 | 
    | External functions used:                                      | 
    | ShowControlBar                                                | 
    | RecalcLayout                                                  | 
    \***************************************************************/ 
    { 
        static int nToolbars; 
        int n, nIdx; 
        CString str; 
        CToolBar *pTB; 
    
        str.Format ("Toolbar #%d", ++nToolbars); 
        nIdx = AddToolbar (nIdr, str); 
        for (n=0 ; n < m_vToolbars.GetSize () ; n++) { 
            pTB = m_vToolbars.GetAt (n); 
            if (n != nIdx) { 
                ShowControlBar (pTB, 0, 0); 
            } 
            else 
                ShowControlBar (pTB, 1, 1); 
        } 
        m_wndToolBar.GetParentFrame()->RecalcLayout(); 
    } 
    
    int CMainFrame::AddToolbar (int nIDR, CString strWndTxt) 
    /***************************************************************\ 
    | This function returns the index of the toolbar, that have the | 
    | ID of 'nIDR', in the toolbar array, 'm_vToolbars'.            | 
    | If the ID does not exist in the loaded ID array, 'm_idrLoaded'| 
    | the function creates a new toolbar, ads the toolbar pointer   | 
    | to the toolbar array and the ID to the loaded toolbar IDs     | 
    | array.                                                        | 
    | The function also docks the toolbar left to the mainframe     | 
    | toolbar.                                                      | 
    | External functions used:                                      | 
    | ShowControlBar                                                | 
    | FindInArray                                                   | 
    \***************************************************************/ 
    { 
        CToolBar *pTB; 
        BOOL f; 
        CRect rc; 
        int nIdx; 
    
        if (nIDR == 0) 
            return (-1); 
        if ((nIdx = ::FindInArray (m_idrLoaded, nIDR)) < 0) { 
            pTB = new CToolBar; 
            pTB->Create (this); 
            f = pTB->LoadToolBar (nIDR); 
            if (f == 0) { 
                pTB->DestroyWindow (); 
                delete pTB; 
                return (-1); 
            } 
            pTB->SetBarStyle(m_wndToolBar.GetBarStyle() | 
                                CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); 
            pTB->EnableDocking(CBRS_ALIGN_TOP); 
            m_wndToolBar.GetWindowRect (&rc); 
            rc.OffsetRect(1,0); 
            DockControlBar(pTB, AFX_IDW_DOCKBAR_TOP, &rc); 
            pTB->SetWindowText (strWndTxt); 
            pTB->ShowWindow (SW_RESTORE); 
            ShowControlBar (pTB, 1, 1); 
            nIdx = m_vToolbars.Add (pTB); 
            m_idrLoaded.Add (nIDR); 
        } 
        return (nIdx); 
    } 
    
    

I hope someone out there find this helpful. I'll be thankful for any comment and/or correction.

Download demo project - 47 KB



Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date