|
|
|
|
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.
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 );
}
|
|