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 » Docking Bug with dynamic bars Collapse All
Subject Author Date
Kevin Murray Jul 26, 2010 - 11:43 AM

This is interesting, but I have reproduced it in the MDI_DynamicBars sample.  First, some history.


When we switched from our previous GUI library to Prof-UIS we lost one feature of the docking system.  Namely, when a window was in MDI mode, the old system had on the docking menu an extra popup menu entry labeled "Dock To" with the choices Left, Right, Top, Bottom.  Only available in MDI mode, it allowed the user the ability to redock the window to the side they wanted, not simply back to where it was docked before being made into an MDI window.  I was tasked with adding this functionality into our new Prof-UIS driven docking system.  I did, but it lead to the discovery of a very interesting bug.


Now, to reproduce this is MDI_DynamicBars sample, add the following methods to the CSimpleControlBar class found in MainFrm.h:



 


 


 

LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam ){

 

LRESULT rc = __super::WindowProc( message, wParam, lParam );

 

switch( message )

 

{

 

case WM_COMMAND:

 

{

 

UINT nCmdID = (UINT)wParam;

 

if( (nCmdID >= 4001) && (nCmdID <= 4004) )

 

{

 

DockToSide( nCmdID );

 

}

 

}

 

break;

 

}

 

return rc;

 

}

 

virtual bool OnInitDbsMenu( CExtPopupMenuWnd * pPopup, HWND hWndTrack, CObject * pHelperSrc, LPARAM lParamHelper = 0 )

 

{

 

bool rc = CExtDynamicControlBar::OnInitDbsMenu( pPopup, hWndTrack, pHelperSrc, lParamHelper );

 

if( (rc == true) &&

 

(BarStateGet() == CExtDynamicControlBar::__EDBS_DOCUMENT) )

 

{

 

CExtPopupMenuWnd* pmenu = new CExtPopupMenuWnd();

 

pmenu->CreatePopupMenu( m_hWnd );

 

if( g_CmdManager->CmdIsRegistered( g_CmdManager->ProfileNameFromWnd( m_hWnd ), 4001 ) == false )

 

{

 

CExtCmdItem* pItem;

 

pItem = g_CmdManager->CmdAllocPtr( g_CmdManager->ProfileNameFromWnd( m_hWnd ), 4001 );

 

pItem->m_sMenuText = "Left";

 

pItem->StateEnable();

 

pItem = g_CmdManager->CmdAllocPtr( g_CmdManager->ProfileNameFromWnd( m_hWnd ), 4002 );

 

pItem->m_sMenuText = "Top";

 

pItem->StateEnable();

 

pItem = g_CmdManager->CmdAllocPtr( g_CmdManager->ProfileNameFromWnd( m_hWnd ), 4003 );

 

pItem->m_sMenuText = "Right";

 

pItem->StateEnable();

 

pItem = g_CmdManager->CmdAllocPtr( g_CmdManager->ProfileNameFromWnd( m_hWnd ), 4004 );

 

pItem->m_sMenuText = "Bottom";

 

pItem->StateEnable();

 

}

 

pmenu->ItemInsert( 4001 );

 

pmenu->ItemInsert( 4002 );

 

pmenu->ItemInsert( 4003 );

 

pmenu->ItemInsert( 4004 );

 

pmenu->ItemGetInfo( 0 ).SetNoCmdUI( true );

 

pmenu->ItemGetInfo( 1 ).SetNoCmdUI( true );

 

pmenu->ItemGetInfo( 2 ).SetNoCmdUI( true );

 

pmenu->ItemGetInfo( 3 ).SetNoCmdUI( true );

 

pPopup->ItemInsertSpecPopup( pmenu, -1, "Dock to" );

 

}

 

return rc;

 

}

 

void DockToSide( int nSide )

 

{

 

UINT uiSide = AFX_IDW_DOCKBAR_LEFT;

 

switch( nSide )

 

{

 

case 4001:

 

uiSide = AFX_IDW_DOCKBAR_LEFT;

 

break;

 

case 4002:

 

uiSide = AFX_IDW_DOCKBAR_TOP;

 

break;

 

case 4003:

 

uiSide = AFX_IDW_DOCKBAR_RIGHT;

 

break;

 

case 4004:

 

uiSide = AFX_IDW_DOCKBAR_BOTTOM;

 

break;

 

}

 

OnMoveChildToBar();

 

_AffixmentSafeClearOuter();

 

m_pDockSite->DockControlBar( this, uiSide );

 

m_pDockSite->ShowControlBar( this, TRUE, FALSE );

 

m_pDockSite->RecalcLayout();

 

}

 

 


Now this code doesn’t do a lot of error checking or optimization, but it will serve its purpose of demonstrating the bug.  Run the app and close all dynamic bars (even the auto-hidden persistent bars).  Now, using the menu, open three of the dynamic bars.  Dock them to the left, each one docking under the previous by dragging to the appropriate dock marker on the windows.


Now on the bottom most window, select Tabbed Document from the menu.  It will become an MDI window.  Right click its menu bar and select Dock to and pick Right.  The window will dock to the right, only two issues now exist:


