From c1daa3a71356d74e91452ac440d2e1c8d7fd07e3 Mon Sep 17 00:00:00 2001 From: fcolin Date: Thu, 1 Feb 2007 13:08:26 +0000 Subject: Utilisateur : Fcolin Date : 14/03/00 Heure : 9:26 Créé (vss 1) --- IvyProbe/ETSLayout.cpp | 2873 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2873 insertions(+) create mode 100644 IvyProbe/ETSLayout.cpp (limited to 'IvyProbe') diff --git a/IvyProbe/ETSLayout.cpp b/IvyProbe/ETSLayout.cpp new file mode 100644 index 0000000..fa62a7b --- /dev/null +++ b/IvyProbe/ETSLayout.cpp @@ -0,0 +1,2873 @@ +//////////////////////////////////////////// +// ___ ____ _________________ // +// / _/_ _// _______________/ // +// / _/ / / / / ___ ___ ____ // +// /__/ /_/ / / / // _/_ _/ // +// _________/ / / / // _/ / / // +// __(c) 1998-9_/ /___//_/ /_/ // +// // +//////////////////////////////////////////// +// all rights reserved // +//////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutDialog +// +// A class for smart layouting of Dialogs and such +// +// USAGE: See LayoutMgr.html +// +// AUTHOR: Erwin Tratar +// +// DISCLAIMER: +// +// This Sourcecode and all accompaning material is ©1998-1999 Erwin Tratar. +// All rights reserved. +// +// The source code may be used in compiled form in any way you desire +// (including usage in commercial applications), providing that your +// application adds essential code (i.e. it is not only a wrapper) to the +// functionality found here +// +// Redistribution of the sourcecode itself, publication in any media or +// inclusion in a library requires the authors expressed written consent. +// You may not sale this code for profit. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. USE IT +// AT YOUR OWN RISK! THE AUTHOR ACCEPTS NO LIABILITY FOR ANY DAMAGE/LOSS OF +// BUSINESS THAT THIS PRODUCT MAY CAUSE. +// +// +// HISTORY: +// 1998/05/1 Initial Release +// 1998/05/13 Added ability to have a Pane with a control +// 1998/05/13 Added better support for TabControls +// 1998/05/14 automatically set Icon to IDR_MAINFRAME +// 1998/05/19 no flicker on restoring position in OnInitialUpdate +// Changed procedure for load/save, see constructor +// 1998/10/02 Added support for Maximum (tracking) size +// 1998/10/02 Much improved handling regarding RELATIVE/GREEDY +// /w critical minimum size +// 1998/10/02 turn on/off gripper at lower right corner +// 1998/10/05 Support for user defined minimum size for items +// (was hardcoded 5 before) +// 1998/10/07 Fix for FormViews +// 1998/10/31 Support for SECDialogBar/CDialogBar +// 1998/10/31 simplified interface +// 1998/10/31 Advanced positioning options +// 1998/10/31 Added paneNull for empty Pane (former: NULL) +// 1998/11/20 Swapped ETSLayoutDialog constructor parameters +// 1998/11/20 Added Pane::addItemSpaceBetween +// [Leo Zelevinsky] +// 1998/11/24 Added fixup for greedy panes +// 1998/11/24 addItemSpaceBetween now subtracts 2*nDefaultBorder +// 1998/11/24 addGrowing() added as a shortcut for a paneNull +// 1998/11/24 simplified interface: no more PaneBase:: / Pane:: +// needed +// 1998/11/24 added FILL_* Modes +// 1998/11/24 improved maximum size handling for greedy panes +// 1998/11/25 Fixup of greedy panes caused infinite loop in some +// cases +// 1999/01/07 addItemSpaceLike() added +// 1999/04/03 Fixed ETSLayoutFormView memory leak +// 1999/04/07 Fixed ALIGN_xCENTER +// 1999/04/08 New simple stream-interface added +// 1999/04/09 Added support for an empty Status-Bar for resizing +// instead of a gripper in the lower right corner +// [Andreas Kapust] +// 1999/04/11 New code for much less flickering, OnEraseBkgnd() +// overidden for this task +// 1999/05/12 Split Layout code into understandable pieces and adding +// a lot of comments +// 1999/06/20 ABSOLUTE_X + ALIGN_FILL_X expands item if there is any +// left space (after all Abs/Rel/Greedy processing is done) +// 1999/10/06 Changed Load() and Save() to use WINDOWPLACEMENT +// [Keith Bussell] +// 1999/11/18 Added possibility to add panes of the same orientation +// to another pane. This merges both panes in one big +// pane with the same orientation +// 1999/11/18 Added support for BCGDialogBar (only with BCG > 4.52!) +// 1999/11/25 Addes support for PropertyPages/Sheets. Uses some code +// of a code submission from Anreas Kapust +// 1999/11/25 Renamed classes to ETSLayoutXXX +// 1999/11/25 Use CreateRoot() and Root() instead of m_pRootPane in +// derived class. +// 1999/11/26 Added autopointer support. No need to use normal pointers +// when defining layout anymore. Changed m_pRootPane to +// m_RootPane +// 1999/11/26 Bug in Fixup Greedy II with multiple GREEDY panes and one +// of them min/max limited +// 1999/11/28 Fixed PaneTab::getConstrainVert() for ABSOLUTE_VERT +// 1999/11/28 Fixed itemFixed() +// 1999/11/28 Changed DWORD modeResize Arguments to layModeResize for +// better type safety. Added typesafe operator| +// 1999/12/04 Don't reposition window in UpdateLayout if it's a child +// (as a child Dialog or PropertyPage) +// 1999/12/04 Erase Backgroung with GCL_HBRBACKGROUND (if available) +// 1999/12/04 itemSpaceXXX() adds a NORESIZE item instead of ABSOLUTE_XXX +// this will fix unwanted growing in secondary direction +// 1999/12/10 Erase Backgroung within TabCtrl was 'fixed' badly. Reverted to +// old working code +// 2000/02/02 When the Dialog is child of a View the class works correctly +// now [Didier BULTIAUW] +// 2000/02/15 Combo-Boxes were not working correctly (in all modes!) + + +#define OEMRESOURCE +#include + +#include "stdafx.h" +#include "ETSLayout.h" + +#ifndef OBM_SIZE +#define OBM_SIZE 32766 +// taken from WinresRc.h +// if not used for any reason +#endif + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static UINT auIDStatusBar[] = +{ + ID_SEPARATOR +}; + +const int ERASE_GROUP_BORDER = 10; +const int FIXUP_CUTOFF = 5; +const int TAB_SPACE = 5; + +// the _NULL-Pane +CWnd* ETSLayoutMgr::paneNull = 0; + +void ETSLayoutMgr::Layout(CRect& rcClient) +{ + // Does nothing, use DECLARE_LAYOUT in derived class + // see DialogMgr.h +} + + +ETSLayoutMgr::CPane ETSLayoutMgr::pane( layOrientation orientation, ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, + int sizeBorder /*=nDefaultBorder*/, int sizeExtraBorder /*=0*/, + int sizeSecondary /*=0*/) +{ + Pane* pPane = new Pane ( this, orientation, sizeBorder, sizeExtraBorder ); + pPane->m_sizeSecondary = sizeSecondary; + pPane->m_modeResize = modeResize; + + return CPane(pPane); +} + +ETSLayoutMgr::CPane ETSLayoutMgr::paneTab( CTabCtrl* pTab, layOrientation orientation, + ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, int sizeBorder /*=nDefaultBorder*/, + int sizeExtraBorder /*=0*/, int sizeSecondary /*=0*/) +{ + Pane* pPane = new PaneTab ( pTab, this, orientation, sizeBorder, sizeExtraBorder ); + pPane->m_sizeSecondary = sizeSecondary; + pPane->m_modeResize = modeResize; + + return CPane(pPane); +} + + +ETSLayoutMgr::CPane ETSLayoutMgr::paneCtrl( CWnd* pCtrl, layOrientation orientation, + ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, int sizeBorder /*=nDefaultBorder*/, + int sizeExtraBorder /*=0*/, int sizeTopExtra /*=0*/, + int sizeSecondary /*=0*/) +{ + Pane* pPane = new PaneCtrl ( pCtrl, this, orientation, sizeBorder, sizeExtraBorder, sizeTopExtra ); + pPane->m_sizeSecondary = sizeSecondary; + pPane->m_modeResize = modeResize; + + return CPane(pPane); +} + +ETSLayoutMgr::CPane ETSLayoutMgr::paneCtrl( UINT nID, layOrientation orientation, ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, + int sizeBorder /*=nDefaultBorder*/, int sizeExtraBorder /*=0*/, + int sizeTopExtra /*=0*/, int sizeSecondary /*=0*/) +{ + Pane* pPane = new PaneCtrl ( nID, this, orientation, sizeBorder, sizeExtraBorder, sizeTopExtra ); + pPane->m_sizeSecondary = sizeSecondary; + pPane->m_modeResize = modeResize; + + return CPane(pPane); +} + + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::item(UINT nID, ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, int sizeX /*=0*/, int sizeY /*=0*/, + int sizeXMin /*=-1*/, int sizeYMin /*=-1*/) +{ + return new PaneItem( nID, this, modeResize, sizeX, sizeY, sizeXMin, sizeYMin); +} + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::item(CWnd* pWnd, ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, + int sizeX /*=0*/, int sizeY /*=0*/, int sizeXMin /*=-1*/, + int sizeYMin /*=-1*/) +{ + return new PaneItem( pWnd, this, modeResize, sizeX, sizeY, sizeXMin, sizeYMin); +} + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::itemFixed(layOrientation orientation, int sizePrimary) +{ + CPaneBase p = new PaneItem(paneNull, this, NORESIZE, (orientation==HORIZONTAL)?sizePrimary:0, (orientation==VERTICAL)?sizePrimary:0); + return p; +} + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::itemGrowing(layOrientation orientation) +{ + return new PaneItem(paneNull, this, (orientation==HORIZONTAL)?ABSOLUTE_VERT:ABSOLUTE_HORZ, 0, 0, -nDefaultBorder, -nDefaultBorder); +} + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::itemSpaceBetween( layOrientation orientation, CWnd* pWndFirst, CWnd* pWndSecond ) +{ + if( orientation == HORIZONTAL ) { + // I'm interested in horizontal spacing + + CRect rLeft, rRight; + pWndFirst->GetWindowRect(&rLeft); + pWndSecond->GetWindowRect(&rRight); + + int sizeX = rRight.left - rLeft.right; + + if( sizeX < 0 ) { + // compare top to top + sizeX = rRight.left - rLeft.left; + } + else { + sizeX -= 2*nDefaultBorder; + } + + return new PaneItem(paneNull, this, NORESIZE, sizeX, 0); + } + else { + // I'm interested in vertical spacing + CRect rTop, rBot; + pWndFirst->GetWindowRect(&rTop); + pWndSecond->GetWindowRect(&rBot); + + int sizeY = rBot.top - rTop.bottom; + + if( sizeY < 0 ) { + // compare top to top + sizeY = sizeY = rBot.top - rTop.top; + } + else { + sizeY -= 2*nDefaultBorder; + } + + return new PaneItem(paneNull, this, NORESIZE, 0, sizeY); + } +} + + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::itemSpaceBetween( layOrientation orientation, UINT nIDFirst, UINT nIDSecond ) +{ + CWnd *pFirst = GetWnd()->GetDlgItem(nIDFirst); + CWnd *pSecond = GetWnd()->GetDlgItem(nIDSecond); + + ASSERT( pFirst && pSecond ); + + return itemSpaceBetween( orientation, pFirst, pSecond ); +} + + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::itemSpaceLike( layOrientation orientation, CWnd* pWnd ) +{ + CRect rRect; + pWnd->GetWindowRect(&rRect); + + if( orientation == HORIZONTAL ) { + // I'm interested in horizontal spacing + return new PaneItem(paneNull, this, NORESIZE, rRect.Width(), 0); + } + else { + // I'm interested in vertical spacing + return new PaneItem(paneNull, this, NORESIZE, 0, rRect.Height() ); + } + +} + + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::itemSpaceLike( layOrientation orientation, UINT nID ) +{ + CWnd *pWnd = GetWnd()->GetDlgItem(nID); + ASSERT( pWnd ); + + return itemSpaceLike( orientation, pWnd ); +} + + + +ETSLayoutMgr::~ETSLayoutMgr() +{ +} + +void ETSLayoutMgr::UpdateLayout() +{ + if(!m_RootPane) + return; + + // Check constraints + CRect rcClient = GetRect(); + + if( m_pWnd->IsKindOf( RUNTIME_CLASS( CDialog ) ) && !(m_pWnd->GetStyle()&WS_CHILD) ) { + CRect rcWindow; + m_pWnd->GetWindowRect(rcWindow); + + // Added by Didier BULTIAUW + CWnd* parentWnd = m_pWnd->GetParent(); + if( (parentWnd != 0) && parentWnd->IsKindOf(RUNTIME_CLASS(CView)) ) + { + CRect rcParent; + parentWnd->GetWindowRect(rcParent); + rcWindow.OffsetRect(-rcParent.left,-rcParent.top); + } + // end add + + CRect rcBorder = rcWindow; + rcBorder -= rcClient; + + // Min and Max info + int minWidth = m_RootPane->getMinConstrainHorz() + rcBorder.Width() + 2*m_sizeRootBorders.cx; + int minHeight = m_RootPane->getMinConstrainVert() + rcBorder.Height() + 2*m_sizeRootBorders.cy; + int maxWidth = m_RootPane->getMaxConstrainHorz(); + if(maxWidth != -1) { + maxWidth += rcBorder.Width() + 2*m_sizeRootBorders.cx; + maxWidth = max(maxWidth, minWidth); + } + int maxHeight = m_RootPane->getMaxConstrainVert(); + if(maxHeight != -1) { + maxHeight += rcBorder.Height() + 2*m_sizeRootBorders.cy; + maxHeight = max(maxHeight, minHeight); + } + + if(rcWindow.Width() < minWidth) + rcWindow.right = rcWindow.left + minWidth; + if(rcWindow.Height() < minHeight) + rcWindow.bottom = rcWindow.top + minHeight; + + if(maxWidth != -1 && rcWindow.Width() > maxWidth) + rcWindow.right = rcWindow.left + maxWidth; + if(maxHeight != -1 && rcWindow.Height() > maxHeight) + rcWindow.bottom = rcWindow.top + maxHeight; + + m_pWnd->MoveWindow(rcWindow); + } + // Do the Layout + rcClient = GetRect(); + + // Add a Border around the rootPane + rcClient.top += m_sizeRootBorders.cy; + rcClient.bottom -= m_sizeRootBorders.cy; + rcClient.left += m_sizeRootBorders.cx; + rcClient.right -= m_sizeRootBorders.cx; + + if(GetWnd()->IsWindowVisible()) { + // Avoid ugly artifacts + //GetWnd()->SetRedraw(FALSE); + Layout(rcClient); + //GetWnd()->SetRedraw(TRUE); + } + else + Layout(rcClient); + + GetWnd()->Invalidate(); +} + + +bool ETSLayoutMgr::Save(LPCTSTR lpstrRegKey) +{ + CRect rcWnd; + + if(IsWindow(GetWnd()->m_hWnd)) + { + WINDOWPLACEMENT wp; + if(GetWnd()->GetWindowPlacement(&wp)) + { + // Make sure we don't pop up + // minimized the next time + if(wp.showCmd != SW_SHOWMAXIMIZED) + wp.showCmd = SW_SHOWNORMAL; + + AfxGetApp()->WriteProfileBinary(lpstrRegKey, + "WindowPlacement", + reinterpret_cast(&wp), sizeof(wp)); + } + } + return true; +} + +bool ETSLayoutMgr::Load(LPCTSTR lpstrRegKey) +{ + LPBYTE pbtData = 0; + UINT nSize = 0; + if(AfxGetApp()->GetProfileBinary(lpstrRegKey, + "WindowPlacement", &pbtData, &nSize)) + { + WINDOWPLACEMENT* pwp = + reinterpret_cast(pbtData); + + ASSERT(nSize == sizeof(WINDOWPLACEMENT)); + if(nSize == sizeof(WINDOWPLACEMENT)) + GetWnd()->SetWindowPlacement(reinterpret_cast(pbtData)); + + delete [] pbtData; + } + return true; +} + + +void ETSLayoutMgr::EraseBkgnd(CDC* pDC) +{ + CRect rcClient; + GetWnd()->GetClientRect( rcClient ); + + CRgn rgn; + rgn.CreateRectRgnIndirect(rcClient); + + CRgn rgnRect; + rgnRect.CreateRectRgn(0,0,0,0); + + CRect rcChild; + CWnd* pWndChild = GetWnd()->GetWindow( GW_CHILD ); + + TCHAR szClassName[ MAX_PATH ]; + + CRect rcClip; + pDC->GetClipBox(&rcClip); + + while( pWndChild ) { + + pWndChild->GetWindowRect(rcChild); + GetWnd()->ScreenToClient( rcChild ); + + rgnRect.SetRectRgn( rcChild ); + + ::GetClassName( pWndChild->GetSafeHwnd(), szClassName, MAX_PATH ); + DWORD dwStyle = pWndChild->GetStyle(); + + // doesn't make sense for hidden children + if( dwStyle & WS_VISIBLE ) { + + if( _tcscmp(szClassName,"Button")==0 && (dwStyle & BS_GROUPBOX) ) { + // it is a group-box, ignore completely + } + else if( _tcscmp(szClassName,"SysTabControl32")==0 ) { + // ignore Tab-Control's inside rect + static_cast(pWndChild)->AdjustRect(FALSE,rcChild); + + CRgn rgnContent; + rgnContent.CreateRectRgnIndirect(rcChild); + + rgnRect.CombineRgn( &rgnRect, &rgnContent, RGN_DIFF ); + rgn.CombineRgn( &rgn, &rgnRect, RGN_DIFF ); + } + else { + rgn.CombineRgn( &rgn, &rgnRect, RGN_DIFF ); + } + } + + pWndChild = pWndChild->GetNextWindow(); + } + + + HBRUSH hBrBack = (HBRUSH) ::GetClassLong(GetWnd()->GetSafeHwnd(), GCL_HBRBACKGROUND) ; + if( hBrBack == 0 ) + hBrBack = ::GetSysColorBrush(COLOR_BTNFACE); + + pDC->FillRgn( &rgn, + CBrush::FromHandle( hBrBack ) + ); + +} + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutMgr::PaneItem implementation + + +ETSLayoutMgr::PaneItem::PaneItem(CWnd* pWnd, ETSLayoutMgr* pMgr, ETSLayoutMgr::layResizeMode modeResize/*=GREEDY*/ + , int sizeX/*=0*/, int sizeY/*=0*/ + , int sizeXMin/*=-1*/, int sizeYMin/*=-1*/ ) : PaneBase( pMgr ) +{ + m_modeResize = modeResize; + m_hwndCtrl = pWnd->GetSafeHwnd(); + + m_sizeX = 0; + m_sizeY = 0; + + m_bComboSpecial = false; + + m_sizeXMin = sizeXMin; + m_sizeYMin = sizeYMin; + + if(!m_hwndCtrl) { // only Dummy! + m_sizeX = sizeX; + m_sizeY = sizeY; + } + else { + CRect rcControl; + ::GetWindowRect(m_hwndCtrl, &rcControl); + + if(sizeX == 0) { + m_sizeX = rcControl.Width(); + } + else { + m_sizeX = sizeX; + } + if( m_sizeXMin == -1 ) { + // do not make smaller than current size + m_sizeXMin = rcControl.Width(); + } + + if(sizeY == 0) { + m_sizeY = rcControl.Height(); + } + else { + m_sizeY = sizeY; + } + if( m_sizeYMin == -1 ) { + // do not make smaller than current size + m_sizeYMin = rcControl.Height(); + } + + TCHAR szClassName[ MAX_PATH ]; + ::GetClassName( m_hwndCtrl, szClassName, MAX_PATH ); + + // special treatment for combo-boxes + if( _tcscmp(szClassName,"ComboBox")==0 ) { + m_bComboSpecial = true; + } + } +} + +ETSLayoutMgr::PaneItem::PaneItem( UINT nID, ETSLayoutMgr* pMgr, ETSLayoutMgr::layResizeMode modeResize/*=GREEDY*/ + , int sizeX/*=0*/, int sizeY/*=0*/ + , int sizeXMin/*=-1*/, int sizeYMin/*=-1*/ ) : PaneBase( pMgr ) +{ + CWnd* pWnd = pMgr->GetWnd()->GetDlgItem(nID); + m_hwndCtrl = pWnd->GetSafeHwnd(); + + m_sizeX = 0; + m_sizeY = 0; + + m_bComboSpecial = false; + + m_modeResize = modeResize; + + m_sizeXMin = sizeXMin; + m_sizeYMin = sizeYMin; + + if(!m_hwndCtrl) { // only Dummy! + m_sizeX = sizeX; + m_sizeY = sizeY; + } + else { + CRect rcControl; + ::GetWindowRect(m_hwndCtrl, &rcControl); + + if(sizeX == 0) { + m_sizeX = rcControl.Width(); + } + else { + m_sizeX = sizeX; + } + if( m_sizeXMin == -1 ) { + // do not make smaller than current size + m_sizeXMin = rcControl.Width(); + } + + if(sizeY == 0) { + m_sizeY = rcControl.Height(); + } + else { + m_sizeY = sizeY; + } + if( m_sizeYMin == -1 ) { + // do not make smaller than current size + m_sizeYMin = rcControl.Height(); + } + + TCHAR szClassName[ MAX_PATH ]; + ::GetClassName( m_hwndCtrl, szClassName, MAX_PATH ); + + // special treatment for combo-boxes + if( _tcscmp(szClassName,"ComboBox")==0 ) { + m_bComboSpecial = true; + } + } +} + +int ETSLayoutMgr::PaneItem::getConstrainHorz(int sizeParent) +{ + if( m_modeResize & ABSOLUTE_HORZ) { + return m_sizeX; + } + if(m_modeResize & RELATIVE_HORZ) { + return (sizeParent * m_sizeX) / 100; + } + return -1; +} + +int ETSLayoutMgr::PaneItem::getConstrainVert(int sizeParent) +{ + if(m_modeResize & ABSOLUTE_VERT) { + return m_sizeY; + } + if(m_modeResize & RELATIVE_VERT) { + return (sizeParent * m_sizeY) / 100; + } + return -1; +} + +int ETSLayoutMgr::PaneItem::getMinConstrainHorz() +{ + if(m_modeResize & ABSOLUTE_HORZ) { + return m_sizeX; + } + return max(nMinConstrain,m_sizeXMin); +} + +int ETSLayoutMgr::PaneItem::getMinConstrainVert() +{ + if(m_modeResize & ABSOLUTE_VERT) { + return m_sizeY; + } + return max(nMinConstrain,m_sizeYMin); +} + +int ETSLayoutMgr::PaneItem::getMaxConstrainHorz() +{ + if(m_modeResize & ABSOLUTE_HORZ) { + return m_sizeX; + } + return -1; +} + +int ETSLayoutMgr::PaneItem::getMaxConstrainVert() +{ + if(m_modeResize & ABSOLUTE_VERT) { + return m_sizeY; + } + return -1; +} + +bool ETSLayoutMgr::PaneItem::resizeTo(CRect& rcNewArea) +{ + if(m_hwndCtrl) { + + CRect rcWnd; + ::GetWindowRect( m_hwndCtrl, rcWnd ); + + if( !(m_modeResize & ALIGN_FILL_HORZ) && m_modeResize & ABSOLUTE_HORZ ) { + + + if( (m_modeResize & ALIGN_HCENTER) == ALIGN_HCENTER ) { + rcNewArea.OffsetRect( (rcNewArea.Width() - rcWnd.Width())/2, 0 ); + } + else if( m_modeResize & ALIGN_RIGHT ) { + rcNewArea.OffsetRect( rcNewArea.Width() - rcWnd.Width(), 0 ); + } + + rcNewArea.right = rcNewArea.left + rcWnd.Width(); + } + if( !(m_modeResize & ALIGN_FILL_VERT) && m_modeResize & ABSOLUTE_VERT ) { + + + if( (m_modeResize & ALIGN_VCENTER) == ALIGN_VCENTER ) { + rcNewArea.OffsetRect( 0, (rcNewArea.Height()-rcWnd.Height())/2 ); + } + else if( m_modeResize & ALIGN_BOTTOM ) { + rcNewArea.OffsetRect( 0, rcNewArea.Height() - rcWnd.Height()); + } + + rcNewArea.bottom = rcNewArea.top + rcWnd.Height(); + + } + + DWORD dwStyle = ::GetWindowLong( m_hwndCtrl, GWL_STYLE ); + + // special treatment for combo-boxes + if( m_bComboSpecial && (dwStyle & CBS_DROPDOWN) ) { + // keep height (though only fully visible when dropped down) + rcNewArea.bottom = rcNewArea.top + rcWnd.Height(); + } + + ::MoveWindow( m_hwndCtrl, rcNewArea.left, rcNewArea.top, rcNewArea.Width(), rcNewArea.Height(), true ); + + if( m_bComboSpecial && !(dwStyle & CBS_DROPDOWN) && !(dwStyle & CBS_NOINTEGRALHEIGHT) ) { + + // Keep CB Size = Edit + LB ( if not CBS_NOINTEGRALHEIGHT) + + ::GetWindowRect( m_hwndCtrl, rcWnd ); + + CRect rcListBox; + HWND hwndListBox = ::GetDlgItem(m_hwndCtrl, 1000); // ListBox of CB + if( hwndListBox != 0 ) + { + ::GetWindowRect( hwndListBox, rcListBox ); + rcWnd.bottom = rcListBox.bottom; + + rcNewArea.bottom = rcNewArea.top + rcWnd.Height(); + + ::MoveWindow( m_hwndCtrl, rcNewArea.left, rcNewArea.top, rcNewArea.Width(), rcNewArea.Height(), true ); + } + } + + ::RedrawWindow(m_hwndCtrl,0,0, RDW_INVALIDATE | RDW_UPDATENOW ); + + } + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutMgr::PaneTab implementation + + +ETSLayoutMgr::PaneTab::PaneTab( CTabCtrl* pTab, ETSLayoutMgr* pMgr, layOrientation orientation, int sizeBorder /*= nDefaultBorder*/, int sizeExtraBorder /*= 0*/ ) +: ETSLayoutMgr::Pane(pMgr, orientation, sizeBorder, sizeExtraBorder) +{ + ASSERT(pTab); + m_pTab = pTab; +} + +int ETSLayoutMgr::PaneTab::getConstrainHorz(int sizeParent) +{ + CRect rcTab; + m_pTab->AdjustRect(TRUE, &rcTab); + + if(rcTab.Width() > sizeParent) + return rcTab.Width(); + + return Pane::getConstrainHorz(sizeParent /*- rcTab.Width()*/); +} + +int ETSLayoutMgr::PaneTab::getConstrainVert(int sizeParent) +{ + CRect rcTab; + m_pTab->AdjustRect(TRUE, &rcTab); + + if( m_modeResize & ABSOLUTE_VERT ) { + return m_sizeSecondary + rcTab.Height(); + } + + if(rcTab.Height() > sizeParent) + return rcTab.Height(); + + return Pane::getConstrainVert(sizeParent /*- rcTab.Height()*/); +} + +int ETSLayoutMgr::PaneTab::getMinConstrainHorz() +{ + CRect rcTab(0,0,0,0); + m_pTab->AdjustRect(TRUE, &rcTab); + + return Pane::getMinConstrainHorz() + rcTab.Width() ; +} + +int ETSLayoutMgr::PaneTab::getMinConstrainVert() +{ + CRect rcTab(0,0,0,0); + m_pTab->AdjustRect(TRUE, &rcTab); + + return Pane::getMinConstrainVert() + rcTab.Height(); +} + +int ETSLayoutMgr::PaneTab::getMaxConstrainHorz() +{ + CRect rcTab(0,0,0,0); + m_pTab->AdjustRect(TRUE, &rcTab); + + int paneMax = Pane::getMaxConstrainHorz(); + return (paneMax != -1) ? paneMax + rcTab.Width() : -1; +} + +int ETSLayoutMgr::PaneTab::getMaxConstrainVert() +{ + CRect rcTab(0,0,0,0); + m_pTab->AdjustRect(TRUE, &rcTab); + + int paneMax = Pane::getMaxConstrainVert(); + return (paneMax != -1) ? paneMax + rcTab.Height() : -1; +} + +bool ETSLayoutMgr::PaneTab::resizeTo(CRect& rcNewArea) +{ + m_pTab->MoveWindow(rcNewArea); + m_pTab->AdjustRect(FALSE,rcNewArea); + + return Pane::resizeTo(rcNewArea); +} + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutMgr::PaneCtrl implementation + + +ETSLayoutMgr::PaneCtrl::PaneCtrl( CWnd* pCtrl, ETSLayoutMgr* pMgr, layOrientation orientation, int sizeBorder /*= nDefaultBorder*/, int sizeExtraBorder /*= 0*/, int sizeTopExtra /*= 0*/ ) +: ETSLayoutMgr::Pane(pMgr, orientation, sizeBorder, sizeExtraBorder) +{ + m_sizeTopExtra = sizeTopExtra; + + ASSERT(pCtrl); + m_hwndCtrl = pCtrl->GetSafeHwnd(); +} + +ETSLayoutMgr::PaneCtrl::PaneCtrl( UINT nID, ETSLayoutMgr* pMgr, layOrientation orientation, int sizeBorder /*= nDefaultBorder*/, int sizeExtraBorder /*= 0*/, int sizeTopExtra /*= 0*/ ) +: ETSLayoutMgr::Pane(pMgr, orientation, sizeBorder, sizeExtraBorder) +{ + m_sizeTopExtra = sizeTopExtra; + + m_hwndCtrl = ::GetDlgItem(pMgr->GetWnd()->GetSafeHwnd(), nID); + ASSERT(m_hwndCtrl); +} + +int ETSLayoutMgr::PaneCtrl::getConstrainHorz(int sizeParent) +{ + return Pane::getConstrainHorz(sizeParent) ; +} + +int ETSLayoutMgr::PaneCtrl::getConstrainVert(int sizeParent) +{ + return Pane::getConstrainVert(sizeParent); +} + +int ETSLayoutMgr::PaneCtrl::getMinConstrainHorz() +{ + return Pane::getMinConstrainHorz(); +} + +int ETSLayoutMgr::PaneCtrl::getMinConstrainVert() +{ + return Pane::getMinConstrainVert() + m_sizeTopExtra; +} + +int ETSLayoutMgr::PaneCtrl::getMaxConstrainHorz() +{ + int paneMax = Pane::getMaxConstrainHorz(); + return ( paneMax == -1) ? -1 : paneMax ; +} + +int ETSLayoutMgr::PaneCtrl::getMaxConstrainVert() +{ + int paneMax = Pane::getMaxConstrainVert(); + return ( paneMax == -1) ? -1 : paneMax + m_sizeTopExtra; +} + +bool ETSLayoutMgr::PaneCtrl::resizeTo(CRect& rcNewArea) +{ + ::MoveWindow(m_hwndCtrl, rcNewArea.left, rcNewArea.top, rcNewArea.Width(), rcNewArea.Height(), true); + ::RedrawWindow(m_hwndCtrl,0,0, RDW_INVALIDATE | RDW_UPDATENOW |RDW_ERASE); + rcNewArea.top += m_sizeTopExtra; + return Pane::resizeTo(rcNewArea); +} + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutMgr::Pane implementation + +ETSLayoutMgr::Pane::Pane( ETSLayoutMgr* pMgr, layOrientation orientation, int sizeBorder /* = nDefaultBorder */, int sizeExtraBorder /*= 0*/) +: PaneBase(pMgr) +{ + m_Orientation = orientation; + m_sizeBorder = sizeBorder; + m_sizeSecondary = 0; + m_modeResize = 0; + m_sizeExtraBorder= sizeExtraBorder; +} + + +ETSLayoutMgr::Pane::~Pane() +{ +} + + +bool ETSLayoutMgr::Pane::addItem( CWnd* pWnd, ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, int sizeX /*=0*/, int sizeY /*=0*/, int sizeXMin /*=0*/, int sizeYMin /*=0*/) +{ + CPaneBase pItem = new PaneItem( pWnd, m_pMgr, modeResize, sizeX, sizeY, sizeXMin, sizeYMin); + return addPane( pItem ); +} + +bool ETSLayoutMgr::Pane::addItem( UINT nID, ETSLayoutMgr::layResizeMode modeResize /*=GREEDY*/, int sizeX /*=0*/, int sizeY /*=0*/, int sizeXMin /*=0*/, int sizeYMin /*=0*/) +{ + CPaneBase pItem = new PaneItem( nID, m_pMgr, modeResize, sizeX, sizeY, sizeXMin, sizeYMin); + return addPane( pItem ); +} + +bool ETSLayoutMgr::Pane::addItemFixed(int size) +{ + CPaneBase pNewItem = m_pMgr->itemFixed(m_Orientation, size); + return addPane( pNewItem ); +} + +bool ETSLayoutMgr::Pane::addItemGrowing() +{ + CPaneBase pNewItem = m_pMgr->itemGrowing(m_Orientation); + return addPane( pNewItem ); +} + +bool ETSLayoutMgr::Pane::addItemSpaceBetween( CWnd* pWndFirst, CWnd* pWndSecond ) +{ + CPaneBase pNewItem = m_pMgr->itemSpaceBetween(m_Orientation, pWndFirst, pWndSecond); + return addPane( pNewItem ); +} + +bool ETSLayoutMgr::Pane::addItemSpaceBetween( UINT nIDFirst, UINT nIDSecond ) +{ + CPaneBase pNewItem = m_pMgr->itemSpaceBetween(m_Orientation, nIDFirst, nIDSecond); + return addPane( pNewItem ); +} + +bool ETSLayoutMgr::Pane::addItemSpaceLike( CWnd* pWnd ) +{ + CPaneBase pNewItem = m_pMgr->itemSpaceLike(m_Orientation, pWnd); + return addPane( pNewItem ); +} + +bool ETSLayoutMgr::Pane::addItemSpaceLike( UINT nID ) +{ + CPaneBase pNewItem = m_pMgr->itemSpaceLike(m_Orientation, nID); + return addPane( pNewItem ); +} + +bool ETSLayoutMgr::Pane::addPane( CPane pSubpane, ETSLayoutMgr::layResizeMode modeResize, int sizeSecondary /* = 0 */) +{ + if( pSubpane->getOrientation() == m_Orientation) + { + // wrap in subpane of opposite orientation + CPane pPaneWrap = new Pane(m_pMgr, m_Orientation==HORIZONTAL?VERTICAL:HORIZONTAL,0,0); + pPaneWrap->addPane( pSubpane ); + + addPane( pPaneWrap, modeResize, sizeSecondary ); + } + else + { + pSubpane->m_modeResize = modeResize; + + if(m_Orientation==HORIZONTAL && (modeResize & ABSOLUTE_HORZ) ) { + if(sizeSecondary == 0) { + pSubpane->m_sizeSecondary = pSubpane->getMinConstrainHorz(); + } + } + else if(m_Orientation==HORIZONTAL && (modeResize & RELATIVE_HORZ) ) { + pSubpane->m_sizeSecondary = sizeSecondary; + } + else if(m_Orientation==VERTICAL && (modeResize & ABSOLUTE_VERT) ) { + if(sizeSecondary == 0) { + pSubpane->m_sizeSecondary = pSubpane->getMinConstrainVert(); + } + } + else if(m_Orientation==VERTICAL && (modeResize & RELATIVE_VERT) ) { + pSubpane->m_sizeSecondary = sizeSecondary; + } + + m_paneItems.Add(pSubpane); + } + + return true; +} + +bool ETSLayoutMgr::Pane::addPane( CPaneBase pItem ) +{ + m_paneItems.Add(pItem); + return true; +} + +int ETSLayoutMgr::Pane::getConstrainHorz(int sizeParent) +{ + ASSERT( m_Orientation == VERTICAL); + + if( m_modeResize & RELATIVE_HORZ ) { + return (sizeParent * m_sizeSecondary) / 100; + } + else if( m_modeResize & ABSOLUTE_HORZ ){ + return m_sizeSecondary; + } + else + return 0; +} + + +int ETSLayoutMgr::Pane::getConstrainVert(int sizeParent) +{ + ASSERT( m_Orientation == HORIZONTAL); + + if( m_modeResize & RELATIVE_VERT ) { + return (sizeParent * m_sizeSecondary) / 100; + } + else if( m_modeResize & ABSOLUTE_VERT ) { + return m_sizeSecondary; + } + else { + return 0; + } +} + +int ETSLayoutMgr::Pane::getMaxConstrainHorz() +{ + if(m_Orientation == HORIZONTAL) { + int nMaxConstr = -1; + for(int i=0; igetMaxConstrainHorz(); + if(nConstrain == -1) + return -1; + + nMaxConstr += nConstrain; + } + return (nMaxConstr == -1) ? -1 : nMaxConstr + (m_paneItems.GetUpperBound()*m_sizeBorder) + 2*m_sizeExtraBorder; + } + else if( m_modeResize & ABSOLUTE_HORZ && m_sizeSecondary!=0) { + return m_sizeSecondary; // + 2*m_sizeExtraBorder; + } + else { + int nMaxConstr = -1; + for(int i=0; igetMaxConstrainHorz(); + + if( nConstrain == -1) + return -1; + else + nMaxConstr = max(nMaxConstr, nConstrain); + + } + return (nMaxConstr == -1) ? -1 : nMaxConstr + 2*m_sizeExtraBorder; + } +} + +int ETSLayoutMgr::Pane::getMaxConstrainVert() +{ + if(m_Orientation == VERTICAL) { + int nMaxConstr = -1; + for(int i=0; igetMaxConstrainVert(); + if(nConstrain == -1) + return -1; + + nMaxConstr += nConstrain; + } + return (nMaxConstr == -1) ? -1 : nMaxConstr + (m_paneItems.GetUpperBound()*m_sizeBorder) + 2*m_sizeExtraBorder; + } + else if( m_modeResize & ABSOLUTE_VERT && m_sizeSecondary!=0) { + return m_sizeSecondary; // + 2*m_sizeExtraBorder; + } + else { + int nMaxConstr = -1; + for(int i=0; igetMaxConstrainVert(); + + if( nConstrain == -1) + return -1; + else + nMaxConstr = max(nMaxConstr, nConstrain); + + } + return (nMaxConstr == -1) ? -1 : nMaxConstr + 2*m_sizeExtraBorder; + } +} + +int ETSLayoutMgr::Pane::getMinConstrainHorz() +{ + if(m_Orientation == HORIZONTAL) { + int nMaxConstr = 0; + for(int i=0; igetMinConstrainHorz()); + } + return nMaxConstr + (m_paneItems.GetUpperBound()*m_sizeBorder) + 2*m_sizeExtraBorder; + } + else if( m_modeResize & ABSOLUTE_HORZ && m_sizeSecondary!=0) { + return m_sizeSecondary; // + 2*m_sizeExtraBorder; + } + else { + int nMaxConstr = 0; + for(int i=0; igetMinConstrainHorz(); + nMaxConstr = max(nMaxConstr, nConstrain); + } + return nMaxConstr + 2*m_sizeExtraBorder; + } +} + +int ETSLayoutMgr::Pane::getMinConstrainVert() +{ + if(m_Orientation == VERTICAL) { + int nMaxConstr = 0; + for(int i=0; igetMinConstrainVert()); + } + return nMaxConstr + (m_paneItems.GetUpperBound()*m_sizeBorder) + 2*m_sizeExtraBorder; + } + else if( m_modeResize & ABSOLUTE_VERT && m_sizeSecondary!=0) { + return m_sizeSecondary; // + 2*m_sizeExtraBorder; + } + else { + int nMaxConstr = 0; + for(int i=0; igetMinConstrainVert(); + nMaxConstr = max(nMaxConstr, nConstrain); + } + return nMaxConstr + 2*m_sizeExtraBorder; + } +} + + +int ETSLayoutMgr::Pane::resizeToAbsolute(int& availSpace, CArray& sizePrimary, + CArray& sizeMin, CArray& sizeMax) +{ + // count all greedy items as returnvalue + int nGreedy = 0; + + // first, subtract all absoulute items from available space + for(int i=0; imodeResize() & ABSOLUTE_HORZ) { + availSpace -= (sizePrimary[i] = pItem->getConstrainHorz(0)); + } + + // count Greedy items for later + if(!(pItem->modeResize() & ABSOLUTE_HORZ) && !(pItem->modeResize() & RELATIVE_HORZ)) { + nGreedy++; + } + + sizeMin[i] = pItem->getMinConstrainHorz(); + sizeMax[i] = pItem->getMaxConstrainHorz(); + } + else { + + // for absolute items subtract their size from available space + if(pItem->modeResize() & ABSOLUTE_VERT) { + availSpace -= (sizePrimary[i] = pItem->getConstrainVert(0)); + } + + // count Greedy items for later + if(!(pItem->modeResize() & ABSOLUTE_VERT) && !(pItem->modeResize() & RELATIVE_VERT)) { + nGreedy++; + } + + sizeMin[i] = pItem->getMinConstrainVert(); + sizeMax[i] = pItem->getMaxConstrainVert(); + } + + } + + // Must not be negative !! + availSpace = max(availSpace, 0); + + return nGreedy; +} + +bool ETSLayoutMgr::Pane::resizeToRelative(int& availSpace, CArray& sizePrimary, + CArray& sizeMin, CArray& sizeMax) +{ + // Then all relative items as percentage of left space (as of now after + // all absolute items are subtracted + + int availRel = availSpace; // At the beginning all of remaining space is available. We want all + // operation to be relative to the left space at this moment, so we + // save this amount here. Then we safly can lower availSpace + + int relDiff = 0; // The cumulated difference between first proposed size and + // eventual maximum/minimum size. This amount has to be + // saved in some other place (i.e. where relativ items/subpane + // are not limited by min/max + + int relLeft = 0; // The cumulated amout of space that can be saved by + // shrinking the items/panes up to the minimum + + int relCount = 0; // Actually allocated item/subpane's cumulated primary sizes + // of non-limited items/subpanes (these can be modified in fixup) + // needed for equally distribution of differences amoung non-limited + // relative items/subpanes + + for(int i=0; imodeResize() & RELATIVE_HORZ) + || + (m_Orientation==VERTICAL && pItem->modeResize() & RELATIVE_VERT) ) + { + // minimum item/subpane size in primary direction (pixels) + int nSizeRelMin = sizeMin[i]; + + // maximum item/subpane size in primary direction (pixels) + int nSizeRelMax = sizeMax[i]; + + // Relative size in primary direction (pixels) + int nSizeRel = (m_Orientation==HORIZONTAL) + ? + (pItem->getConstrainHorz(availRel)) + : + (pItem->getConstrainVert(availRel)); + + if( nSizeRel < nSizeRelMin) { + // The item/pane is shrinked too small! + // We will grow it to it's minimum-size. In order not to modify + // this item later when fixing up set the size to the negative + // minimum size + sizePrimary[i] = -nSizeRelMin; + + // As we grew one item/subpane we have to shrink another one. + // We keep count on how much space we needed to grow the item + // to it's minimum size + relDiff += ( nSizeRelMin - nSizeRel ); + } + else if( nSizeRelMax != -1 && nSizeRel > nSizeRelMax) { + // if there's a maximum size (nSizeRelMax != -1) and our item/subpane + // is to be resized over that amount correct it. In order not to modify + // this item later when fixing up set the size to the negative + // maximum size + sizePrimary[i] = -nSizeRelMax; + + // As we shrinked one item/subpane we have to grow another one. + // We keep count on how much space we needed to grow the item + // to it's maximum size. + relDiff += ( nSizeRelMax - nSizeRel ); + } + else { + // this is the normal case: neither are we minimum limited nor maximum + // limited + + // As this item/subpane is larger that it's minimum we could later (if + // necessary for fixup) shrink it for the difference amount of pixels + relLeft += ( nSizeRel - nSizeRelMin ); + + // Set the primary size of this item/pane. Can later be modified by fixup + sizePrimary[i] = nSizeRel; + + // Add this item/subpane's primary size to the count of already allocated + // cumulated size of non-limited items/subpanes (these can be modified in fixup) + relCount += nSizeRel; + } + + // decrease available space by used space in this step + availSpace -= nSizeRel; + } + } + + // We now have the situation that some items/subpanes had to be adjusted for cumulated + // relDiff pixels (positive value means more space taken than indicated by percentage of + // left space). On the other hand we have some items/subpanes which were not limited (in + // their current dimensions) but could be if necessary up to relLeft pixels. + if(relLeft < relDiff && availSpace >= (relDiff-relLeft) ){ + + // If it's not possible to shrink other (relative) panes in order to distribute the + // difference because the left for shrinking (relLeft) is too small we need to aquire + // more space from the globally left space (if available at all) + availSpace -= (relDiff-relLeft); + relDiff = relLeft; + } + + // At this point we should have some space left (at least not be negative with the leftover + // space) and on the other hand there's enough space for the limit-difference to be distributed + ASSERT( availSpace >= 0 && relLeft >= relDiff); + + // Fixup Relative: + // Distribute (if anecessary) relDiff on other (not limited) relative items/subpanes + // (if available - if not later just grow the limited panes) + while( relDiff != 0 && relCount >= 0 ) { + + // in every iteration there must be some space distributed (of the difference) or it could + // come to endless looping. Save the amount of space actually distributed in this iteration + int relDist = 0; + + for(i=0; imodeResize() & RELATIVE_HORZ) && sizePrimary[i] > 0) + || + (m_Orientation==VERTICAL && (pItem->modeResize() & RELATIVE_VERT) && sizePrimary[i] > 0) ) + { + // keep a flag for termination of this iteration + bool bLast = false; + + // the difference should be distributed amoung all non-limited items/subpanes equally. + // nDiff is the amount for the current item/subpane + int nDiff = (relDiff * sizePrimary[i]) / relCount; + + // if it's a too small value just add it to the current pane and break iteration + if( abs(relDiff) <= FIXUP_CUTOFF ) { + // take it all in this step + nDiff = relDiff; + + // set break flag + bLast = true; + } + + // calculate the new size for the current item/subpane + int nNewSize = sizePrimary[i] - nDiff; + + if( nNewSize < sizeMin[i] ) { + // oh, we are limited here. Revise our plan: + + // Not all of the space could be saved, add the actually possible space + // to the sum + relDist += ( sizePrimary[i] - sizeMin[i] ); + + // set it to the minimum possible size + sizePrimary[i] = -sizeMin[i]; + + // as this item/subpane is now limited it's occupied space doesn't count + // for relCount anymore + relCount-= ( sizePrimary[i] ); + } + else { + // account the difference of the sizes in relDist and set new size + relDist += ( sizePrimary[i] - nNewSize ); + sizePrimary[i] = nNewSize; + + // if it's the last one break now + if(bLast) + break; + } + } + } + // Distributed some relDiff-space in every iteration + ASSERT(relDist != 0); + relDiff -= relDist; + } + + // Fixup Relative: invert all negative (limited) sized to correct value + for(i=0; imodeResize() & RELATIVE_HORZ) && sizePrimary[i] < 0) + || + (m_Orientation==VERTICAL && (pItem->modeResize() & RELATIVE_VERT) && sizePrimary[i] < 0) ) + { + sizePrimary[i] *= -1; + } + } + + return true; +} + +bool ETSLayoutMgr::Pane::resizeToGreedy(int& availSpace, int nGreedy, CArray& sizePrimary, + CArray& sizeMin, CArray& sizeMax) +{ + // Now resize all Greedy items/subpanes equally among the remaining space + int greedyDiff = 0; // The cumulated difference between first proposed size and + // eventual maximum/minimum size. This amount has to be + // saved in some other place (i.e. where items/subpane + // are not limited by min/max + + int greedyLeft = 0; // The cumulated amount of space that can be saved by + // shrinking the items/panes up to the minimum + + int greedyCount = 0; // Actually allocated item/subpane's cumulated primary sizes + // of non-limited items/subpanes (these can be modified in fixup) + // needed for equally distribution of differences amoung non-limited + // items/subpanes + + for(int i=0; imodeResize()&ABSOLUTE_HORZ) + && !(pItem->modeResize()&RELATIVE_HORZ) + ) + || + (m_Orientation==VERTICAL + && !(pItem->modeResize()&ABSOLUTE_VERT) + && !(pItem->modeResize()&RELATIVE_VERT) + ) + ) + { + + // All greedy items get an equal portion of the left space + int nSize = availSpace / nGreedy; + + // minimum item/subpane size in primary direction (pixels) + int nSizeMin = sizeMin[i]; + + // maximum item/subpane size in primary direction (pixels) + int nSizeMax = sizeMax[i]; + + + // the last gets the all of the remaining space + if( nGreedy == 1 ) + nSize = availSpace; + + if( nSize < nSizeMin) { + // The item/pane is shrinked too small! + // We will grow it to it's minimum-size. In order not to modify + // this item later when fixing up set the size to the negative + // minimum size + sizePrimary[i] = -nSizeMin; + + // As we grew one item/subpane we have to shrink another one. + // We keep count on how much space we needed to grow the item + // to it's minimum size + greedyDiff += ( nSizeMin - nSize ); + } + else if( nSizeMax != -1 && nSize > nSizeMax) { + // if there's a maximum size (nSizeRelMax != -1) and our item/subpane + // is to be resized over that amount correct it. In order not to modify + // this item later when fixing up set the size to the negative + // maximum size + sizePrimary[i] = -nSizeMax; + + // As we shrinked one item/subpane we have to grow another one. + // We keep count on how much space we needed to grow the item + // to it's maximum size. + greedyDiff += ( nSizeMax - nSize ); + } + else { + + // this is the normal case: neither are we minimum limited nor maximum + // limited + + // As this item/subpane is larger that it's minimum we could later (if + // necessary for fixup) shrink it for the difference amount of pixels + greedyLeft += ( nSize - nSizeMin ); + + // Set the primary size of this item/pane. Can later be modified by fixup + sizePrimary[i] = nSize; + + // Add this item/subpane's primary size to the count of already allocated + // cumulated size of non-limited items/subpanes (these can be modified in fixup) + greedyCount += nSize; + } + + // decrease available space by used space in this step + availSpace -= nSize; + + // one greedy item/subpane complete + --nGreedy; + } + } + + + // Fixup Greedy I + // Distribute (if anecessary) greedyDiff on other (not limited) greedy items/subpanes + // (if available - if not later just grow the limited panes) + + // at least on not limited item present + bool bAtLeastOne = true; + + while( bAtLeastOne && greedyDiff != 0 && greedyCount > 0) { + + // in every iteration there must be some space distributed (of the difference) or it could + // come to endless looping. Save the amount of space actually distributed in this iteration + int greedyDist = 0; + + // at least on not limited item present + bAtLeastOne = false; + + for(i=0; imodeResize()&ABSOLUTE_HORZ) + && !(pItem->modeResize()&RELATIVE_HORZ) + && sizePrimary[i] > 0 + ) + || + (m_Orientation==VERTICAL + && !(pItem->modeResize()&ABSOLUTE_VERT) + && !(pItem->modeResize()&RELATIVE_VERT) + && sizePrimary[i] > 0 + ) + ) + { + // keep a flag for termination of this iteration + bool bLast = false; + + // the difference should be distributed among all non-limited items/subpanes equally. + // nDiff is the amount for the current item/subpane + int nDiff = (greedyDiff * sizePrimary[i]) / greedyCount; + + // if it's a too small value just add it to the current pane and break iteration + if( abs(greedyDiff) <= FIXUP_CUTOFF || nDiff == 0) { + // take it all in this step + nDiff = greedyDiff; + + // set break flag + bLast = true; + } + + // calculate the new size for the current item/subpane + int nNewSize = sizePrimary[i] - nDiff; + + if( nNewSize < sizeMin[i] ) { + // oh, we are limited here. Revise our plan: + + if( sizePrimary[i] != sizeMin[i] ) + bAtLeastOne = true; + + // Not all of the space could be saved, add the actually possible space + // to the sum + greedyDist += ( sizePrimary[i] - sizeMin[i] ); + + // set it to the minimum possible size + sizePrimary[i] = sizeMin[i]; + + // as this item/subpane is now limited its occupied space doesn't count + // for relCount anymore + greedyCount -= ( sizePrimary[i] ); + } + else { + // yes, there is one + bAtLeastOne = true; + + // account the difference of the sizes in relDist and set new size + greedyDist += ( sizePrimary[i] - nNewSize ); + sizePrimary[i] = nNewSize; + + // if it's the last one break now + if(bLast) + break; + } + } + } + // Distributed some greedyDiff-space in every iteration + ASSERT(!bAtLeastOne || greedyDist != 0 || greedyCount<=0); + greedyDiff -= greedyDist; + } + + + // Fixup Greedy II + if( greedyDiff < 0 ) { + // still difference, some space left + + // are there any items which are minimum-limited where we can give more space? + for(i=0; imodeResize()&ABSOLUTE_HORZ) + && !(pItem->modeResize()&RELATIVE_HORZ) + ) + || + (m_Orientation==VERTICAL + && !(pItem->modeResize()&ABSOLUTE_VERT) + && !(pItem->modeResize()&RELATIVE_VERT) + ) + ) + { + if( sizePrimary[i] == -sizeMin[i] ) { + // fill this one up as much as possible + if( sizeMax[i] == -1) { + // all fits in + sizePrimary[i] += greedyDiff; + greedyDiff = 0; + } + else { + sizePrimary[i] += -min( -greedyDiff, sizeMax[i]-sizeMin[i]); + greedyDiff -= -min( -greedyDiff, sizeMax[i]-sizeMin[i]); + } + } + } + } + } + + + // Fixup Greedy III: invert all negative (limited) sized to correct value + for(i=0; imodeResize() & ABSOLUTE_HORZ) + && !(pItem->modeResize() & RELATIVE_HORZ) + && sizePrimary[i] < 0 + && sizeMin[i] >= 0 + ) + || + (m_Orientation==VERTICAL + && !(pItem->modeResize() & ABSOLUTE_VERT) + && !(pItem->modeResize() & RELATIVE_VERT) + && sizePrimary[i] < 0 + && sizeMin[i] >= 0 + ) + ) + { + if(sizePrimary[i] < 0) + sizePrimary[i] *= -1; + } + } + + return true; +} + + +bool ETSLayoutMgr::Pane::resizeTo(CRect& rcNewArea) +{ + // There must be some items or subpanes + ASSERT(m_paneItems.GetSize()); + + // This Array holds the size in primary direction for each item/subpane + CArray sizePrimary; + sizePrimary.SetSize(m_paneItems.GetSize()); + + // This Array holds information about the minimum size in primary direction + CArray sizeMin; + sizeMin.SetSize(m_paneItems.GetSize()); + + // This Array holds information about the maximum size in primary direction + CArray sizeMax; + sizeMax.SetSize(m_paneItems.GetSize()); + + + // How much space is actually available, subtract all borders between items + int availSpace = (m_Orientation == HORIZONTAL ? rcNewArea.Width() : rcNewArea.Height() ) - (m_paneItems.GetUpperBound()*m_sizeBorder); + + // If there is some Extra border (on top/bottem resp. left/right) subtract it too + availSpace -= 2*m_sizeExtraBorder; + + // Add the extra Border to top/bottem resp. left/right + if(m_Orientation == HORIZONTAL) { + rcNewArea.top += m_sizeExtraBorder; + rcNewArea.bottom -= m_sizeExtraBorder; + } + else { + rcNewArea.left += m_sizeExtraBorder; + rcNewArea.right -= m_sizeExtraBorder; + } + + // Counts the number of greedy items/subpanes + int nGreedy = resizeToAbsolute(availSpace, sizePrimary, sizeMin, sizeMax ); + + if(nGreedy == -1) + return false; + + if(! resizeToRelative(availSpace, sizePrimary, sizeMin, sizeMax ) ) + return false; + + if(! resizeToGreedy(availSpace, nGreedy, sizePrimary, sizeMin, sizeMax ) ) + return false; + + + // If there is any left space and there are ALIGN_FILL_* Items to assign it + // equally among them + if( availSpace > 0 ) { + // Count possible Items + int nFillItems = 0; + + for(int i=0; imodeResize() & ABSOLUTE_HORZ ) + && (pItem->modeResize() & ALIGN_FILL_HORZ) + + || + + (pItem->modeResize() & ABSOLUTE_VERT ) + && (pItem->modeResize() & ALIGN_FILL_VERT) + ) + { + ++nFillItems; + } + } + + if( nFillItems > 0 ) { + // okay, there are nFillItems, make them all availSpace/nFillItems bigger + for(int i=0; imodeResize() & ABSOLUTE_HORZ ) + && (pItem->modeResize() & ALIGN_FILL_HORZ) + + || + + (pItem->modeResize() & ABSOLUTE_VERT ) + && (pItem->modeResize() & ALIGN_FILL_VERT) + ) + { + + if( nFillItems == 1 ) { + // the last one gets all the rest + sizePrimary[i] += availSpace; + availSpace = 0; + --nFillItems; + } + else { + sizePrimary[i] += availSpace/nFillItems; + availSpace -= availSpace/nFillItems; + --nFillItems; + } + + } + } + } + + } + + // Now reposition all items: + + // starting offset + int nOffset = (m_Orientation==HORIZONTAL ? rcNewArea.left : rcNewArea.top ) + m_sizeExtraBorder; + for(int i=0; iresizeTo( rcPane ); + + // go to the next position (old pos + size + border) + ASSERT(sizePrimary[i] >= 0); + nOffset += m_sizeBorder + sizePrimary[i]; + } + + + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutDialog dialog + +#pragma warning(disable: 4355) +ETSLayoutDialog::ETSLayoutDialog(UINT nID, CWnd* pParent /*=NULL*/, LPCTSTR strName /*=NULL*/, bool bGripper /*=true*/) + : CBaseDialog(nID, pParent), ETSLayoutMgr( this ) +{ + //{{AFX_DATA_INIT(ETSLayoutDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bGripper = bGripper; + + if(strName) + m_strRegStore = strName; +} +#pragma warning(default: 4355) + +BEGIN_MESSAGE_MAP(ETSLayoutDialog, CBaseDialog) + //{{AFX_MSG_MAP(ETSLayoutDialog) + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_ERASEBKGND() + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutDialog message handlers + +BOOL ETSLayoutDialog::OnEraseBkgnd(CDC* pDC) +{ + EraseBkgnd(pDC); + return true; +} + +void ETSLayoutDialog::OnSize(UINT nType, int cx, int cy) +{ + CBaseDialog::OnSize(nType, cx, cy); + + if( abs(cx) + abs(cy) > 0) + { + // Reposition Size Marker + // Re-Layout all controls + UpdateLayout(); + RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); + } + +} + +void ETSLayoutDialog::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + if(m_RootPane.IsValid()) { + CRect rcClient = GetRect(); + + CRect rcWnd; + GetWindowRect(rcWnd); + + // How much do Window and Client differ + int nDiffHorz = rcWnd.Width() - rcClient.Width(); + int nDiffVert = rcWnd.Height() - rcClient.Height(); + + // Take into account that there is a border around the rootPane + lpMMI->ptMinTrackSize = CPoint(m_RootPane->getMinConstrainHorz() + nDiffHorz + 2*m_sizeRootBorders.cx, + m_RootPane->getMinConstrainVert() + nDiffVert + 2*m_sizeRootBorders.cy); + + int maxWidth = m_RootPane->getMaxConstrainHorz(); + int maxHeight = m_RootPane->getMaxConstrainVert(); + + if( maxWidth != -1 ) { + lpMMI->ptMaxTrackSize.x = maxWidth + nDiffHorz + 2*m_sizeRootBorders.cx; + lpMMI->ptMaxSize.x = maxWidth + nDiffHorz + 2*m_sizeRootBorders.cx; + } + + if( maxHeight != -1 ) { + lpMMI->ptMaxTrackSize.y = maxHeight + nDiffVert + 2*m_sizeRootBorders.cy; + lpMMI->ptMaxSize.y = maxHeight + nDiffVert + 2*m_sizeRootBorders.cy; + } + } +} + + +CRect ETSLayoutDialog::GetRect() +{ + CRect r; + GetClientRect(r); + + if( m_bGripper ) + { + if( ::IsWindow(m_StatusBar.GetSafeHwnd()) ) + { + CRect rcSizeIcon; + m_StatusBar.GetWindowRect( rcSizeIcon); + r.bottom -= (rcSizeIcon.Height() - m_sizeRootBorders.cy - 5); + } + } + + return r; +} + + +BOOL ETSLayoutDialog::OnInitDialog() +{ + CBaseDialog::OnInitDialog(); + + if(!m_strRegStore.IsEmpty()) { + Load(m_strRegStore); + } + +#ifdef _AUTO_SET_ICON + POSITION pos = AfxGetApp()->GetFirstDocTemplatePosition(); + if(pos) { + + class ETSPseudoDocTemplate : public CDocTemplate + { + friend class ETSLayoutDialog; + }; + + ETSPseudoDocTemplate* pDocT = (ETSPseudoDocTemplate*) AfxGetApp()->GetNextDocTemplate(pos); + SetIcon( AfxGetApp()->LoadIcon(pDocT->m_nIDResource) ,FALSE); + } +#endif + + // Sizing icon + if(m_bGripper) + { + if(m_StatusBar.Create(m_pWnd)) + { + m_StatusBar.SetIndicators(auIDStatusBar, sizeof(auIDStatusBar) / sizeof(UINT)); + m_StatusBar.SetWindowText(""); + m_StatusBar.SetPaneStyle( 0, SBPS_STRETCH | SBPS_NOBORDERS ); + m_pWnd -> RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); + } + else + AfxMessageBox("Error - Statusbar"); + + } + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void ETSLayoutDialog::OnDestroy() +{ + // Store size/position + if(!m_strRegStore.IsEmpty()) { + Save(m_strRegStore); + } + + // manually delete layout definition if object is reused + m_RootPane = 0; + + CBaseDialog::OnDestroy(); +} + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutDialog dialog + +#pragma warning(disable: 4355) +#ifdef CS_HELP +ETSLayoutDialogBar::ETSLayoutDialogBar(UINT nID ) + : CBaseDialogBar( nID ), ETSLayoutMgr( this ) +#else +ETSLayoutDialogBar::ETSLayoutDialogBar() + : ETSLayoutMgr( this ) +#endif +{ + //{{AFX_DATA_INIT(ETSLayoutDialogBar) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bInitialized = false; + setRootBorders(0,0); +} +#pragma warning(default: 4355) + +BEGIN_MESSAGE_MAP(ETSLayoutDialogBar, CBaseDialogBar) + //{{AFX_MSG_MAP(ETSLayoutDialogBar) + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + ON_WM_ERASEBKGND() + ON_MESSAGE(WM_INITDIALOG, OnInitDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutDialogBar message handlers + +LRESULT ETSLayoutDialogBar::OnInitDialog(WPARAM, LPARAM) +{ + Default(); + Initialize(); + return TRUE; +} + +CSize ETSLayoutDialogBar::CalcDynamicLayout(int nLength, DWORD dwMode) +{ + CSize sizeRet = CBaseDialogBar::CalcDynamicLayout(nLength, dwMode); + + CSize sizeMin = sizeRet; + CSize sizeMax = sizeRet; + + if(m_RootPane.IsValid()) { + CRect rcClient = GetRect(); + + CRect rcWnd; + GetWindowRect(rcWnd); + + // How much do Window and Client differ + CSize sizeDiff( rcWnd.Width() - rcClient.Width(), rcWnd.Height() - rcClient.Height()); + + // Take into account that there is a border around the rootPane + sizeMin = CSize(m_RootPane->getMinConstrainHorz() + sizeDiff.cx + 2*m_sizeRootBorders.cx, + m_RootPane->getMinConstrainVert() + sizeDiff.cy + 2*m_sizeRootBorders.cy); + + + int maxWidth = m_RootPane->getMaxConstrainHorz(); + int maxHeight = m_RootPane->getMaxConstrainVert(); + + if( maxWidth != -1 ) { + sizeMax.cx = maxWidth + sizeDiff.cy + 2*m_sizeRootBorders.cx; + } + + if( maxHeight != -1 ) { + sizeMax.cy = maxHeight + sizeDiff.cy + 2*m_sizeRootBorders.cy; + } + } + + if( IsFloating() || !(dwMode&LM_HORZ)) + { + sizeRet.cx = min( sizeRet.cx, sizeMax.cx ); + } + if( IsFloating() || (dwMode&LM_HORZ)) + { + sizeRet.cy = min( sizeRet.cy, sizeMax.cy ); + } + + sizeRet.cx = max( sizeRet.cx, sizeMin.cx ); + sizeRet.cy = max( sizeRet.cy, sizeMin.cy ); + + return sizeRet; +} + +BOOL ETSLayoutDialogBar::OnEraseBkgnd(CDC* pDC) +{ + EraseBkgnd(pDC); + return true; +} + + +void ETSLayoutDialogBar::OnSize(UINT nType, int cx, int cy) +{ + CBaseDialogBar::OnSize(nType, cx, cy); + + if( abs(cx) + abs(cy) > 0) + { + // Re-Layout all controls + UpdateLayout(); + } + RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); + +} + + +CRect ETSLayoutDialogBar::GetRect() +{ + CRect r; + GetClientRect(r); + + if( IsFloating() ) + r.DeflateRect(4,4); + + return r; +} + + +void ETSLayoutDialogBar::OnDestroy() +{ + // Store size/position on your own! + CBaseDialogBar::OnDestroy(); +} + + + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutFormView dialog + +IMPLEMENT_DYNAMIC(ETSLayoutFormView, CFormView) + +#pragma warning(disable: 4355) +ETSLayoutFormView::ETSLayoutFormView(UINT nID, LPCTSTR strName /*=NULL*/) + : CBaseFormView(nID), ETSLayoutMgr( this ) +{ + if(strName) + m_strRegStore = strName; +} +#pragma warning(default: 4355) + +BEGIN_MESSAGE_MAP(ETSLayoutFormView, CBaseFormView) + //{{AFX_MSG_MAP(ETSLayoutFormView) + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_ERASEBKGND() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutFormView message handlers + +BOOL ETSLayoutFormView::OnEraseBkgnd(CDC* pDC) +{ + EraseBkgnd(pDC); + return true; +} + + +void ETSLayoutFormView::OnSize(UINT nType, int cx, int cy) +{ +// CBaseFormView::OnSize(nType, cx, cy); + SetScrollSizes(MM_TEXT, CSize(cx,cy)); + if( abs(cx) + abs(cy) > 0) { + // Re-Layout all controls + UpdateLayout(); + } +// MoveWindow(0,0,cx,cy); +} + +/* +void ETSLayoutFormView::UpdateLayout() +{ + ETSLayoutMgr::UpdateLayout(); + + if(m_RootPane.IsValid()) { + // Force MainFrame to re-layout + CFrameWnd* pFrame = static_cast(GetParent()); + if(pFrame) { + + CRect rcWnd; + pFrame->GetWindowRect(rcWnd); + pFrame->MoveWindow(rcWnd); + pFrame->RecalcLayout(); + + } + return; + } +} +*/ + +void ETSLayoutFormView::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + // To use this you'll have to modify your CMainFrame: + // + // 1) Add a handler for WM_GETMINMAXINFO() + // 2) Let this handler be: + // void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) + // { + // CFrameWnd::OnGetMinMaxInfo(lpMMI); + // + // if( GetActiveView() && GetActiveView()->IsKindOf( RUNTIME_CLASS(ETSLayoutFormView) ) ) { + // GetActiveView()->SendMessage( WM_GETMINMAXINFO, 0, (LPARAM) lpMMI ); + // } + // } + // 3) Add "#include "dialogmgr.h" to MainFrm.cpp + + if(m_RootPane.IsValid()) { + CRect rcClient = GetRect(); + + CRect rcWnd; + GetParent()->GetWindowRect(rcWnd); + + // How much do Window and Client differ + rcWnd-=rcClient; + + // Take into account that there is a border around the rootPane + lpMMI->ptMinTrackSize = CPoint(m_RootPane->getMinConstrainHorz() + rcWnd.Width() + 2*m_sizeRootBorders.cx, + m_RootPane->getMinConstrainVert() + rcWnd.Height() + 2*m_sizeRootBorders.cy); + + int maxWidth = m_RootPane->getMaxConstrainHorz(); + int maxHeight = m_RootPane->getMaxConstrainVert(); + + if( maxWidth != -1 ) { + lpMMI->ptMaxTrackSize.x = maxWidth + rcWnd.Width()+ 2*m_sizeRootBorders.cx; + lpMMI->ptMaxSize.x = maxWidth + rcWnd.Width()+ 2*m_sizeRootBorders.cx; + } + + if( maxHeight != -1 ) { + lpMMI->ptMaxTrackSize.y = maxHeight + rcWnd.Height() + 2*m_sizeRootBorders.cy; + lpMMI->ptMaxSize.y = maxHeight + rcWnd.Height() + 2*m_sizeRootBorders.cy; + } + } +} + +ETSLayoutFormView::~ETSLayoutFormView() +{ + // Cleanup +} + + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutPropertyPage + +#ifdef CS_HELP + IMPLEMENT_DYNCREATE(ETSLayoutPropertyPage, ETSCSHelpPropPage) +#else + IMPLEMENT_DYNCREATE(ETSLayoutPropertyPage, CPropertyPage) +#endif + +#pragma warning(disable: 4355) +ETSLayoutPropertyPage::ETSLayoutPropertyPage( ) : ETSLayoutMgr( this ) +{ + m_bLockMove = false; +} + +ETSLayoutPropertyPage::ETSLayoutPropertyPage( UINT nIDTemplate, UINT nIDCaption /*= 0*/ ) + : CBasePropertyPage(nIDTemplate, nIDCaption), ETSLayoutMgr( this ) +{ + m_bLockMove = false; +} + +ETSLayoutPropertyPage::ETSLayoutPropertyPage( LPCTSTR lpszTemplateName, UINT nIDCaption /*= 0*/ ) + : CBasePropertyPage(lpszTemplateName, nIDCaption), ETSLayoutMgr( this ) +{ + m_bLockMove = false; +} +#pragma warning(default: 4355) + +ETSLayoutPropertyPage::~ETSLayoutPropertyPage() +{ +} + + +BEGIN_MESSAGE_MAP(ETSLayoutPropertyPage, CBasePropertyPage) + //{{AFX_MSG_MAP(ETSLayoutPropertyPage) + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_ERASEBKGND() + ON_WM_WINDOWPOSCHANGING() + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen für Nachrichten ETSLayoutPropertyPage + + +void ETSLayoutPropertyPage::OnWindowPosChanging( WINDOWPOS* lpwndpos ) +{ + // In WizardMode the System calls SetWindowPos with the + // original size at every activation. This could cause + // some flicker in certain circumstances. Therefore we lock + // moving the page and unlock it only if _we_ move the page + if( m_bLockMove) + { + lpwndpos->flags |= SWP_NOMOVE | SWP_NOSIZE; + } + CBasePropertyPage::OnWindowPosChanging( lpwndpos ); +} + +BOOL ETSLayoutPropertyPage::OnEraseBkgnd(CDC* pDC) +{ + EraseBkgnd(pDC); + return true; +} + +void ETSLayoutPropertyPage::OnDestroy() +{ + // manually delete layout definition if object is reused + m_RootPane = 0; + + CBasePropertyPage::OnDestroy(); +} + +void ETSLayoutPropertyPage::OnSize(UINT nType, int cx, int cy) +{ + CBasePropertyPage::OnSize(nType, cx, cy); + + if( abs(cx) + abs(cy) > 0) + { + // Re-Layout all controls + UpdateLayout(); + } +} + +void ETSLayoutPropertyPage::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + if(m_RootPane.IsValid()) { + CRect rcClient = GetRect(); + + CRect rcWnd; + GetWindowRect(rcWnd); + + // How much do Window and Client differ + int nDiffHorz = rcWnd.Width() - rcClient.Width(); + int nDiffVert = rcWnd.Height() - rcClient.Height(); + + // Take into account that there is a border around the rootPane + lpMMI->ptMinTrackSize = CPoint(m_RootPane->getMinConstrainHorz() + nDiffHorz + 2*m_sizeRootBorders.cx, + m_RootPane->getMinConstrainVert() + nDiffVert + 2*m_sizeRootBorders.cy); + + int maxWidth = m_RootPane->getMaxConstrainHorz(); + int maxHeight = m_RootPane->getMaxConstrainVert(); + + if( maxWidth != -1 ) { + lpMMI->ptMaxTrackSize.x = maxWidth + nDiffHorz + 2*m_sizeRootBorders.cx; + lpMMI->ptMaxSize.x = maxWidth + nDiffHorz + 2*m_sizeRootBorders.cx; + } + + if( maxHeight != -1 ) { + lpMMI->ptMaxTrackSize.y = maxHeight + nDiffVert + 2*m_sizeRootBorders.cy; + lpMMI->ptMaxSize.y = maxHeight + nDiffVert + 2*m_sizeRootBorders.cy; + } + } +} + + +CRect ETSLayoutPropertyPage::GetRect() +{ + CRect r; + GetClientRect(r); + return r; +} + + +BOOL ETSLayoutPropertyPage::OnInitDialog() +{ + CBasePropertyPage::OnInitDialog(); + UpdateLayout(); + + ETSLayoutPropertySheet* pSheet = (ETSLayoutPropertySheet*) GetParent(); + + ASSERT_KINDOF( ETSLayoutPropertySheet, pSheet); + if(pSheet) + { + if(pSheet->IsWizard()) + { + m_bLockMove = true; + } + } + + return TRUE; +} + +BOOL ETSLayoutPropertyPage::OnSetActive() +{ + ETSLayoutPropertySheet* pSheet = (ETSLayoutPropertySheet*) GetParent(); + + ASSERT_KINDOF( ETSLayoutPropertySheet, pSheet); + if(pSheet) + { + if(pSheet->IsWizard()) + { + // In WizardMode the System calls SetWindowPos with the + // original size on Page Activation. This will position the + // page at the correct position + m_bLockMove = false; + MoveWindow(pSheet->m_rcPage); + m_bLockMove = true; + } + } + + UpdateLayout(); + + return CBasePropertyPage::OnSetActive(); +} + +///////////////////////////////////////////////////////////////////////////// +// ETSLayoutPropertySheet + +IMPLEMENT_DYNAMIC(ETSLayoutPropertySheet, CPropertySheet) + +#pragma warning(disable: 4355) +ETSLayoutPropertySheet::ETSLayoutPropertySheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage, + LPCTSTR strName /*=NULL*/, bool bGripper/*=true*/) + : CPropertySheet(nIDCaption, pParentWnd, iSelectPage), ETSLayoutMgr( this ) +{ + Init(strName, bGripper); +} + +ETSLayoutPropertySheet::ETSLayoutPropertySheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage, + LPCTSTR strName /*=NULL*/, bool bGripper/*=true*/) + : CPropertySheet(pszCaption, pParentWnd, iSelectPage), ETSLayoutMgr( this ) +{ + Init(strName, bGripper); +} +#pragma warning(default: 4355) + +void ETSLayoutPropertySheet::Init(LPCTSTR strName, bool bGripper) +{ + m_bGripper = bGripper; + if(strName) + m_strRegStore = strName; + + m_bAutoDestroy = false; + m_bAutoDestroyPages = false; + m_bModelessButtons = false; +} + +ETSLayoutPropertySheet::~ETSLayoutPropertySheet() +{ +} + + +BEGIN_MESSAGE_MAP(ETSLayoutPropertySheet, CPropertySheet) + //{{AFX_MSG_MAP(ETSLayoutPropertySheet) + ON_WM_CREATE() + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + ON_WM_ERASEBKGND() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen für Nachrichten ETSLayoutPropertySheet + +BOOL ETSLayoutPropertySheet::OnEraseBkgnd(CDC* pDC) +{ + EraseBkgnd(pDC); + return true; +} + + +int ETSLayoutPropertySheet::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CPropertySheet::OnCreate(lpCreateStruct) == -1) + return -1; + + ModifyStyle(0,WS_THICKFRAME| WS_SYSMENU |WS_CLIPCHILDREN); + return 0; +} + + +void ETSLayoutPropertySheet::Resize(int cx, int cy) +{ + if( abs(cx) + abs(cy) > 0 && m_RootPane.IsValid() ) + { + UpdateLayout(); + + if(IsWizard()) + { + // manual reposition of the FINISH button + // can not be done with normaly layouting because it + // shares position with the NEXT button + CWnd *pWndFinish; + pWndFinish=GetDlgItem(ID_WIZFINISH); + + if(pWndFinish) + { + CRect rcWnd; + GetDlgItem(ID_WIZNEXT)->GetWindowRect(&rcWnd); + ScreenToClient(&rcWnd); + pWndFinish->MoveWindow(rcWnd); + pWndFinish->RedrawWindow(0,0, RDW_INVALIDATE | RDW_UPDATENOW ); + } + } + + // reposition Gripper + if(m_bGripper) + RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); + + CPropertyPage* pPage = (CPropertyPage*)GetActivePage(); + + if(pPage) + { + CRect rcWnd; + GetTabControl()->GetWindowRect(&rcWnd); + ScreenToClient(&rcWnd); + + if(!IsWizard()) { + // get inside of tab + GetTabControl()->AdjustRect(FALSE, &rcWnd); + } + else + { + rcWnd.bottom += 5; + } + + // we need this size in WizardMode in order to + // reposition newly activated page correctly + m_rcPage = rcWnd; + + if( IsWizard() && pPage->IsKindOf(RUNTIME_CLASS(ETSLayoutPropertyPage)) ) + { + ETSLayoutPropertyPage* pEtsPage = reinterpret_cast(pPage); + + pEtsPage->m_bLockMove = false; + pEtsPage->MoveWindow(m_rcPage); + pEtsPage->m_bLockMove = true; + } + else + { + pPage->MoveWindow(m_rcPage); + } + + } + + if(IsWindowVisible()) + { + RedrawWindow(0,0, RDW_INVALIDATE|RDW_UPDATENOW ); + + if(!IsWizard()) + GetTabControl()->RedrawWindow(0,0, RDW_INVALIDATE|RDW_UPDATENOW ); + } + } +} + +void ETSLayoutPropertySheet::OnSize(UINT nType, int cx, int cy) +{ + CPropertySheet::OnSize(nType, cx, cy); + Resize(cx,cy); +} + +// IDs of all PropertySheet controls +long _PropertySheetIDs[] = +{ + ID_WIZBACK, + ID_WIZNEXT, + IDOK, + IDCANCEL, + ID_APPLY_NOW, + IDHELP +}; + + +BOOL ETSLayoutPropertySheet::OnInitDialog() +{ + BOOL bRet = CPropertySheet::OnInitDialog(); + + ASSERT(!m_RootPane); + + // Save initial rect + GetWindowRect(&m_rcStart); + + CPropertyPage* pPage = CPropertySheet::GetActivePage(); + ASSERT(pPage); + + CRect rcPage; + pPage->GetClientRect(&rcPage); + + CreateRoot(VERTICAL); + ASSERT(m_RootPane); + + // Add Tabcontrol to root pane + m_ItemTab = item( GetTabControl(), GREEDY, 0, 0, 0, 0); + m_RootPane << m_ItemTab; + + // Tabcontrol is invisible in WizardMode + if(IsWizard()) + { + GetTabControl()->ShowWindow(false); + } + + // add horizontal line in WizardMode + if(IsWizard() && GetDlgItem(ID_WIZFINISH+1)) + { + m_RootPane << item(ID_WIZFINISH+1, ABSOLUTE_VERT, 0, 0, 0, 0); + } + + if( IsWizard() || !m_bModeless || m_bModelessButtons ) + { + // No spaces in WizardMode in order to keep BACK & NEXT together + CPane bottomPane = pane(HORIZONTAL, ABSOLUTE_VERT, IsWizard() ? 0 : 5); + + // first item greedy to keep others right + bottomPane->addItem (paneNull, GREEDY); + + + // add all Controls to the layouting + bool bFirst = true; + for(int i = 0; i < (sizeof(_PropertySheetIDs) / sizeof(long)) ; i++) + { + CWnd* pWnd = GetDlgItem(_PropertySheetIDs[i]); + + if(pWnd) + { + + if(!(m_psh.dwFlags & PSH_HASHELP) && _PropertySheetIDs[i] == IDHELP) + { + // don't insert + continue; + } + + if((m_psh.dwFlags & PSH_NOAPPLYNOW) && _PropertySheetIDs[i] == ID_APPLY_NOW) + { + // don't insert + continue; + } + + // space before first one and between BACK & NEXT + if( IsWizard() ) + { + if( !bFirst && !(_PropertySheetIDs[i]==ID_WIZNEXT) ) + { + bottomPane->addItem(paneNull, NORESIZE,12,0,0,0); + } + } + + pWnd->ShowWindow(true); + bottomPane->addItem(_PropertySheetIDs[i], NORESIZE); + bFirst = false; + } + } + + // add bottom (button) pane + m_RootPane << bottomPane; + } + + + + // some Space between Buttons und Gripper + if(m_bGripper) + { + m_RootPane->addItem(paneNull, ABSOLUTE_VERT,0,2); + + if(m_StatusBar.Create(m_pWnd)) + { + m_StatusBar.SetIndicators(auIDStatusBar, + sizeof(auIDStatusBar) / sizeof(UINT)); + m_StatusBar.SetWindowText(""); + RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); + } + else + { + AfxMessageBox("Error - Statusbar"); + } + } + + if(!m_strRegStore.IsEmpty()) + { + Load(m_strRegStore); + } + + Resize(1,1); // Fix. for 95/98/NT difference + + CRect rcWnd; + GetWindowRect( & rcWnd ); + MoveWindow( rcWnd ); + + return bRet; +} + + +void ETSLayoutPropertySheet::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + if(m_RootPane.IsValid() && GetTabControl() != 0 ) + { + CRect rcWnd; + GetWindowRect(rcWnd); + + CRect rcClient = GetRect(); + rcWnd-=rcClient; + + // ask for MinMax of all pages + CSize sizePageMax(0,0); + CSize sizePageMin(0,0); + for( int nPage=0; nPageGetSafeHwnd()) ) + { + pPage->SendMessage(WM_GETMINMAXINFO, 0, (LPARAM) &mmi); + + if(mmi.ptMaxTrackSize.x != 0) + { + sizePageMax.cx = min(sizePageMax.cx, mmi.ptMaxTrackSize.x); + } + if(mmi.ptMaxTrackSize.y != 0) + { + sizePageMax.cy = min(sizePageMax.cy, mmi.ptMaxTrackSize.y); + } + if(mmi.ptMinTrackSize.x != 0) + { + sizePageMin.cx = max(sizePageMin.cx, mmi.ptMinTrackSize.x); + } + if(mmi.ptMinTrackSize.y != 0) + { + sizePageMin.cy = max(sizePageMin.cy, mmi.ptMinTrackSize.y); + } + } + } + } + static_cast( m_ItemTab.GetPaneBase() )->m_sizeXMin = sizePageMin.cx; + static_cast( m_ItemTab.GetPaneBase() )->m_sizeYMin = sizePageMin.cy; + + // calculate the needed size of the tabctrl in non-wizard-mode + CRect rcItem(0,0,0,0); + if(!IsWizard()) + { + GetTabControl()->AdjustRect( TRUE, rcItem ); + } + + lpMMI->ptMinTrackSize.x = m_RootPane->getMinConstrainHorz() + rcWnd.Width() + 2*m_sizeRootBorders.cx + + rcItem.Width(); + + lpMMI->ptMinTrackSize.y = m_RootPane->getMinConstrainVert() + rcWnd.Height() + 2*m_sizeRootBorders.cy + + rcItem.Height(); + + // never smaller than inital size! + lpMMI->ptMinTrackSize.x = max(lpMMI->ptMinTrackSize.x, m_rcStart.Width() ); + lpMMI->ptMinTrackSize.y = max(lpMMI->ptMinTrackSize.y, m_rcStart.Height() ); + + // Rest like ETSLayoutMgr + + int maxWidth = m_RootPane->getMaxConstrainHorz(); + int maxHeight = m_RootPane->getMaxConstrainVert(); + + if( maxWidth != -1 ) + { + lpMMI->ptMaxSize.x = sizePageMax.cx + rcWnd.Width()+ 2*m_sizeRootBorders.cx + rcItem.Width() ; + } + + if( maxHeight != -1 ) + { + lpMMI->ptMaxSize.y = sizePageMax.cy + rcWnd.Height() + 2*m_sizeRootBorders.cy + rcItem.Width() ; + } + + lpMMI->ptMaxTrackSize = lpMMI->ptMaxSize; + + } +} + + +void ETSLayoutPropertySheet::OnDestroy() +{ + // Store size/position + if(!m_strRegStore.IsEmpty()) + { + Save(m_strRegStore); + } + m_RootPane = 0; + + CPropertySheet::OnDestroy(); +} + +void ETSLayoutPropertySheet::PostNcDestroy() +{ + if(m_bAutoDestroyPages) + { + // walk all pages and destry them + for( int nPage=0; nPageRelease(); +} + +void ETSLayoutMgr::CPaneBase::operator=( PaneBase* pPane ) +{ + if(m_pPaneHolder) + { + m_pPaneHolder->Release(); + m_pPaneHolder = 0; + } + + if( pPane != 0 ) + m_pPaneHolder = new PaneHolder( pPane ); +} + +void ETSLayoutMgr::CPaneBase::operator=( const CPaneBase& other ) +{ + ASSERT( other.m_pPaneHolder ); + + if(m_pPaneHolder) + { + m_pPaneHolder->Release(); + m_pPaneHolder = 0; + } + + other.m_pPaneHolder->AddRef(); + m_pPaneHolder = other.m_pPaneHolder; +} + +ETSLayoutMgr::PaneBase* ETSLayoutMgr::CPaneBase::operator->() const +{ + ASSERT(m_pPaneHolder); + + if(!m_pPaneHolder) + return 0; + + return (m_pPaneHolder->m_pPane); +} + + + +ETSLayoutMgr::CPane::CPane( ) +{ +} + +ETSLayoutMgr::CPane::CPane( Pane* pPane ) : ETSLayoutMgr::CPaneBase( static_cast(pPane) ) +{ +} + +ETSLayoutMgr::CPane::CPane( const CPane& other ) +{ + operator=(other); +} + +ETSLayoutMgr::CPane::~CPane() +{ +} + +void ETSLayoutMgr::CPane::operator=( Pane* pPane ) +{ + CPaneBase::operator=(pPane); +} + +void ETSLayoutMgr::CPane::operator=( const ETSLayoutMgr::CPane& other ) +{ + ASSERT( other.m_pPaneHolder ); + + if(m_pPaneHolder) + { + m_pPaneHolder->Release(); + m_pPaneHolder = 0; + } + + other.m_pPaneHolder->AddRef(); + m_pPaneHolder = other.m_pPaneHolder; +} + +ETSLayoutMgr::Pane* ETSLayoutMgr::CPane::operator->() const +{ + ASSERT(m_pPaneHolder); + + if(!m_pPaneHolder) + return 0; + + return reinterpret_cast(m_pPaneHolder->m_pPane); +} + +ETSLayoutMgr::CPaneBase ETSLayoutMgr::CPane::ConvertBase() const +{ + ASSERT(m_pPaneHolder); + return CPaneBase( m_pPaneHolder->m_pPane ); +} + +ETSLayoutMgr::CPane& ETSLayoutMgr::CPane::operator<< ( const ETSLayoutMgr::CPane pPane ) +{ + GetPane()->addPane( pPane, (ETSLayoutMgr::layResizeMode)pPane->m_modeResize, pPane->m_sizeSecondary); + return (*this); +} + +ETSLayoutMgr::CPane& ETSLayoutMgr::CPane::operator<< ( const ETSLayoutMgr::CPaneBase pItem ) +{ + GetPane()->addPane( pItem ); + return (*this); +} -- cgit v1.1