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 » Wrong realization of CExtDynamicBarSite::BarFreeAll() Collapse All
Subject Author Date
Gevork Odabashyan Oct 4, 2006 - 11:01 AM

Hellow

Imagine we have a dynamic control bar in floating state. When we call CExtDynamicBarSite::BarFreeAll(), destructor of control bar is called at first and then destructor of the dockBar is called. As you know, the code of MFC’s CDockBar is as follows:

CDockBar::~CDockBar()
{
    for (int i = 0; i < m_arrBars.GetSize(); i++)
    {
        CControlBar* pBar = GetDockedControlBar(i);
        if (pBar != NULL && pBar->m_pDockBar == this)
            pBar->m_pDockBar = NULL;
    }
}

So we use bad pointers in this case. I think it’s a bug. Test sample doesn’t crash at this point, but my application does it from time to time with access violation.

If you need to illustrate calls order, please do these steps in attatched sample:
1. Set breakpoints in ~CExtControlBar() and ~CDockBar().
2. Open new dynamic bar ("Create dynamic bar\Bar 1")
3. Switch UI profile to Profile 2 ("Switch Profile\To Profile 2"). This will cause the CExtDynamicBarSite::BarFreeAll() call.
The sapmple dynamic_bar_sample2.rar was sent to support@prof-uis.com

Technical Support Oct 5, 2006 - 7:20 AM

Thank you for reporting the bug. Please update the source code for the CExtDynamicBarSite::_BarFreeImpl() method in the ExtControlBar.cpp file to fix the bug:

