Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » CExtControlBar/CExtDynamicControlBar Close Button Collapse All
Subject Author Date
Michael Morrison Sep 16, 2005 - 9:34 AM

I would like to turn the "Hide" [X] button in my CExtControlBars/CExtDynamicControlBars into a real "Close" button.  There have been several previous discussions on this in this forum, and I want to verify that the following steps are what is required to do this:


1) Derive a class from <!--StartFragment -->CExtBarNcAreaButtonClose to override the OnNcAreaClicked method.


2) Derive a class from CExtControlBar to override the OnNcAreaButtonsReinitialize method.  Insert my derived "Close" class instead of CExtBarNcAreaButtonClose.


3) Possibly override the OnDbsCreateTabbedBarInstance in my main frame in order to return one of my derived classes instead of the control bar class it returns:

CExtDynamicTabbedControlBar *
CMainFrame::OnDbsCreateTabbedBarInstance() const
{
   ASSERT( this != NULL );
   CExtDynamicTabbedControlBar * pBar =
      new C_YOUR_DynamicTabbedControlBar;
   return pBar;
}

4) Add this method to my main frame class:


<!--StartFragment -->

#include "AfxPriv.h"
#include "../Src/ExtDockBar.h"
#include "../Src/ExtControlBarTabbedFeatures.h"
 
. . .
 
void CMainFrame::_RemovePanel(
    CExtControlBar * pBar
    )
{
CMiniDockFrameWnd * pMiniFrame = NULL;
    if( pBar->IsFloating() )
    {
        pMiniFrame =
            DYNAMIC_DOWNCAST(
                CMiniDockFrameWnd,
                pBar->GetDockingFrame()
                );
        ASSERT_VALID( pMiniFrame );
    }
    else
    {
        ASSERT( ! pBar->m_pDockBar->m_bFloating );
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
        if( pBar->AutoHideModeGet() )
        {
            ASSERT_KINDOF(
                CExtDockBar,
                pBar->m_pDockBar
                );
            CExtDynAutoHideArea * pWndAutoHideArea =
                ((CExtDockBar*)pBar->m_pDockBar)->
                    _GetAutoHideArea();
            ASSERT_VALID( pWndAutoHideArea );
            CExtDynAutoHideSlider * pWndSlider =
                pWndAutoHideArea->GetAutoHideSlider();
            ASSERT_VALID( pWndSlider );
            if( (pWndSlider->GetStyle()&WS_VISIBLE) != 0 )
                pWndSlider->SendMessage( WM_CANCELMODE );
            pWndAutoHideArea->
                RemoveControlBar( pBar, true );
        }
#endif
        if(    pBar->m_pDockBar->
                IsKindOf(
                    RUNTIME_CLASS( CExtDockBar )
                    )
                )
        {
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
            if(    pBar->m_pDockBar->
                    IsKindOf(
                        RUNTIME_CLASS(
                            CExtDockDynTabBar
                            )
                        )
                    )
            {
                CExtDynTabControlBar * pDynTabbedBar =
                    STATIC_DOWNCAST(
                        CExtDynTabControlBar,
                        pBar->m_pDockBar->GetParent()
                        );
                LONG nIdx =
                    pDynTabbedBar->FindControlBar( pBar );
                if( nIdx >= 0 )
                {
                    LONG nSel =
                        pDynTabbedBar->
                            GetSwitcherSelection();
                    if( nIdx != nSel )
                        pDynTabbedBar->
                            SetSwitcherSelection( nIdx );
                    pDynTabbedBar->RemoveSelFromSwitcher();
                    if( pDynTabbedBar->
                            GetSwitcherItemCount() > 0
                        )
                        pDynTabbedBar->
                            SetSwitcherSelection(0);
                    pDynTabbedBar->
                        OnNcAreaButtonsReinitialize();
                }
            }
#endif
            VERIFY(
                ((CExtDockBar *)pBar->m_pDockBar)->
                    RemoveControlBar( pBar, -1, 0, false )
                );
        }
        else
        {
            VERIFY(
                pBar->m_pDockBar->RemoveControlBar(pBar)
                );
        }
    } // else from if( pBar->IsFloating() )
    RemoveControlBar( pBar );
    pBar->m_pDockSite = NULL;
    pBar->m_pDockBar = NULL;
    if( pMiniFrame != NULL )
        pMiniFrame->DestroyWindow();
    else
        pBar->DestroyWindow();
    CExtDockBar::_OptimizeCircles( this);
    RecalcLayout();
}

