Changing Splitter Rows and Columns
John Horton -- jhorton@unitechsys.com Thursday, October 10, 1996 Environment: VC++ 4.2 / NT 4.0 I have a static splitter window with two panes - one on top of the other (1 col, 2 rows). I would like to allow the user to change the splitter so the panes are side-by-side (2 cols, 1 row). Can this be done without having to create a new splitter and new views? Any help would be appreciated, John
Kostya Sebov -- sebov@is.kiev.ua Saturday, October 12, 1996 > Environment: VC++ 4.2 / NT 4.0 > > I have a static splitter window with two panes - one on top of the > other (1 col, 2 rows). I would like to allow the user to change the > splitter so the panes are side-by-side (2 cols, 1 row). > > Can this be done without having to create a new splitter and new > views? > > Any help would be appreciated, > > John > I didn't find easier way than hacking the internal CSplitterWnd data structures (manually 'reshaping' the arrays) then changing child window ID's for the panes. Although this may sound too crude from the purist's view the code worked almost unchanged from 2.5 to 4.1. If needed I can post the code. HTH --- Kostya Sebov. ---------------------------------------------------------------------------- Tel: (38 044) 266-6387 | Fax: (38 044) 266-6195 | E-mail: sebov@is.kiev.ua
Archana -- ARANGINANI@cerner.com Friday, October 18, 1996 I had the same issue of allowing the user to change the splitter from vertical to horizontal . I got around it basically by creating two views .....one with horizontal splitter and other with vertical splitter. I would appreciate if you can post your code >---------- >From: Kostya Sebov[SMTP:sebov@is.kiev.ua] >Sent: Saturday, October 12, 1996 12:24 PM >To: jhorton@unitechsys.com >Cc: mfc-l@netcom.com >Subject: Re: Changing Splitter Rows and Columns > >> Environment: VC++ 4.2 / NT 4.0 >> >> I have a static splitter window with two panes - one on top of the >> other (1 col, 2 rows). I would like to allow the user to change the >> splitter so the panes are side-by-side (2 cols, 1 row). >> >> Can this be done without having to create a new splitter and new >> views? >> >> Any help would be appreciated, >> >> John >> > >I didn't find easier way than hacking the internal CSplitterWnd data >structures (manually 'reshaping' the arrays) then changing child window >ID's >for the panes. Although this may sound too crude from the purist's view >the code >worked almost unchanged from 2.5 to 4.1. > >If needed I can post the code. > >HTH > >--- >Kostya Sebov. >------------------------------------------------------------------------ >---- >Tel: (38 044) 266-6387 | Fax: (38 044) 266-6195 | E-mail: >sebov@is.kiev.ua >
Kostya Sebov -- sebov@is.kiev.ua Wednesday, October 30, 1996 >> I have a static splitter window with two panes - one on top of the >> other (1 col, 2 rows). I would like to allow the user to change the >> splitter so the panes are side-by-side (2 cols, 1 row). >> >> Can this be done without having to create a new splitter and new >> views? >> >> Any help would be appreciated, >> >> John >> > >I didn't find easier way than hacking the internal CSplitterWnd data >structures (manually 'reshaping' the arrays) then changing child window >ID's >for the panes. Although this may sound too crude from the purist's view >the code >worked almost unchanged from 2.5 to 4.1. > >If needed I can post the code. > So I'm doing this. Begging for your pardon for the delay I've also included the code that switches the panes' order and keeps relative widths/heights when the splitter is resized. Note however that I'm pasting from my source code removing specifics on the way so forgive me in advance if this won't compile at the very first time. The final note is that the method was used for static splitters but I think can be easily adapted for the dynamic ones. //RvSplit.h ///////////////////////////////////////////////////////////////////////////// // CRvSplitter // class CRvSplitter : public CSplitterWnd { DECLARE_DYNAMIC( CRvSplitter ) // Construction / destruction public: CRvSplitter(); virtual ~CRvSplitter(); // Attributes protected: int m_nSplitRatio; BOOL m_bPanesSwapped; public: void SetSplitRatio( int nRatio ); BOOL IsSplitHorizontally() const; BOOL IsSplitVertically() const { return !IsSplitHorizontally(); } BOOL ArePanesSwapped() const { return m_bPanesSwapped; } // Operations protected: BOOL UpdateSplitRatio(); BOOL UpdatePanes( int cx, int cy ); BOOL UpdatePanes(); public: void Flip(); void SplitVertically(); void SplitHorizontally(); void SwapPanes(); // Implementation public: protected: // Generated message map functions //{{AFX_MSG(CRvSplitter) afx_msg void OnSize(UINT nType, int cx, int cy); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// ============================================================================ //RvSplit.cpp #include "StdAfx.h" #include "RvApp.h" #include "RvSplit.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CRvSplitter // IMPLEMENT_DYNAMIC( CRvSplitter, CSplitterWnd ) CRvSplitter::CRvSplitter() : m_nSplitRatio( -1 ), m_bPanesSwapped( FALSE ) { } CRvSplitter::~CRvSplitter() { } BEGIN_MESSAGE_MAP(CRvSplitter, CSplitterWnd) //{{AFX_MSG_MAP(CRvSplitter) ON_WM_SIZE() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CRvSplitter::SetSplitRatio( int nRatio ) { m_nSplitRatio = nRatio; } BOOL CRvSplitter::IsSplitHorizontally() const { ASSERT(( m_nRows > 1 ) != ( m_nCols > 1 )); ASSERT( max( m_nRows, m_nCols ) == 2 ); // This assertion comes from my specifics. // Hopefully it can be removed for more than 2 panes. return ( m_nCols > 1 ); } void CRvSplitter::SplitHorizontally() { if( IsSplitHorizontally()) return; ASSERT( m_nCols = 1 ); ASSERT( m_nRows = 2 ); // Get the last pane. // We need one to change its child ID later but not to produce the assertion // falure in the IdFromRowCol. // There's no need to change ID for the first one. CWnd* pPane = GetDlgItem( IdFromRowCol( 1, 0 )); ASSERT( pPane ); // swap the H/V information m_nMaxCols = m_nCols = 2; m_nMaxRows = m_nRows = 1; CRowColInfo* pTmp = m_pColInfo; m_pColInfo = m_pRowInfo; m_pRowInfo = pTmp; // change the last pane's ID reference pPane->SetDlgCtrlID( IdFromRowCol( 0, 1 )); ASSERT( GetPane( 0, 1 )->GetSafeHwnd() == pPane->GetSafeHwnd() ); if( UpdatePanes()) RecalcLayout(); } void CRvSplitter::SplitVertically() { if( IsSplitVertically()) return; ASSERT( m_nCols = 2 ); ASSERT( m_nRows = 1 ); // Get the last pane. // We need one to change its child ID later but not to produce the assertion // falure in the IdFromRowCol. // There's no need to change ID for the first one. CWnd* pPane = GetDlgItem(IdFromRowCol( 0, 1 )); ASSERT( pPane ); // swap the H/V information m_nMaxCols = m_nCols = 1; m_nMaxRows = m_nRows = 2; CRowColInfo* pTmp = m_pColInfo; m_pColInfo = m_pRowInfo; m_pRowInfo = pTmp; // change the last pane's ID reference ( no need to change ID for the first one ) pPane->SetDlgCtrlID( IdFromRowCol( 1, 0 )); ASSERT( GetPane( 1, 0 )->GetSafeHwnd() == pPane->GetSafeHwnd() ); if( UpdatePanes()) RecalcLayout(); } void CRvSplitter::Flip() { if( IsSplitHorizontally()) SplitVertically(); else { ASSERT( IsSplitVertically()); SplitHorizontally(); } } void CRvSplitter::SwapPanes() { if( IsSplitHorizontally()) { ASSERT( m_nCols = 2 ); ASSERT( m_nRows = 1 ); CWnd* pLeft = GetDlgItem( IdFromRowCol( 0, 0 )); ASSERT( pLeft ); CWnd* pRight = GetDlgItem(IdFromRowCol( 0, 1 )); ASSERT( pRight ); pLeft ->SetDlgCtrlID( IdFromRowCol( 0, 1 ));// will be right pRight->SetDlgCtrlID( IdFromRowCol( 0, 0 ));// will be left ASSERT( GetPane( 0, 0 )->GetSafeHwnd() == pRight->GetSafeHwnd() ); ASSERT( GetPane( 0, 1 )->GetSafeHwnd() == pLeft->GetSafeHwnd() ); } else { ASSERT( IsSplitVertically()); ASSERT( m_nCols = 1 ); ASSERT( m_nRows = 2 ); CWnd* pUpper = GetDlgItem( IdFromRowCol( 0, 0 )); ASSERT( pUpper ); CWnd* pLower = GetDlgItem( IdFromRowCol( 1, 0 )); ASSERT( pLower ); pUpper->SetDlgCtrlID( IdFromRowCol( 1, 0 ));// will be lower pLower->SetDlgCtrlID( IdFromRowCol( 0, 0 ));// will be upper ASSERT( GetPane( 0, 0 )->GetSafeHwnd() == pLower->GetSafeHwnd() ); ASSERT( GetPane( 1, 0 )->GetSafeHwnd() == pUpper->GetSafeHwnd() ); } m_bPanesSwapped = ~m_bPanesSwapped; if( UpdatePanes()) RecalcLayout(); } int CRvSplitter::UpdateSplitRatio() { CRowColInfo* pPanes; int czSplitter; if( IsSplitHorizontally()) { pPanes = m_pColInfo; czSplitter = m_cxSplitter; } else { pPanes = m_pRowInfo; czSplitter = m_cySplitter; } TRACE( "CRvSplitter::UpdateSplitRatio: 1:%i, 2:%i\n", pPanes[0].nCurSize, pPanes[1].nCurSize ); if(( pPanes[0].nCurSize != -1 ) && ( pPanes[0].nCurSize + pPanes[1].nCurSize != 0 ) ) { m_nSplitRatio = CProfile::splitResolution * pPanes[0].nCurSize / ( pPanes[0].nCurSize + pPanes[1].nCurSize + czSplitter ); } TRACE("m_nSplitRatio=%i\n", m_nSplitRatio ); return m_nSplitRatio; } BOOL CRvSplitter::UpdatePanes() { CRect rcClient; GetClientRect( rcClient ); return ( !rcClient.IsRectEmpty() && UpdatePanes( rcClient.Width(), rcClient.Height()) ); } BOOL CRvSplitter::UpdatePanes( int cx, int cy ) { TRACE("UpdatePanes: cx=%i, cy=%i\n", cx, cy ); CRowColInfo* pPanes; int cz; if( IsSplitHorizontally()) { pPanes = m_pColInfo; cz = cx; } else { pPanes = m_pRowInfo; cz = cy; } BOOL bRes = UpdateSplitRatio(); if( m_nSplitRatio >= 0 ) { ASSERT( (ULONG)m_nSplitRatio * cz / CProfile::splitResolution <= (ULONG)INT_MAX ); pPanes[0].nIdealSize = int( (ULONG)m_nSplitRatio * cz / CProfile::splitResolution ); } return bRes; } ///////////////////////////////////////////////////////////////////////////// // CRvSplitter message handlers // void CRvSplitter::OnSize( UINT nType, int cx, int cy ) { TRACE("CRvSplitter::OnSize: cx:%i, cy:%i\n", cx, cy ); if(( nType != SIZE_MINIMIZED )&&( cx > 0 )&&( cy > 0 )) UpdatePanes( cx, cy ); CSplitterWnd::OnSize( nType, cx, cy ); } --- Kostya Sebov. ---------------------------------------------------------------------------- Tel: (38 044) 266-6387 | Fax: (38 044) 266-6195 | E-mail: sebov@is.kiev.ua
| Вернуться в корень Архива |