void CExtDynamicBarSite::_BarFreeImpl(
    CExtDynamicControlBar * pBar,
    bool bForceFloatMode,
    bool bForceNoOptimizeMode
    )
{
    ASSERT( this != NULL );
    ASSERT_VALID( pBar );
UINT nCmdID = (UINT)pBar->GetDlgCtrlID();
bool bPersistentBar = pBar->IsPersistentBar();
    if( pBar->m_pDockSite != NULL && pBar->m_pDockBar != NULL )
    {
        ASSERT_VALID( pBar->m_pDockSite );
        ASSERT_VALID( pBar->m_pDockBar );
        HWND hWndChild = pBar->OnQueryChildHWND();
        if( hWndChild != NULL && ::IsWindow( hWndChild ) )
        {
            HWND hWndContainer = ::GetParent( hWndChild );
            if( hWndContainer != pBar->m_hWnd )
            {
                CWnd * pWndPermanent =
                    CWnd::FromHandlePermanent( hWndContainer );
                if( pWndPermanent != NULL )
                {
                    CExtDynamicBarSite::eDetectedUiType_t eDUIT =
                        GetDetectedUiType();
                    if(     eDUIT == __EDUIT_MDI_ORDINARY
                        ||  eDUIT == __EDUIT_MDI_WITH_TABS
                        )
                    { // if MDI environment
                        CExtDynamicMDIChildWnd * pWndMdiChild =
                            DYNAMIC_DOWNCAST(
                                CExtDynamicMDIChildWnd,
                                pWndPermanent
                                );
                        if( pWndMdiChild != NULL )
                        {
                            pWndMdiChild->DestroyWindow();
                        } // if( pWndMdiChild != NULL )
                    } // if MDI environment
#if (!defined __EXT_MFC_NO_TAB_PAGECONTAINER_CTRL)
                    else if( eDUIT == __EDUIT_SDI_TAB_PAGE_CONTAINER )
                    { // if SDI tab page container environment
                        CExtTabPageContainerWnd * pWndTabPageContainer =
                            DYNAMIC_DOWNCAST(
                                CExtTabPageContainerWnd,
                                pWndPermanent
                                );
                        if( pWndTabPageContainer != NULL )
                        {
                            int nPageCount =
                                pWndTabPageContainer->PageGetCount();
                            for( int nPageIdx = 0; nPageIdx < nPageCount; nPageIdx++ )
                            {
                                HWND hWnd =
                                    pWndTabPageContainer->PageHwndGetSafe(
                                        nPageIdx
                                        );
                                if( hWnd == hWndChild )
                                {
                                    pWndTabPageContainer->
                                        PageRemove( nPageIdx, 1, true );
                                    break;
                                } // if( hWnd == hWndChild )
                            } // for( int nPageIdx = 0; nPageIdx < nPageCount; nPageIdx++ )
                        } // if( pWndTabPageContainer != NULL )
                    } // if SDI tab page container environment
#endif // (!defined __EXT_MFC_NO_TAB_PAGECONTAINER_CTRL)
                } // if( pWndPermanent != NULL )
            } // if( hWndContainer != pBar->m_hWnd )
        } // if( hWndChild != NULL && ::IsWindow( hWndChild ) )
    } // if( pBar->m_pDockSite != NULL && pBar->m_pDockBar != NULL )
    if(       pBar->m_pDockBar == NULL
        ||    bForceFloatMode
        )
    {
        CWnd * pWnd = NULL;
        if( ! m_mapBars.Lookup( pBar, pWnd ) )
            return;
        m_mapBars.RemoveKey( pBar );
        if( pBar->m_pDockBar != NULL )
        {
            CMiniDockFrameWnd * pMiniFrame = NULL;
            CWnd * pWnd = pBar->GetParentFrame();
            if( pWnd != NULL )
            {
                pMiniFrame = 
                    DYNAMIC_DOWNCAST(
                        CMiniDockFrameWnd,
                        pBar->GetDockingFrame()
                        );
            }
            int nPos = pBar->m_pDockBar->FindBar( pBar );
            if( nPos > 0 )
                pBar->m_pDockBar->m_arrBars.RemoveAt( nPos );
            CFrameWnd * pDockSite = DockSiteGet();
            if( pDockSite->GetSafeHwnd() != NULL )
                pDockSite->RemoveControlBar( pBar );
            pBar->m_pDockSite = NULL;
            pBar->m_pDockBar = NULL;
            if( pMiniFrame != NULL )
                pMiniFrame->DestroyWindow();
            else
                pBar->DestroyWindow();
        } // if( pBar->m_pDockBar != NULL )
        return;
    }
    ASSERT_VALID( pBar->m_pDockBar );
CFrameWnd * pDockSite = DockSiteGet();
    if( pDockSite->GetSafeHwnd() == NULL )
        return;
    ASSERT_VALID( pDockSite );
    ASSERT( pBar->m_pDockSite == pDockSite );
    ASSERT(
           pDockSite->GetSafeHwnd() != NULL
        && ::IsWindow( pDockSite->GetSafeHwnd() )
        );
CWnd * pWnd = NULL;
    if( ! m_mapBars.Lookup( pBar, pWnd ) )
        return;
CMiniDockFrameWnd * pMiniFrame = NULL;
    if( pBar->IsFloating() )
    {
        pMiniFrame = 
            DYNAMIC_DOWNCAST(
                CMiniDockFrameWnd,
                pBar->GetDockingFrame()
                );
        ASSERT_VALID( pMiniFrame );
    } // if( pBar->IsFloating() )
    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 );
        } // if( pBar->AutoHideModeGet() )
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
        if( pBar->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
        {
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
            if( pBar->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockDynTabBar)) )
            {
                CExtDynTabControlBar * pTabbedBar =
                    STATIC_DOWNCAST(
                        CExtDynTabControlBar,
                        pBar->m_pDockBar->GetParent()
                        );
                LONG nIdx = pTabbedBar->FindControlBar( pBar );
                if( nIdx >= 0 )
                {
                    LONG nSel = pTabbedBar->GetSwitcherSelection();
                    if( nIdx != nSel )
                        pTabbedBar->SetSwitcherSelection( nIdx );
                    pTabbedBar->RemoveSelFromSwitcher();
                } // if( nIdx >= 0 )
            } // if( pBar->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockDynTabBar)) )
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
            VERIFY(
                ((CExtDockBar *)pBar->m_pDockBar)->
                    RemoveControlBar( pBar, -1, 0, false )
                );
        }
        else
        {
            VERIFY( pBar->m_pDockBar->RemoveControlBar(pBar) );
        }
    } // else from if( pBar->IsFloating() )
    pDockSite->RemoveControlBar( pBar );
    pBar->m_pDockSite = NULL;
INT nPosInDockBar = pBar->m_pDockBar->FindBar( pBar );
    if( nPosInDockBar >= 0 )
    {
        pBar->m_pDockBar->m_arrBars.RemoveAt( nPosInDockBar );
        if(    nPosInDockBar > 1
            && pBar->m_pDockBar->m_arrBars[ nPosInDockBar - 1 ] == m_pDockSite
            )
            pBar->m_pDockBar->m_arrBars.RemoveAt( nPosInDockBar - 1 );
    }
    pBar->m_pDockBar = NULL;
    m_mapBars.RemoveKey( pBar );
    if( ! bPersistentBar )
        OnDbsFreeBarCommandID( nCmdID );
    if( pMiniFrame != NULL )
        pMiniFrame->DestroyWindow();
    else
        pBar->DestroyWindow();
    if( ! bForceNoOptimizeMode )
        CExtDockBar::_OptimizeCircles( pDockSite );
}