// LayoutPanel.cpp: implementation of the CLayoutPanel class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "LayoutPanel.h" #include "LayoutSplit.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction // Yangzj 2003.09.13 23:35 ////////////////////////////////////////////////////////////////////// namespace DynamicLayout { CLayoutPanel::CLayoutPanel( CWnd* wndOwner,Layout t,Layout b,Layout l,Layout r ) : CLayoutBase( wndOwner,t,b,l,r ),m_bShowBorder(TRUE),m_rectLast(0,0,0,0) { m_dwBKColor = 1; m_pSplit = NULL; } CLayoutPanel::~CLayoutPanel() { Clear(); } void CLayoutPanel::GetRect(CRect& rect) { if( m_cWndRect.IsRectNull() ) UpdateLayout(); rect = m_cWndRect; } //计算布局矩形区 void CLayoutPanel::UpdateLayout() { CRect rect; CLayoutBase* pLayout; POSITION pos = m_list_Layout.GetHeadPosition(); m_cWndRect.SetRectEmpty(); while( pos != NULL ) { pLayout = m_list_Layout.GetNext(pos); pLayout->UpdateLayout(); pLayout->GetRect( rect ); if( pLayout->IsPanel() ) RectLess( rect ); if( m_cWndRect.left <1 || rect.left < m_cWndRect.left ) m_cWndRect.left = rect.left; if( m_cWndRect.top < 1 || rect.top < m_cWndRect.top ) m_cWndRect.top = rect.top; if( rect.right > m_cWndRect.right ) m_cWndRect.right = rect.right; if( rect.bottom > m_cWndRect.bottom ) m_cWndRect.bottom = rect.bottom; } RectMore( m_cWndRect ); } //设置Panal的大小(关键) //针对每一个子项,依据Layout属性,改变大小、位置; void CLayoutPanel::SetRect( CRect& rect ) { if( rect.right < rect.left || rect.bottom < rect.top ) m_bShoudInvaldeMainWnd = TRUE; CRect subRect; CLayoutBase *pLayout; POSITION pos = m_list_Layout.GetHeadPosition(); while( pos != NULL ) { pLayout = m_list_Layout.GetNext(pos); //得到子布局 pLayout->GetRect(subRect); //获取子布局的原矩形区 GetSubRect( pLayout, subRect, rect ); //计算新矩形区 pLayout->SetRect( subRect ); //设置新矩形区 if( pLayout->IsPanel() && pLayout->NeedInvalidate() ) { m_bShoudInvaldeMainWnd = TRUE; } } m_cWndRect = rect; } //依照新矩形区,得到某子布局的矩形区 void CLayoutPanel::GetSubRect( CLayoutBase* pLayout, CRect& subRect, const CRect& rect ) { subRect.top = (pLayout->m_eTop )?(rect.top +(subRect.top -m_cWndRect.top )):(rect.bottom-(m_cWndRect.bottom-subRect.top )); subRect.bottom = (pLayout->m_eBottom)?(rect.bottom-(m_cWndRect.bottom-subRect.bottom )):(rect.top +(subRect.bottom -m_cWndRect.top )); subRect.left = (pLayout->m_eLeft )?(rect.left +(subRect.left -m_cWndRect.left)):(rect.right -(m_cWndRect.right -subRect.left )); subRect.right = (pLayout->m_eRight )?(rect.right -(m_cWndRect.right -subRect.right )):(rect.left +(subRect.right -m_cWndRect.left)); } void CLayoutPanel::Clear() { POSITION pos = m_list_Layout.GetHeadPosition(); while( pos != NULL ) { delete m_list_Layout.GetNext(pos); } m_list_Layout.RemoveAll(); ClearSplit(); CLayoutBase::Clear(); } void CLayoutPanel::Draw( ) { UnDrawLast(); if( m_bVisible && m_bShowBorder && m_cWndRect.left < m_cWndRect.right && m_cWndRect.top < m_cWndRect.bottom ) { CDC* pDC = m_wndOwner->GetDC(); if( m_dwBKColor != 1 )//绘制背景色 { CRgn rgn; GetRgn( m_cWndRect, rgn, FALSE ); CBrush brush; brush.CreateSolidBrush( m_dwBKColor ); pDC->FillRgn( &rgn, &brush ); } pDC->Draw3dRect( m_cWndRect,RGB(255,255,255),RGB(64,64,64) ); m_rectLast = m_cWndRect; m_wndOwner->ReleaseDC(pDC); } POSITION pos = m_list_Layout.GetHeadPosition(); while( pos != NULL ) { m_list_Layout.GetNext(pos)->Draw(); } } void CLayoutPanel::UnDrawLast() { if( m_rectLast.IsRectEmpty() ) return; if( m_bVisible && m_bShowBorder &&(m_rectLast==m_cWndRect) ) return; CRgn panelRgn; GetRgn( m_rectLast, panelRgn, TRUE ); m_wndOwner->InvalidateRgn(&panelRgn); m_rectLast.SetRectEmpty(); } //设置是否可见 void CLayoutPanel::Show( BOOL bShow/*=TRUE*/ ) { m_bVisible = bShow; POSITION pos = m_list_Layout.GetHeadPosition(); while( pos != NULL ) { m_list_Layout.GetNext(pos)->Show( bShow ); } } //设置是否改变边框 void CLayoutPanel::ShowBorder( BOOL bShow/*=FALSE*/ ) { m_bShowBorder = bShow; POSITION pos = m_list_Layout.GetHeadPosition(); while( pos != NULL ) { m_list_Layout.GetNext(pos)->ShowBorder( bShow ); } } void CLayoutPanel::Invalidate() { CRgn rgn; GetRgn( m_rectLast, rgn, FALSE ); m_wndOwner->InvalidateRgn( &rgn ); } // // 得到布局未被子布局覆盖的区域 // Yangzj 2007.10.28 void CLayoutPanel::GetRgn( CRect& rect, CRgn& rgn, BOOL bWithBorder/*=FALSE*/ ) { CRect rectTemp( rect ); if( !bWithBorder ) RectLess( rectTemp ); rgn.CreateRectRgnIndirect( rectTemp ); //去除子布局所占的矩形区 CLayoutBase* pLayout; POSITION pos = m_list_Layout.GetHeadPosition(); while( pos != NULL ) { pLayout = m_list_Layout.GetNext( pos ); if( !pLayout->IsVisible() ) continue; pLayout->GetRect( rectTemp ); if( rectTemp.left > rect.right || rectTemp.top > rect.bottom ) continue; CRgn rgnTemp; rgnTemp.CreateRectRgnIndirect( rectTemp ); rgn.CombineRgn( &rgn, &rgnTemp, RGN_DIFF ); } } // //判断本Panel能否添加分割条; //条件是: //1. 有且仅有两个子布局; //2. 它们之间不相交; //3. 对应边绑定方式要相反 BOOL CLayoutPanel::CanSplit() { //条件1 if( m_list_Layout.GetCount() != 2 ) return FALSE; // if( !m_list_Layout.GetHead()->IsPanel() ) return FALSE; // if( !m_list_Layout.GetTail()->IsPanel() ) return FALSE; //条件2 UpdateLayout(); CRect rect1, rect2; CLayoutBase* pPanel1= m_list_Layout.GetHead(); pPanel1->GetRect( rect1 ); CLayoutBase* pPanel2 = m_list_Layout.GetTail(); pPanel2->GetRect( rect2 ); if( rect1.PtInRect( CPoint(rect2.left,rect2.top )) || rect1.PtInRect( CPoint(rect2.right,rect2.top )) || rect1.PtInRect( CPoint(rect2.left,rect2.bottom )) || rect1.PtInRect( CPoint(rect2.right,rect2.bottom)) ) return FALSE;//矩形相交 //条件3 if( rect1.right < rect2.left && pPanel1->m_eRight == pPanel2->m_eLeft ) return FALSE; if( rect1.left > rect2.right && pPanel1->m_eLeft == pPanel2->m_eRight ) return FALSE; if( rect1.top > rect2.bottom && pPanel1->m_eTop == pPanel2->m_eBottom) return FALSE; if( rect1.bottom< rect2.top && pPanel1->m_eBottom== pPanel2->m_eTop ) return FALSE; //通过考验 return TRUE; } //如果本Panel CanSplit生产一个Split返回 //否则返回NULL CLayoutSplit* CLayoutPanel::GetSplit() { if( !CanSplit() ) return NULL; if( m_pSplit != NULL ) return m_pSplit; CRect rect1, rect2; CLayoutBase* pPanel1= m_list_Layout.GetHead(); pPanel1->GetRect( rect1 ); CLayoutBase* pPanel2 = m_list_Layout.GetTail(); pPanel2->GetRect( rect2 ); CLayoutSplit* pSplit = new CLayoutSplit( m_wndOwner, m_dwBKColor ); if( rect1.right < rect2.left ) { if( pPanel1->m_eRight != LAYOUT_LOCK ) { pSplit->SetPanelAdhere( pPanel1, BORDER_RIGHT ); pSplit->SetPanelSizing( pPanel2 ); } else { pSplit->SetPanelAdhere( pPanel2, BORDER_LEFT ); pSplit->SetPanelSizing( pPanel1 ); } } else if( rect1.left > rect2.right ) { if( pPanel1->m_eLeft != LAYOUT_LOCK ) { pSplit->SetPanelAdhere( pPanel1, BORDER_LEFT ); pSplit->SetPanelSizing( pPanel2 ); } else { pSplit->SetPanelAdhere( pPanel2, BORDER_RIGHT ); pSplit->SetPanelSizing( pPanel1 ); } } else if( rect1.top > rect2.bottom ) { if( pPanel1->m_eTop != LAYOUT_LOCK ) { pSplit->SetPanelAdhere( pPanel1, BORDER_TOP ); pSplit->SetPanelSizing( pPanel2 ); } else { pSplit->SetPanelAdhere( pPanel2, BORDER_BOTTOM); pSplit->SetPanelSizing( pPanel1 ); } } else if( rect1.bottom< rect2.top ) { if( pPanel1->m_eBottom != LAYOUT_LOCK ) { pSplit->SetPanelAdhere( pPanel1, BORDER_BOTTOM ); pSplit->SetPanelSizing( pPanel2 ); } else { pSplit->SetPanelAdhere( pPanel2, BORDER_TOP ); pSplit->SetPanelSizing( pPanel1 ); } } else { LAYOUT_ASSERT(false,_T("[逻辑错误] 逻辑错误!")); } return pSplit; } void CLayoutPanel::ClearSplit() { delete m_pSplit; m_pSplit = NULL; } }