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 General Discussion » CExtDynamicBarSite::BarFreeAll() Bug Collapse All
Subject Author Date
Andrew Harding May 31, 2006 - 11:52 AM

If you save the window state with all windows docked and then after saving the state you drag one of the windows off the docking site so that it’s floating and then you call CExtDynamicBarSite::BarFreeAll ( ) you’ll ASSERT every time.

This bug is wreaking havoc with my save / restore layout menu items in my application. Is it possible to get this fixed in the next release?

Andrew Harding May 31, 2006 - 3:16 PM

I forgot to mention that I’m using Prof-UIS 2.42 though I have tried downloading 2.54 and it still happens there as well. After stepping through the code it looks like the problem is somewhere in CExtDynamicBarSite::_BarFreeImpl ( ). In a couple of places in that function the code checks to see if the bar is floating or not but the way in which they check to see if the bar is floating is erroneous. It works fine if the user specifically changed the bar to "floating" via the right click title menu but if the user just drags the window off the docksite it fails the floating checks and the docking checks. Windows that are dragged off have an edbs state of __EDBS_DOCKED and their m_pDockBar->m_bFloating member is true.

I’m not really sure what the code needs to be changed to in order to fix this bug, I can only tell you that the floating / docking checks performed in this function are wrong.

Technical Support Jun 1, 2006 - 3:11 AM

We cannot yet confirm that are some errors in the bar destruction code and we did not receive reports about similar problems. Is it possible to get some test project which reproduces the same assertion failures?

Andrew Harding Jun 7, 2006 - 10:11 AM

Here’s some sample code derived from our code, to reproduce the problem simply call SaveWindowState() for the current tab page and then drag window2 or window3 off the CFrameWnd with the mouse so that it’s floating (don’t use the floating menu option) then call LoadWindowState() and the code will blow chunks.

/**
* create the main frame
*/
void CMyMainFrame::OnCreate ( ... )
{
    ...
    
    // create the tab page container
    m_tabPageContainerOneNoteWnd.Create( this, rect, AFX_IDW_PANE_FIRST );
    m_tabPageContainerOneNoteWnd.OrientationSet( __ETWS_ORIENT_TOP );
    m_tabPageContainerOneNoteWnd.FullWidthSet( true );
    m_tabPageContainerOneNoteWnd.ItemDraggingSet ( true );

    // create the tabs
    CMyTabPageFrameWnd    page;
    CString                tabName;
    page = new CMyTabPageFrameWnd();
    tabName = _T("tab1");
    page->Create(this, tabName.GetString());
    m_tabFrame.PageInsert( page, tabName.GetString() );

    page = new CMyTabPageFrameWnd();
    tabName = _T("tab2");
    page->Create(this, tabName.GetString());
    m_tabFrame.PageInsert( page, tabName.GetString() );

    page = new CMyTabPageFrameWnd();
    tabName = _T("tab3");
    page->Create(this, tabName.GetString());
    m_tabFrame.PageInsert( page, tabName.GetString() );
}

/**
* this function gets called whenever a tab is selected, we delay loading the windows each tab contains
* until it becomes selected for the first time to improve initial application load speed.
*/
void CMyTabPageFrameWnd::OnTabFrameSelected ( )
{
    if ( m_bFirstTimeSelected )
    {
        // create the windows and load the docking state from the registry
        LoadWindowState ( );
        m_bFirstTimeSelected = false;
    }
}