5) Inside my CExtBarNcAreaButtonClose::OnButtonClose method, if CExtBarNcAreaButtonClose::OnButtonClose() returns true, call CMainFrame::_RemoveBar() on the button’s parent.


This seems like a lot of work, is there an easier way?


Thanks.

Michael Morrison Sep 19, 2005 - 12:02 PM

Thanks for the clarifications.

Since we use both CExtDynamicControlBars and CExtControlBars, can I call CExtDynamicBarSite::BarFree() on my CExtControlBar (not CExtDynamicControlBar) - derived class? Should I use CExtDynamicBarNcAreaButtonClose in my CExtControlBar-derived classes too?

Also, what exactly should happen inside my XXX::OnButtonClose() method? Can I just call CExtDynamicBarSite::BarFree() on the button’s parent and everything will work out correctly (ie: window is closed and removed from popup menus, MFC stuff like DestroyWindow is called on child window, etc)? Can you post what the "right way" to handle this is?

Would it be possible to add a method to the CExt(Dynamic)ControlBar class to set whether the [X] button is Hide or Close? It seems this would simplify things and not require so much subclassing. Just a thought.

Thanks.

Technical Support Sep 20, 2005 - 7:58 AM

The CExtDynamicBarSite is the management system for dynamic resizable control bars (the CExtDynamicControlBar class). So, if you decide to use dynamic bars, then we recommend you forget about the CExtControlBar class and follow our recommendations described the previous answer.

By default, the X button simply hides the bar. But, as we said, you can make it destroy the bar. The dynamic bars must be destroyed by invoking the CExtDynamicBarSite::BarFree() method. Besides, we must note that after destroying a bar, its location information is lost. So, you should carefully think about whether you really need to destroy your dynamic bars or just to hide them.

Technical Support Sep 19, 2005 - 3:13 AM

Here are some comments about the steps you provided:

1) The CExtControlBar class uses CExtBarNcAreaButtonClose as its X button implementation. The CExtDynamicControlBar class uses the CExtDynamicBarNcAreaButtonClose class instead. We recommend you use CExtDynamicBarNcAreaButtonClose as a base class for implementing your X button.
2) CExtControlBar is a simple resizable control bar which exists persistently as long as its frame window does and does not relate to the subsystem that manages dynamic control bars. So, create the CExtDynamicControlBar-derived class, override the OnNcAreaButtonsReinitialize() method in it and instantiate the CExtDynamicBarNcAreaButtonClose-derived object. Please note that the implementation of your dynamic control bar must include DECLARE_SERIAL / IMPLEMENT_SERIAL MFC features absolutely like in the CExtDynamicControlBar class.
3) Suppose your tabbed bar container is correct. Please ensure it is derived from the CExtDynamicTabbedControlBar class (not from CExtDynTabControlBar) and its OnNcAreaButtonsReinitialize() virtual method creates only CExtDynamicBarNcArea***-derived classes as caption buttons.
4) Looks correct but the CExtDynamicBarSite::BarFree() method in the Prof-UIS 2.40 performs the same work.
5) As we said above, CExtDynamicBarSite::BarFree() is better and allow you avoid dependencies on Prof-UIS versions.

Finally, we are very impressed and appreciate your interest in dynamic control bars. Please do not hesitate to contact us if you encounter any difficulties. Of course, we could code a simplier API for resizable control bars, but the current API would have lost its flexibility and extensibility.