1) It docks on the outer most circle.  Any attempts to dock to an inner circle will result in problem number 2 (below) immediately.


2) If you drag the dynamic bar off the application (or change the DockToSide method to dock to an inner circle), the other two windows still docked on the left stack on top of each other so that only one is visible, and lots of empty space below it.


This seemingly can only be reproduced with three or more windows.  If you attempt to close the application after the aforementioned problem happens, it will ASSERT and crash and such.  I have tried changing to the DockToSide code in various ways with various combinations of dock calls, to no avail.  Is there a way for me to properly implement this feature and avoid the bug?  Is there perhaps a way to change the Prof-UIS library to avoid the bug?


Any help greatly appreciated.


K.



 

Kevin Murray Jul 27, 2010 - 12:24 PM

That doesn’t work.  The problem crops up immediately upon docking the bar to the right side. 


 


K.

Technical Support Jul 28, 2010 - 2:22 AM

Here is the project with your code and our DockToSide() method:
http://www.prof-uis.com/download/forums/tmp/FOR_Kevin_Murray_MDI_DynamicBars.zip
We can invoke the context menu over MDI tab items and dock the bar in the document mode to any side of the main frame window, including right side.
We used Prof-UIS 2.90 and Windows 7 Ultimate x64.

Kevin Murray Jul 28, 2010 - 11:19 AM

I tried your project, and get the same results.  I have emailed two screenshots to support.


The first, DynamicBarIssue_Start.jpg, shows how I stack the bars.  I then make DynamicBar2 into a tabbed document, then DyanamicBarIssue_AfterDocking.jpg shows what happens when I pick "Dock To --> Right" using your version of the code.  This is the same result I saw if I tried moving Bar 2 after docking it.


I should also mention if you exit the application in this sate, so it saves the bar states, then reload, you get an ASSERT on load, which you can ignore, then the app loads with the bars where you would expect them to be.


K.

Kevin Murray Jul 28, 2010 - 11:20 AM

And for what it is worth, I’m on Vista 32-bit.


K.

Technical Support Jul 29, 2010 - 3:53 AM

This is not possible. The CExtControlBar::DockControlBarInnerOuter() always docks one control bar into one new row/column near the outer frame side or into the inner frame side. There are no conflicts with other bars. The new row/column of bars is organized and it contain only one bar. We cannot reproduce the incorrect layout demonstrated on the screen shots you sent us. Please provide us with exact step-by-step description of how to reproduce the incorrect bar layout? We suspect it may depend on the bar states restored at app startup. The bar states can be incorrect on your computer because the previous version of this test app performed incorrect bar redocking.

Kevin Murray Jul 29, 2010 - 10:56 AM

I went through my registry and removed all references to MDI_DynamicBars* to remove the state information (I hope anyway -- it does make it start in the default state).


I start the application.  It comes up maximized with lots of windows open.  I close every Dynamic Bar window via its X button, both docked and in the MDI area, and I close the Persistent bar that is auto-hidden on the left by mousing over it and hitting the X.  I leave the MDIDOC1 window and the toolbars/menubar open.  I use the View menu, go to Dynamic Resizable Bars, and select Dynamic Bar 0.  I drag it from its position to the dock marker at the left of the application.  I then drag the sizing bar to make it wider as it docks far too narrowly.  I go back to View --> Dynamic Resiable bars and pick Dynamic Bar 1.  I drag it over Dynamic Bar 0 and drop it on Bar 0’s bottom dock marker.  I go back to the menu, pick Dynamic Bar 2, drag it tfrom its default location o Dynamic Bar 1’s bottom dock marker.  I then click on the down arrow button on Dynamic Bar 2’s caption bar, and select Tabbed Document from the menu.  It becomes an MDI window.  I then go to Dynamic Bar 2’s title bar, right click, and select Dock to --> Right on the menu.  The result is what I sent in the screen shot.


K.

Technical Support Jul 30, 2010 - 9:14 AM

We reproduced this issue. We have an alpha version of the fix for it. Please drop us an e-mail to the support mail box at this web site so we will provide you with the source code update.

Technical Support Jul 27, 2010 - 10:35 AM

Thank you for the sample code. The problem is hidden in the DockToSide() method. It does not change the state of the dynamic resizable control bar from document to docked mode. It uses CFrameWnd::DockControlBar() method instead of the CExtControlBar::DockControlBarInnerOuter() method. Here is the correct version:

	void DockToSide( int nSide )
	{
		UINT uiSide = AFX_IDW_DOCKBAR_LEFT;
		switch( nSide )
		{
		case 4001: uiSide = AFX_IDW_DOCKBAR_LEFT;	break;
		case 4002: uiSide = AFX_IDW_DOCKBAR_TOP;	break;
		case 4003: uiSide = AFX_IDW_DOCKBAR_RIGHT;	break;
		case 4004: uiSide = AFX_IDW_DOCKBAR_BOTTOM;	break;
		}
		VERIFY( BarStateSet( CExtDynamicControlBar::__EDBS_DOCKED, false ) );
		DelayShow( TRUE );
		DockControlBarInnerOuter( uiSide, true, m_pDockSite );
	}