/**
* allocate all docking windows and position them according to their previously saved state.
*/
void CMyTabPageFrameWnd::LoadWindowState ( )
{
    CTypedPtrArray<CPtrArray, CExtDynamicControlBar*> aAllControlBars;
    CMyDynamicControlBar    *pBar = NULL;
    CString                    barCaption;
    CExtCmdIcon                icon;
CRect                    rect;
    int                        i, n;

    m_controlBars.clear ( );
    icon.CreateEmptyIcon ( );

    ////////////////////////////////////////
    // Destroy any windows that existed previously
    ////////////////////////////////////////
    FreeWindows ( );

////////////////////////////////////////
    // Create the docking bars
    ////////////////////////////////////////
    if ( !CExtDynamicBarSite::StateLoad(theApp.GetCompanyName(), theApp.GetProductName(), m_szFrameName) )
    {
        aAllControlBars.Add ( CExtDynamicBarSite::BarAlloc ( ResString(IDS_WINDOW1_TITLE).GetString(), icon, 0, RUNTIME_CLASS(CMyDynamicControlBar) ) );
        aAllControlBars.Add ( CExtDynamicBarSite::BarAlloc ( ResString(IDS_WINDOW2_TITLE).GetString(), icon, 0, RUNTIME_CLASS(CMyDynamicControlBar) ) );
        aAllControlBars.Add ( CExtDynamicBarSite::BarAlloc ( ResString(IDS_WINDOW3_TITLE).GetString(), icon, 0, RUNTIME_CLASS(CMyDynamicControlBar) ) );
    }
    else
    {
        CExtDynamicBarSite::BarEnumGetArray( aAllControlBars, true, true );
    }

    ////////////////////////////////////////////
    // Populate the map of resource id’s to control bars
    ////////////////////////////////////////////
    POINT    ptMinSize;
    ptMinSize.x = 75; // minimum docking bar width
    ptMinSize.y = GetSystemMetrics ( SM_CYCAPTION ) * 3; // minimum docking bar height
    n = int(aAllControlBars.GetSize());
    for ( i = 0; i < n; i++ )
    {
        pBar = (CMyDynamicControlBar*)aAllControlBars[i];
        pBar->SetListener ( GetSafeHwnd() ); // set this object as the listener for the bar events
        pBar->SetMinSize ( ptMinSize );
        barCaption = pBar->m_strCaptionText;
        if ( barCaption.Compare ( ResString(IDS_WINDOW1_TITLE) ) == 0 )
            m_controlBars[IDS_WINDOW1_TITLE] = pBar;
        else if ( barCaption.Compare ( ResString(IDS_WINDOW2_TITLE) ) == 0 )
            m_controlBars[IDS_WINDOW2_TITLE] = pBar;
        else if ( barCaption.Compare ( ResString(IDS_WINDOW3_TITLE) ) == 0 )
            m_controlBars[IDS_WINDOW3_TITLE] = pBar;
        else
        {
            TRACE ( "Unhandled control bar, it needs to be added to this map!" );
            ASSERT ( 0 );
        }
    }

////////////////////////////////////////////
    // Create the dialog boxes that go inside of the
    // docking containers
    ////////////////////////////////////////////
    m_dlgWindow1 = new CExtWFF<CDlgWindow1>;
    m_dlgWindow1->Create(CDlgWindow1::IDD, m_controlBars[IDS_WINDOW1_TITLE] );
    m_dlgWindow2 = new CExtWFF<CDlgWindow2>;
    m_dlgWindow2->Create( CDlgWindow2::IDD, m_controlBars[IDS_WINDOW2_TITLE] );
    m_dlgWindow3 = new CExtWFF<CDlgWindow3>;
    m_dlgWindow3->Create(CDlgWindow3::IDD, m_controlBars[IDS_WINDOW3_TITLE]);

    ///////////////////////////////////////////
    // Dock the control bars in their default positions
    ///////////////////////////////////////////
    if ( !CExtControlBar::ProfileBarStateLoad(this, theApp.GetCompanyName(), theApp.GetProductName(), m_szFrameName, NULL) )
    {
        m_controlBars[IDS_WINDOW1_TITLE]->BarStateSet ( CMyDynamicControlBar::__EDBS_DOCUMENT, true );
        m_controlBars[IDS_WINDOW2_TITLE]->BarStateSet ( m_controlBars[IDS_WINDOW2_TITLE]->BarStateGet(), true );
        m_controlBars[IDS_WINDOW2_TITLE]->DockControlBarInnerOuter ( AFX_IDW_DOCKBAR_BOTTOM, false, this, true );
        m_controlBars[IDS_WINDOW3_TITLE]->BarStateSet ( m_controlBars[IDS_WINDOW3_TITLE]->BarStateGet(), true );
        m_controlBars[IDS_WINDOW3_TITLE]->DockControlBarLTRB ( m_controlBars[IDS_WINDOW2_TITLE], AFX_IDW_DOCKBAR_RIGHT, true );
    }
}

/**
* save the current tab layout as it currently appears
* @param    szTabName        name of the tab containing this layout
*/
void CMyTabPageFrameWnd::SaveWindowState ( CString *szTabName )
{
    VERIFY(CExtControlBar::ProfileBarStateSave(this, theApp.GetCompanyName(), theApp.GetProductName(), *szTabName));
    VERIFY(CExtDynamicBarSite::StateSave(theApp.GetCompanyName(), theApp.GetProductName(), *szTabName));
}

/**
* destroy and delete all windows in the current tab
*/
void CMyTabPageFrameWnd::FreeWindows ( )
{
    CExtDynamicBarSite::BarFreeAll ( true, true );

    if ( m_dlgWindow1 )
    {
        m_dlgWindow1->DestroyWindow ( );
        delete m_dlgWindow1;
        m_dlgWindow1 = NULL;
    }
    if ( m_dlgWindow2 )
    {
        m_dlgWindow2->DestroyWindow ( );
        delete m_dlgWindow2;
        m_dlgWindow2 = NULL;
    }
    if ( m_dlgWindow3 )
    {
        m_dlgWindow3->DestroyWindow ( );
        delete m_dlgWindow3;
        m_dlgWindow3 = NULL;
    }
}

Technical Support Jun 7, 2006 - 12:13 PM

We are ready to help you with this, but if you send us some simple test project that shows the problem that would be of great help. If it is not possible, we can connect to your desktop and debug the problem remotely.