// DynamicLayoutExport.cpp: implementation of the CDynamicLayout class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "DynamicLayoutExport.h" #include "LayoutControl.h" #include "LayoutPanelFrame.h" #include "LayoutSplit.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #ifndef GET_X_LPARAM #define GET_X_LPARAM(lp) (int)(short)(LOWORD(lp)) #define GET_Y_LPARAM(lp) (int)(short)(HIWORD(lp)) #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// namespace DynamicLayout { //初始化默认值 CDynamicLayout::CDynamicLayout():m_wndOwner(NULL),m_pMainPanel(NULL) { m_szMin = 0; m_szMax = 0; } CDynamicLayout::~CDynamicLayout() { if( m_pMainPanel != NULL ) delete m_pMainPanel; } //初始化状态值 void CDynamicLayout::InitLayout(CWnd* pOwner) { LAYOUT_ASSERT( pOwner != NULL,_T("为CDynamicLayout类对象指定的拥有者pOwner不能为空!") ); LAYOUT_ASSERT( pOwner->IsKindOf(RUNTIME_CLASS(CWnd)),_T("为CDynamicLayout类对象指定的拥有者pOwner必须为CWnd或其派生类!")); if( !pOwner->IsKindOf(RUNTIME_CLASS(CWnd)) ) return; m_wndOwner = pOwner; if( m_pMainPanel != NULL ) delete m_pMainPanel; m_pMainPanel = new CLayoutPanelFrame(pOwner,LAYOUT_LOCK,LAYOUT_LOCK,LAYOUT_LOCK,LAYOUT_LOCK); m_mapPanel.SetAt( _T(""),m_pMainPanel ); CRect rect; pOwner->GetClientRect( rect ); m_pMainPanel->SetRect( rect ); } void CDynamicLayout::SetDialogMinSize( int cx, int cy ) { LAYOUT_ASSERT( cx >0 && cy > 0,_T("指定对话框的最小大小,数值无效。") ); m_szMin.cx = cx; m_szMin.cy = cy; if( m_szMin.cx > m_szMax.cx ) m_szMax.cx = m_szMin.cx; if( m_szMin.cy > m_szMin.cy ) m_szMax.cy = m_szMin.cy; } void CDynamicLayout::SetDialogMaxSize(int cx, int cy) { LAYOUT_ASSERT( cx >0 && cy >0, _T("指定对话框的最大大小,数值无效。") ); m_szMax.cx = cx; m_szMax.cy = cy; if( m_szMin.cx > m_szMax.cx ) m_szMax.cx = m_szMin.cx; if( m_szMin.cy > m_szMin.cy ) m_szMax.cy = m_szMin.cy; } //获取名称对应的Panel CLayoutPanel* CDynamicLayout::GetPanel( Panel Name ) { LAYOUT_ASSERT( m_pMainPanel != NULL,_T("[致命错误]调用CDynamicLayout其它成员之前,请先调用InitLayout(this)!") ); CLayoutPanel* pPanel = NULL; m_mapPanel.Lookup(Name,(void*&)pPanel); LAYOUT_ASSERT( pPanel != NULL,_T("[致命错误] 指定的Panel[")+Name+_T("]不存在!")); return pPanel; } //在指定的Panel下添加一个Panel void CDynamicLayout::AddPanel(Panel Name,Panel Owner/* =_T("") */,Layout top/* =LAYOUT_LOCK */,Layout bottom/* =LAYOUT_UNLOCK */,Layout left/* =LAYOUT_LOCK */,Layout right/* =LAYOUT_UNLOCK */) { LAYOUT_ASSERT( !Name.IsEmpty(),_T("[严重错误]添加Panal时,名称不能为空!") ); LAYOUT_ASSERT( m_pMainPanel != NULL,_T("[致命错误]添加布局之前,请调用InitLayout(pOwner)!") ); CLayoutPanel* pPanal = NULL; if( !m_mapPanel.Lookup(Name,(void*&)pPanal) ) { pPanal = new CLayoutPanel(m_wndOwner,top,bottom,left,right); GetPanel( Owner )->AddLayout( pPanal ); m_mapPanel.SetAt( Name, pPanal ); }else{ LAYOUT_ASSERT( false,_T("新添加的Panal[")+Name+_T("],该名称已存在!") ); } } //添加控件(ID)到指定的Panel void CDynamicLayout::AddControl( UINT nID, Panel Owner/*=_T("")*/,Layout top/*=LAYOUT_LOCK*/,Layout bottom/*=LAYOUT_UNLOCK*/,Layout left/*=LAYOUT_LOCK*/,Layout right/*=LAYOUT_UNLOCK*/ ) { LAYOUT_ASSERT( m_pMainPanel != NULL,_T("添加控件布局之前,请调用InitLayout(pOwner)!")); CWnd* pCtrl = m_wndOwner->GetDlgItem(nID); LAYOUT_ASSERT( pCtrl!=NULL,_T("[致命错误]添加控件布局时,指定的ID无效")); AddControl( pCtrl, Owner, top, bottom, left, right ); } //添加控件(窗口指针)到指定Panel void CDynamicLayout::AddControl( CWnd* pCtrl,Panel Owner/*=_T("")*/,Layout top/*=LAYOUT_LOCK*/,Layout bottom/*=LAYOUT_UNLOCK*/,Layout left/*=LAYOUT_LOCK*/,Layout right/*=LAYOUT_UNLOCK*/ ) { CLayoutControl* pControl = new CLayoutControl(m_wndOwner,pCtrl,top,bottom,left,right); GetPanel( Owner )->AddLayout( pControl ); } void CDynamicLayout::UpdateLayout() { LAYOUT_ASSERT( m_pMainPanel != NULL,_T("[致命错误]调用CDynamicLayout::UpdateLayout()之前,请先调用CDynamicLayout::InitLayout(pOwner)!")); m_pMainPanel->UpdateLayout(); } LRESULT CDynamicLayout::FilterDynamicLayoutMessage( UINT& message, WPARAM& wParam, LPARAM& lParam ) { if( m_wndOwner == NULL || m_pMainPanel == NULL ) return FALSE; switch( message ) { case WM_PAINT: OnPaint(); break; case WM_SIZE: { if( wParam == SIZE_MAXSHOW ) { OnPaint(); } else if( wParam != SIZE_MINIMIZED ) { CRect rect(CPoint(0,0),CSize((DWORD)lParam)); m_pMainPanel->SetRect( rect ); if( m_pMainPanel->NeedInvalidate() ) m_wndOwner->Invalidate(); OnPaint(); } break; } case WM_SIZING: { RECT* pRect = (RECT*)lParam; if( m_szMin.cx > 0 && pRect->right-pRect->left < m_szMin.cx ) pRect->right = pRect->left + m_szMin.cx; if( m_szMin.cy > 0 && pRect->bottom - pRect->top < m_szMin.cy ) pRect->bottom = pRect->top + m_szMin.cy; if( m_szMax.cx > 0 && pRect->right - pRect->left > m_szMax.cx ) pRect->right = pRect->left + m_szMax.cx; if( m_szMax.cy > 0 && pRect->bottom - pRect->top > m_szMax.cy ) pRect->bottom = pRect->top + m_szMax.cy; break; } case WM_LBUTTONDOWN: OnLButtonDown( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) ); break; case WM_MOUSEMOVE: { OnMouseMove( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) ); break; } case WM_LBUTTONUP: { OnLButtonUp( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) ); break; } default: break; } return FALSE; } void CDynamicLayout::OnLButtonDown(int x, int y) { CLayoutPanel* pPanel; CLayoutSplit* pSplit; POSITION pos = m_mapSplit.GetStartPosition(); while( pos != NULL ) { m_mapSplit.GetNextAssoc(pos,(void*&)pPanel,(void*&)pSplit ); if( pSplit->OnLButtonDown(x,y) ) break; } } void CDynamicLayout::OnLButtonUp(int x, int y) { CLayoutPanel* pPanel; CLayoutSplit* pSplit; POSITION pos = m_mapSplit.GetStartPosition(); while( pos != NULL ) { m_mapSplit.GetNextAssoc(pos,(void*&)pPanel,(void*&)pSplit ); if( pSplit->OnLButtonUp(x,y) ) { AfxBeginThread(WhenEndSplit,this);//跳出当前线程,刷新界面显示 break; } } } void CDynamicLayout::OnMouseMove(int x, int y ) { CLayoutPanel* pPanel; CLayoutSplit* pSplit; POSITION pos = m_mapSplit.GetStartPosition(); while( pos != NULL ) { m_mapSplit.GetNextAssoc(pos,(void*&)pPanel,(void*&)pSplit ); if( pSplit->OnMouseMove(x,y) ) break; } } //显示/隐藏布局包括子布局 void CDynamicLayout::ShowLayout(Panel Name /* = _T("")*/,BOOL bShow /* = FALSE */) { GetPanel( Name )->Show( bShow ); m_wndOwner->Invalidate(FALSE); } //显示/不显示Panel void CDynamicLayout::ShowPanel(Panel Name/* =_T */,BOOL bShow /* = FALSE */) { GetPanel( Name )->ShowBorder( bShow ); m_wndOwner->Invalidate(FALSE); } void CDynamicLayout::OnPaint() { LAYOUT_ASSERT( m_pMainPanel != NULL,_T("[致命错误]未调用InitLayout(this)!") ); m_pMainPanel->Draw( ); } void CDynamicLayout::SetBkColor( Panel Name/*=_T("")*/,COLORREF dwColor/*=1*/ ) { GetPanel( Name )->SetBkColor( dwColor ); m_wndOwner->Invalidate(FALSE); } //设置/取消分割条 void CDynamicLayout::SetSplit( Panel Name, BOOL bAdd /*= TRUE */ ) { CLayoutPanel* pPanel = GetPanel( Name ); if( bAdd ) { CLayoutSplit* pSplit = pPanel->GetSplit(); if( pSplit != NULL ) { m_mapSplit.SetAt( pPanel, pSplit ); }else{ LAYOUT_ASSERT( pSplit != NULL, _T("Panel[")+Name+("]不符合分割条件,设置Split失败!") ); } }else{ pPanel->ClearSplit(); } } //是否已存在命名为Name的Panel BOOL CDynamicLayout::IsPanelExist( Panel Name ) { void* pTemp; return m_mapPanel.Lookup( Name, pTemp ); } UINT CDynamicLayout::WhenEndSplit( LPVOID lParam ) { CDynamicLayout* pThis = (CDynamicLayout*)lParam; Sleep(1); pThis->m_wndOwner->Invalidate(); Sleep(1); pThis->m_pMainPanel->Draw(); return 0; } }