Unfortunately, there is no such algorithm in Prof-UIS 2.88. But it will appear in the next release so you can use and test it right now. Please add the following static method into the CExtControlBar
class:
static void stat_CompressFrameLayout(
CFrameWnd * pDockSite,
CSize sizeFreeSpaceAtCenterRequired = CSize(100,100),
bool bCompressInnerFirst = true,
bool bCompressProportionally = false,
bool bRecalcLayout = true,
bool bDelayRecalcLayout = true,
UINT nCenterDlgCtrlID = AFX_IDW_PANE_FIRST
);
void CExtControlBar::stat_CompressFrameLayout(
CFrameWnd * pDockSite,
CSize sizeFreeSpaceAtCenterRequired, // = CSize(100,100)
bool bCompressInnerFirst, // = true
bool bCompressProportionally, // = false
bool bRecalcLayout, // = true
bool bDelayRecalcLayout, // = true
UINT nCenterDlgCtrlID // = AFX_IDW_PANE_FIRST
)
{
if( sizeFreeSpaceAtCenterRequired.cx < 0
|| sizeFreeSpaceAtCenterRequired.cy < 0
|| pDockSite->GetSafeHwnd() == NULL
|| pDockSite->IsKindOf( RUNTIME_CLASS(CMiniDockFrameWnd) )
)
{ // incorrect parameter(s)
ASSERT( FALSE );
return;
} // incorrect parameter(s)
ASSERT_VALID( pDockSite );
CRect rcFrameInner;
pDockSite->GetClientRect( &rcFrameInner );
RepositionBarsEx(
pDockSite,
0,
0x0FFFF,
nCenterDlgCtrlID,
CWnd::reposQuery,
rcFrameInner,
rcFrameInner
);
bool bLayoutChanged = false;
CSize sizeFreeSpaceAtCenterCurrent = rcFrameInner.Size();
for( int nSpaceType = 0; nSpaceType <= 1; nSpaceType ++ )
{ // nSpaceType==0 - horizontal space search, nSpaceType==1 - vertical space search
bool bHorzSpaceSearch = ( nSpaceType == 0 ) ? true : false;
LONG nSizeRequired = bHorzSpaceSearch ? sizeFreeSpaceAtCenterRequired.cx : sizeFreeSpaceAtCenterRequired.cy;
LONG nSizeCurrent = bHorzSpaceSearch ? sizeFreeSpaceAtCenterCurrent.cx : sizeFreeSpaceAtCenterCurrent.cy;
if( nSizeRequired <= nSizeCurrent )
continue;
LONG nSizeAvailable = 0;
UINT nDockBarID1 = bHorzSpaceSearch ? AFX_IDW_DOCKBAR_LEFT : AFX_IDW_DOCKBAR_TOP;
UINT nDockBarID2 = bHorzSpaceSearch ? AFX_IDW_DOCKBAR_RIGHT : AFX_IDW_DOCKBAR_BOTTOM;
CList < CExtDockBar *, CExtDockBar * > listDockBars;
CList < LONG, LONG > listAvailableSizes;
CWnd * pWnd = pDockSite->GetWindow( GW_CHILD );
for( ; pWnd != NULL; pWnd = pWnd->GetWindow( GW_HWNDNEXT ) )
{
CExtDockBar * pDockBar = DYNAMIC_DOWNCAST( CExtDockBar, pWnd );
if( pDockBar == NULL || pDockBar->IsKindOf( RUNTIME_CLASS(CExtDockOuterBar) ) )
continue;
UINT nDockBarID = pDockBar->GetDlgCtrlID();
if( ! ( nDockBarID == nDockBarID1 || nDockBarID == nDockBarID2 ) )
continue;
if( ( pDockBar->GetStyle() & WS_VISIBLE ) == 0 )
continue;
CRect rcDockBarWnd;
pDockBar->GetWindowRect( &rcDockBarWnd );
LONG nDockBarMinSize = 0, nDockBarCurrentSize = bHorzSpaceSearch ? rcDockBarWnd.Width() : rcDockBarWnd.Height();
CWnd * pTestBar = pDockBar->GetWindow( GW_CHILD );
for( ; pTestBar != NULL; pTestBar = pTestBar->GetWindow( GW_HWNDNEXT ) )
{
CExtControlBar * pBar = DYNAMIC_DOWNCAST( CExtControlBar, pTestBar );
if( pBar == NULL )
continue;
if( ! pBar->IsVisible() )
continue;
LONG nBarMinSize = bHorzSpaceSearch ? pBar->_CalcDesiredMinHW() : pBar->_CalcDesiredMinVH();
nDockBarMinSize = max( nDockBarMinSize, nBarMinSize );
} // for( ; pTestBar != NULL; pTestBar = pTestBar->GetWindow( GW_HWNDNEXT ) )
LONG nDockBarAvailableSize = nDockBarCurrentSize - nDockBarMinSize;
if( nDockBarAvailableSize <= 0 )
continue;
nSizeAvailable += nDockBarAvailableSize;
if( bCompressInnerFirst )
{
listDockBars.AddHead( pDockBar );
listAvailableSizes.AddHead( nDockBarAvailableSize );
}
else
{
listDockBars.AddTail( pDockBar );
listAvailableSizes.AddTail( nDockBarAvailableSize );
}
} // for( ; pWnd != NULL; pWnd = pWnd->GetWindow( GW_HWNDNEXT ) )
LONG nSizeToCompress = min( nSizeAvailable, nSizeRequired );
if( nSizeToCompress <= 0 )
continue;
bLayoutChanged = true;
ASSERT( listDockBars.GetCount() == listAvailableSizes.GetCount() );
CMap < CExtDockBar *, CExtDockBar *, LONG, LONG > mapSizesToCompress;
for( ; nSizeToCompress > 0; )
{
POSITION posDockBar = listDockBars.GetHeadPosition();
POSITION posAvailableSize = listAvailableSizes.GetHeadPosition();
LONG nStepResult = 0;
for( ; posDockBar != NULL && nSizeToCompress > 0; )
{
CExtDockBar * pDockBar = listDockBars.GetNext( posDockBar );
LONG nDockBarSizeCompressed = 0, nDockBarAvailableSize = listAvailableSizes.GetNext( posAvailableSize );
if( ! mapSizesToCompress.Lookup( pDockBar, nDockBarSizeCompressed ) )
nDockBarSizeCompressed = 0;
nDockBarAvailableSize -= nDockBarSizeCompressed;
ASSERT( nDockBarAvailableSize >= 0 );
if( nDockBarAvailableSize == 0 )
continue;
if( bCompressProportionally )
{
nDockBarSizeCompressed ++;
nSizeToCompress --;
nStepResult ++;
}
else
{
LONG nCompress = min( nDockBarAvailableSize, nSizeToCompress );
nDockBarSizeCompressed += nCompress;
nSizeToCompress -= nCompress;
nStepResult += nCompress;
}
mapSizesToCompress.SetAt( pDockBar, nDockBarSizeCompressed );
ASSERT( nSizeToCompress >= 0 );
} // for( ; posDockBar != NULL && nSizeToCompress > 0; )
ASSERT( nStepResult >= 0 );
if( nStepResult == 0 )
break;
} // for( ; nSizeToCompress > 0; )
POSITION pos = mapSizesToCompress.GetStartPosition();
for( ; pos != NULL ; )
{
CExtDockBar * pDockBar = NULL;
LONG nDockBarSizeCompressed = 0;
mapSizesToCompress.GetNextAssoc( pos, pDockBar, nDockBarSizeCompressed );
CWnd * pTestBar = pDockBar->GetWindow( GW_CHILD );
for( ; pTestBar != NULL; pTestBar = pTestBar->GetWindow( GW_HWNDNEXT ) )
{
CExtControlBar * pBar = DYNAMIC_DOWNCAST( CExtControlBar, pTestBar );
if( pBar == NULL )
continue;
//if( ! pBar->IsVisible() )
// continue;
CRect rcBarWnd;
pBar->GetWindowRect( &rcBarWnd );
CSize sizeBar = rcBarWnd.Size();
if( bHorzSpaceSearch )
{
sizeBar.cx -= nDockBarSizeCompressed;
pBar->SetInitDesiredSizeVertical( sizeBar );
}
else
{
sizeBar.cy -= nDockBarSizeCompressed;
pBar->SetInitDesiredSizeHorizontal( sizeBar );
}
} // for( ; pTestBar != NULL; pTestBar = pTestBar->GetWindow( GW_HWNDNEXT ) )
} // for( ; pos != NULL ; )
} // nSpaceType==0 - horizontal space search, nSpaceType==1 - vertical space search
if( ! bLayoutChanged )
return;
if( bRecalcLayout )
pDockSite->RecalcLayout();
else if( bDelayRecalcLayout )
pDockSite->DelayRecalcLayout();
}
We used the
MDI sample application to test the method above. We added the following code into this sample application:
LRESULT CMainFrame::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
LRESULT lResult = CExtNCW < CMDIFrameWnd > :: WindowProc( message, wParam, lParam );
switch( message )
{
case WM_SIZE:
if( wParam != SIZE_MINIMIZED )
CExtControlBar::stat_CompressFrameLayout( this );
break;
}
return lResult;
}