www.pudn.com > AccessADO.rar > CoolControlBar.cpp


/*######################################################################## 
	Filename: 	CoolControlbar.cpp 
	---------------------------------------------------- 
	Remarks:	... 
	---------------------------------------------------- 
	Author:		成真 
	Email:		anyou@sina.com 
				anyou@msn.com 
	Created:	7/3/2003 21:52 
  ########################################################################*/ 
#include "stdafx.h" 
#include "resource.h" 
#include "CoolControlBar.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
CCoolBarArray CCoolControlBar::m_arrBars;  
 
/*######################################################################## 
			  ------------------------------------------------ 
								  class CCoolControlBar 
			  ------------------------------------------------ 
  ########################################################################*/ 
 
CCoolControlBar::CCoolControlBar() 
{ 
	m_bTracking = FALSE; 
	m_bParentSizing = FALSE; 
} 
 
CCoolControlBar::~CCoolControlBar() 
{ 
 
} 
 
BOOL CCoolControlBar::Create(CWnd *pParentWnd, CSize size, UINT dwStyle, UINT uID) 
{ 
	ASSERT_VALID(pParentWnd); 
	ASSERT( (dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_TOP    || 
			(dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_BOTTOM || 
			(dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_LEFT   || 
			(dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_RIGHT); 
	 
    ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC))); 
	 
	m_dwStyle = (dwStyle & CBRS_ALL); 
	// keep only the generic window styles-------------- 
	dwStyle &= ~CBRS_ALL; 
	// force WS_CLIPSIBLINGS (otherwise will cause repaint problems)--- 
	dwStyle |= WS_CLIPSIBLINGS; 
	 
	BOOL bRets = CControlBar::Create(NULL, NULL, dwStyle,  
		CRect(0, 0, 0, 0), pParentWnd, uID, NULL); 
	if (bRets) 
	{ 
		m_szDefault = size;     
		m_szHorz	= size; 
		m_szVert	= size; 
		m_szFloat   = size; 
		 
		// force the size to zero - resizing bar will occur later---------- 
		SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); 
	} 
	return bRets; 
} 
 
BOOL CCoolControlBar::DestroyWindow()  
{ 
    int nPos = FindCoolBar(this); 
    ASSERT(nPos >= 0); 
    m_arrBars.RemoveAt(nPos); 
	 
	return CControlBar::DestroyWindow(); 
} 
 
CSize CCoolControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz) 
{ 
	if (bStretch)  
	{ 
		return CSize(bHorz ? 32767 : m_szVert.cx, bHorz ? m_szHorz.cy : 32767); 
	} 
	else 
	{ 
		// dirty cast - using CCoolDockBar to access protected CDockBar members 
		CFriendDockBar* pDockBar = (CFriendDockBar*)m_pDockBar; 
		if (pDockBar != NULL) 
		{ 
			// force imediate RecalcDelayShow() for all sizing bars on the row 
			// with delayShow/delayHide flags set to avoid IsVisible() problems 
			CCoolBarArray arrCoolBars; 
			GetCoolBars(arrCoolBars); 
			AFX_SIZEPARENTPARAMS layout; 
			layout.hDWP = pDockBar->m_bLayoutQuery ? NULL  
				: ::BeginDeferWindowPos(arrCoolBars.GetSize()); 
			for (int i = 0; i < arrCoolBars.GetSize(); i++) 
			{ 
				arrCoolBars[i]->RecalcDelayShow(&layout); 
			} 
			 
			if (layout.hDWP != NULL) 
			{ 
				::EndDeferWindowPos(layout.hDWP); 
			} 
			if (IsVisible() && !IsFloating() && m_bParentSizing && arrCoolBars[0] == this) 
			{ 
				m_bParentSizing = FALSE; 
 
				CRect rc = pDockBar->m_rectLayout; 
				if (rc.IsRectEmpty()) 
				{ 
					m_pDockSite->GetClientRect(&rc); 
				} 
				 
				int nLengthAvail = bHorz ? rc.Width() + 2 : rc.Height(); 
				if (AutoSize(nLengthAvail, bHorz)) 
				{ 
					AutoAlign(); 
				} 
			} 
		} 
		return bHorz ? m_szHorz : m_szVert; 
	} 
} 
 
CSize CCoolControlBar::CalcDynamicLayout(int nLength, DWORD dwMode) 
{ 
	if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ? 
    { 
		if (nLength == -1) m_bParentSizing = TRUE; 
        return CControlBar::CalcDynamicLayout(nLength, dwMode); 
    } 
 
    if (dwMode & LM_MRUWIDTH) return m_szFloat; 
    if (dwMode & LM_COMMIT)   return m_szFloat; // already committed 
 
    ((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength; 
 
    m_szFloat.cx = max(m_szFloat.cx, m_szDefault.cx); 
    m_szFloat.cy = max(m_szFloat.cy, m_szDefault.cy); 
 
   return m_szFloat; 
} 
 
IMPLEMENT_DYNAMIC(CCoolControlBar, CControlBar); 
 
/*######################################################################## 
			  ------------------------------------------------ 
								Message handlers 
			  ------------------------------------------------ 
  ########################################################################*/ 
 
BEGIN_MESSAGE_MAP(CCoolControlBar, CControlBar) 
//{{AFX_MSG_MAP(CCoolControlBar) 
	ON_WM_NCCALCSIZE() 
	ON_WM_NCPAINT() 
	ON_WM_ERASEBKGND() 
	ON_WM_NCLBUTTONDOWN() 
	ON_WM_WINDOWPOSCHANGING() 
	ON_WM_NCHITTEST() 
	ON_WM_MOUSEMOVE() 
	ON_WM_LBUTTONUP() 
	ON_WM_CREATE() 
	ON_WM_PAINT() 
	ON_WM_NCLBUTTONUP() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
int CCoolControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
    m_arrBars.Add(this); 
	if (CControlBar::OnCreate(lpCreateStruct) == -1) 
	{ 
		return -1; 
	} 
	return 0; 
} 
 
void CCoolControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)  
{ 
	// force non-client recalc if moved or resized 
    lpwndpos->flags |= SWP_FRAMECHANGED; 
	CControlBar::OnWindowPosChanging(lpwndpos); 
} 
 
void CCoolControlBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)  
{ 
	CRect rect = lpncsp->rgrc[0]; 
 
	BOOL bALignLeft   = (m_dwStyle & CBRS_ALIGN_LEFT  ); 
	BOOL bALignRight  = (m_dwStyle & CBRS_ALIGN_RIGHT ); 
	BOOL bALignTop    = (m_dwStyle & CBRS_ALIGN_TOP   ); 
	BOOL bALignBottom = (m_dwStyle & CBRS_ALIGN_BOTTOM); 
 
	if ((m_dwStyle & CBRS_FLOATING) != CBRS_FLOATING) 
	{ 
		if (m_pDockBar != NULL) 
		{ 
			rect.DeflateRect(5, 5); 
		} 
		else 
		{ 
			if (bALignLeft) rect.DeflateRect(1, 1, 3, 0); 
			else if (bALignRight) rect.DeflateRect(3, 0, 1, 0); 
			else if (bALignTop) rect.DeflateRect(0, 0, 0, 3); 
			else rect.DeflateRect(0, 3, 0, 0); 
		} 
 
		if (m_dwStyle & CBRS_TITLEBAR) 
		{ 
			(IsHorizontal() ? rect.left : rect.top) += 16; 
		} 
	} 
 
    lpncsp->rgrc[0] = rect;	 
} 
 
void CCoolControlBar::OnNcPaint()  
{ 
    CWindowDC dc(this); 
	dc.SetBkMode(TRANSPARENT); 
	 
    CRect rcClient, rcWindow; 
    GetWindowRect(&rcWindow); 
    GetClientRect(&rcClient); 
	ClientToScreen(&rcClient); 
    rcClient.OffsetRect(-rcWindow.TopLeft()); 
    rcWindow.OffsetRect(-rcWindow.TopLeft()); 
 
	//填充背景----------------------------------------- 
	if (rcClient.bottom > rcClient.top && rcClient.right > rcClient.left) 
	{ 
		 dc.ExcludeClipRect(rcClient); 
	} 
	dc.FillSolidRect(rcWindow, ::GetSysColor(COLOR_3DFACE)); 
	 
	//绘制边框----------------------------------------- 
	if (m_pDockBar != NULL) 
	{ 
		dc.Draw3dRect(rcWindow, RGB(128, 128, 128), RGB(255, 255, 255)); 
		rcWindow.DeflateRect(1, 1); 
		dc.Draw3dRect(rcWindow, RGB(255, 255, 255), RGB(128, 128, 128)); 
	} 
	 
	//绘制标题栏--------------------------------------- 
	if (m_dwStyle & CBRS_TITLEBAR) 
	{ 
		CRect rcTitleBar(rcWindow); 
		if (IsHorizontal()) 
		{ 
			rcTitleBar.right = rcTitleBar.left + 19; 
			rcTitleBar.DeflateRect(0, 4); 
			if (m_pDockBar == NULL) 
			{ 
				rcTitleBar.OffsetRect(-2, 0); 
			} 
 
			m_rcCloseButton.right = rcTitleBar.right - 1; 
			m_rcCloseButton.top   = rcTitleBar.top + 1; 
		} 
		else 
		{ 
			rcTitleBar.bottom = rcTitleBar.top + 19; 
			rcTitleBar.DeflateRect(4, 0); 
			if (m_pDockBar == NULL) 
			{ 
				rcTitleBar.OffsetRect(0, -2); 
			} 
			m_rcCloseButton.right = rcTitleBar.right - 1; 
			m_rcCloseButton.top   = rcTitleBar.top + 4; 
		} 
		m_rcCloseButton.left = m_rcCloseButton.right - 12; 
		m_rcCloseButton.bottom = m_rcCloseButton.top + 12; 
 
		DrawTitleBar(&dc, rcTitleBar, IsHorizontal()); 
		DrawCloseButton(&dc, m_dwButtonState); 
	} 
	 
	ReleaseDC(&dc); 
} 
 
void CCoolControlBar::OnPaint()  
{ 
	CPaintDC dc(this);  
} 
 
BOOL CCoolControlBar::OnEraseBkgnd(CDC* pDC)  
{ 
	CRect rect; 
	GetClientRect(&rect); 
	pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE)); 
	return CControlBar::OnEraseBkgnd(pDC); 
} 
 
UINT CCoolControlBar::OnNcHitTest(CPoint point)  
{ 
	if (IsFloating()) 
	{ 
		return CControlBar::OnNcHitTest(point); 
	} 
 
    CRect rcWindow, rcTrack; 
    GetWindowRect(rcWindow); 
 
	if (m_dwStyle & CBRS_TITLEBAR) 
	{ 
		CRect rc(m_rcCloseButton); 
		rc.OffsetRect(rcWindow.TopLeft()); 
		if (rc.PtInRect(point)) 
		{ 
			return HTCLOSE; 
		} 
	} 
	 
	for (int i = 0; i < 4; i++) 
	{ 
		if (GetTrackRect(rcTrack, i) && rcTrack.PtInRect(point))  
		{ 
			switch (i)  
			{ 
				case 0:  return HTLEFT;	  break; 
				case 1:  return HTTOP; 	  break; 
				case 2:  return HTRIGHT;  break; 
				case 3:  return HTBOTTOM; break; 
			} 
		} 
	} 
	 
	return HTCLIENT;  
} 
 
void CCoolControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point)  
{ 
	if (IsFloating()) 
	{ 
		CControlBar::OnNcLButtonDown(nHitTest, point); 
		return; 
	} 
	 
	if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST)) 
	{ 
		SetCapture(); 
		m_bTracking  = TRUE; 
		m_bTrackType = nHitTest; 
		m_oldPoint   = point; 
	} 
} 
 
void CCoolControlBar::OnNcLButtonUp(UINT nHitTest, CPoint point)  
{ 
	if (nHitTest == HTCLOSE) 
	{ 
		GetParentFrame()->ShowControlBar(this, FALSE, FALSE); 
		return; 
	}	 
	CControlBar::OnNcLButtonUp(nHitTest, point); 
} 
 
void CCoolControlBar::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	if (m_bTracking) 
	{ 
		ClientToScreen(&point); 
		UpdateWndSize(point); 
	} 
	CControlBar::OnMouseMove(nFlags, point); 
} 
 
void CCoolControlBar::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	ReleaseCapture(); 
	if (m_bTracking) 
	{ 
		m_bTracking = FALSE; 
		return; 
	} 
	CControlBar::OnLButtonUp(nFlags, point); 
} 
 
void CCoolControlBar::OnUpdateCmdUI(CFrameWnd *pTarget, BOOL bDisableIfNoHndler) 
{ 
	CPoint point; 
    ::GetCursorPos(&point); 
	CRect rcWindow; 
	GetWindowRect(&rcWindow); 
	point = point - rcWindow.TopLeft(); 
 
	DWORD dwoldState = m_dwButtonState; 
	m_dwButtonState = m_rcCloseButton.PtInRect(point) ? 
				((::GetKeyState(VK_LBUTTON) < 0) ? 2 : 1) : 0; 
	// if need paint--------------------------------------- 
    if (dwoldState != m_dwButtonState) 
	{ 
        SendMessage(WM_NCPAINT); 
	}	 
} 
 
/*######################################################################## 
			  ------------------------------------------------ 
						 
			  ------------------------------------------------ 
  ########################################################################*/ 
 
BOOL CCoolControlBar::GetTrackRect(CRect& rcTrack, int nEdge) 
{ 
	CRect rcWindow; 
    GetWindowRect(rcWindow); 
    rcTrack = rcWindow; 
	 
	BOOL bAtStart = TRUE; 
	BOOL bAtEnd   = TRUE; 
 
	if (m_pDockBar != NULL) 
	{ 
		CCoolBarArray arrCoolBars; 
		GetCoolBars  (arrCoolBars); 
		bAtStart  =  (arrCoolBars[0] == this); 
		bAtEnd    =  (arrCoolBars[arrCoolBars.GetSize() - 1] == this); 
	} 
 
	BOOL bALignLeft   = (m_dwStyle & CBRS_ALIGN_LEFT  ); 
	BOOL bALignRight  = (m_dwStyle & CBRS_ALIGN_RIGHT ); 
	BOOL bALignTop    = (m_dwStyle & CBRS_ALIGN_TOP   ); 
	BOOL bALignBottom = (m_dwStyle & CBRS_ALIGN_BOTTOM); 
	 
    BOOL bHorz = IsHorizontal(); 
	 
    switch (nEdge) 
    { 
	case 0: 
		{ 
			if (!bALignRight) return FALSE; 
			rcTrack.right = rcTrack.left + SIZING_WIDTH; 
		} 
		break; 
	case 1: 
		{ 
			if (!bALignBottom) return FALSE; 
			rcTrack.bottom = rcTrack.top + SIZING_WIDTH; 
		} 
		break; 
	case 2: 
		{ 
			if (bALignRight || (bAtEnd && (bALignTop || bALignBottom))) return FALSE; 
			rcTrack.left = rcTrack.right - SIZING_WIDTH; 
		} 
		break; 
	case 3: 
		{ 
			if (bALignBottom || (bAtEnd && (bALignLeft || bALignRight))) return FALSE; 
			rcTrack.top = rcTrack.bottom - SIZING_WIDTH; 
		} 
		break; 
    default: 
        ASSERT(FALSE); // invalid hit test code 
    } 
    return TRUE; 
} 
 
void CCoolControlBar::UpdateWndSize(CPoint point) 
{ 
	ASSERT(m_bTracking); 
	if (!m_bTracking) return; 
	BOOL bHorz = IsHorizontal(); 
	 
	CSize szOld = (bHorz ? m_szHorz : m_szVert); 
	CSize szNew = szOld; 
 
	//仅在控制栏所在的行内改变大小-------------------------- 
	if ((m_bTrackType == HTRIGHT && bHorz) || (m_bTrackType == HTBOTTOM && !bHorz)) 
	{ 
		CCoolBarArray arrCoolBars; 
		GetCoolBars(arrCoolBars); 
		//取得与它相邻的下一条控制条的指针------------------ 
		for (int i = 0; i < arrCoolBars.GetSize(); i++) 
		{ 
			if (arrCoolBars.GetAt(i) == this) break; 
		} 
		CCoolControlBar *pCoolBar = arrCoolBars.GetAt(i + 1); 
 
		if (bHorz) 
		{ 
			if ((m_szHorz.cx == TITLE_HEIGHT && (point.x < m_oldPoint.x)) 
				|| (pCoolBar->m_szHorz.cx == TITLE_HEIGHT && (point.x > m_oldPoint.x)))  
			{ 
				return; 
			} 
			m_szHorz.cx += (point.x - m_oldPoint.x); 
			pCoolBar->m_szHorz.cx -= (point.x - m_oldPoint.x); 
			 
			if (m_szHorz.cx < TITLE_HEIGHT) 
			{ 
				pCoolBar->m_szHorz.cx += m_szHorz.cx - TITLE_HEIGHT; 
				m_szHorz.cx = TITLE_HEIGHT; 
			} 
			else if (pCoolBar->m_szHorz.cx < TITLE_HEIGHT) 
			{ 
				m_szHorz.cx -= TITLE_HEIGHT - pCoolBar->m_szHorz.cx; 
				pCoolBar->m_szHorz.cx = TITLE_HEIGHT; 
			} 
			AutoAlign(); 
		} 
		else 
		{ 
			if ((m_szVert.cy == TITLE_HEIGHT && (point.y < m_oldPoint.y)) 
			 || (pCoolBar->m_szVert.cy == TITLE_HEIGHT && (point.y > m_oldPoint.y)))  
			{ 
				return; 
			} 
			m_szVert.cy += (point.y - m_oldPoint.y); 
			pCoolBar->m_szVert.cy -= (point.y - m_oldPoint.y); 
			 
			if (m_szVert.cy < TITLE_HEIGHT) 
			{ 
				pCoolBar->m_szVert.cy += m_szVert.cy - TITLE_HEIGHT; 
				m_szVert.cy = TITLE_HEIGHT; 
			} 
			else if (pCoolBar->m_szVert.cy < TITLE_HEIGHT) 
			{ 
				m_szVert.cy -= TITLE_HEIGHT - pCoolBar->m_szVert.cy; 
				pCoolBar->m_szVert.cy = TITLE_HEIGHT; 
			} 
			AutoAlign(); 
		} 
 
		m_oldPoint = point; 
		return; 
	} 
 
	switch (m_bTrackType)  
	{ 
		case HTLEFT:   szNew.cx -= (point.x - m_oldPoint.x); break; 
		case HTRIGHT:  szNew.cx += (point.x - m_oldPoint.x); break; 
		case HTTOP:	   szNew.cy -= (point.y - m_oldPoint.y); break; 
		case HTBOTTOM: szNew.cy += (point.y - m_oldPoint.y); break; 
		default: return; break; 
	} 
	//取得可用的最大尺寸--------------------------------- 
	CRect rc; 
	m_pDockSite->RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST, reposQuery, &rc, NULL, TRUE); 
    CSize szMax = szOld + rc.Size() - CSize(4, 4); 
 
	//限制它的最小和最大尺寸-----------------------------	 
	szNew.cx = max(TITLE_HEIGHT, min(szNew.cx, szMax.cx)); 
	szNew.cy = max(TITLE_HEIGHT, min(szNew.cy, szMax.cy)); 
 
	//是否改变了尺寸------------------------------------- 
	if ((szNew.cx - szOld.cx) == 0 && (szNew.cy - szOld.cy) == 0) return; 
 
	(bHorz ? m_szHorz : m_szVert) = szNew; 
	m_pDockSite->DelayRecalcLayout(); 
	m_oldPoint = point; 
} 
 
int CCoolControlBar::GetFirstBar() 
{ 
	ASSERT_VALID(m_pDockBar);  
    int nThis = m_pDockBar->FindBar(this); 
    ASSERT(nThis != -1); 
	 
    // find the first bar in row 
    for (int i = nThis - 1; i >= 0; i--) 
	{ 
        if (m_pDockBar->m_arrBars[i] == NULL) 
		{ 
			return(i + 1); 
		} 
	} 
    ASSERT(FALSE); 
	return -1; 
} 
 
int CCoolControlBar::GetLastBar() 
{ 
	ASSERT_VALID(m_pDockBar);  
    int nThis = m_pDockBar->FindBar(this); 
    ASSERT(nThis != -1); 
	 
    int nBarsCount = m_pDockBar->m_arrBars.GetSize(); 
	 
    // find the last bar in row 
    for (int i = nThis + 1; i < nBarsCount; i++) 
	{ 
        if (m_pDockBar->m_arrBars[i] == NULL) 
		{ 
            return(i - 1); 
		} 
	} 
    ASSERT(FALSE); 
	return -1; 
} 
 
void CCoolControlBar::GetCoolBars(CCoolBarArray &arrCoolBars) 
{ 
	ASSERT_VALID(m_pDockBar);  
	 
    arrCoolBars.RemoveAll(); 
 
	int nFirst = GetFirstBar(); 
	int nLast  = GetLastBar(); 
    for (int i = nFirst; i <= nLast; i++) 
    { 
        CControlBar* pBar = (CControlBar*)m_pDockBar->m_arrBars[i]; 
        if (HIWORD(pBar) == 0)  continue; // placeholder 
        if (!pBar->IsVisible()) continue; 
        if (FindCoolBar(pBar) >= 0) 
		{ 
            arrCoolBars.Add((CCoolControlBar*)pBar); 
		} 
    } 
} 
 
int CCoolControlBar::FindCoolBar(CControlBar *pBar) 
{ 
   for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++) 
   { 
        if (m_arrBars[nPos] == pBar) 
		{ 
            return nPos; // got it 
		} 
   } 
    return -1; // not found 
} 
 
/*======================================================================== 
	Params:		 
		nLengthAvail:	此行中所有控制条共有的有用的长度 
		bHorz:			控制条停泊方向 
    ---------------------------------------------------------- 
	returns:	 
    ---------------------------------------------------------- 
	Remarks:	自动分配各控制条的尺寸 
==========================================================================*/ 
BOOL CCoolControlBar::AutoSize(int nLengthAvail, BOOL bHorz) 
{ 
	CCoolBarArray  arrCoolBars; 
    GetCoolBars(arrCoolBars); 
    CCoolControlBar *pCoolBar = NULL; 
	 
    int nActualLength = 0; 
    int nWidth = 0, nSizingWidth = 0; 
 
	int nFirst = GetFirstBar(); 
	int nLast  = GetLastBar(); 
 
	// 减去可见的固定长度的控制栏的长度 
    // subtract the visible fixed bars' lengths----------------- 
    for (int i = nFirst; i <= nLast; i++) 
    { 
        CControlBar* pFixedBar = (CControlBar*)m_pDockBar->m_arrBars[i]; 
        if (HIWORD(pFixedBar) == 0)  
		{ 
			continue; // 占位符(placeholder) 
		} 
        else if (!pFixedBar->IsVisible() || FindCoolBar(pFixedBar) >= 0)  
		{ 
			continue; // 不可见或不是固定控制栏. 
		} 
		 
		CRect rcBarWindow; 
        pFixedBar->GetWindowRect(&rcBarWindow); 
        nLengthAvail -= (bHorz ? rcBarWindow.Width() - 2 : rcBarWindow.Height() - 2); 
    } 
	 
	// 计算实际长度以及公共宽度. 
    // compute actual and min lengths; also the common width---- 
    for (i = 0; i < arrCoolBars.GetSize(); i++) 
    { 
        pCoolBar = arrCoolBars[i]; 
        nActualLength += bHorz ? pCoolBar->m_szHorz.cx - 2 : pCoolBar->m_szVert.cy - 2; 
        nWidth = max(nWidth, bHorz ? pCoolBar->m_szHorz.cy : pCoolBar->m_szVert.cx); 
		 
		if (pCoolBar->m_bTracking) 
		{	 
			//如果此控制栏正在被用户改变大小---------------------------- 
			//if this control bar is sizing now------------------------- 
			nSizingWidth = bHorz ? pCoolBar->m_szHorz.cy: pCoolBar->m_szVert.cx; 
		} 
    } 
 
	//如果其中有控制栏在改变大小,则公共宽度为当前正在改变宽度的控制栏的 
	//宽度,否则为当前栏中,宽度最大的那条控制栏的宽度------------------ 
	if (nSizingWidth > 0) 
	{ 
		nWidth = nSizingWidth; 
	} 
     
	// 使所有的控制栏具有相同的宽度. 
    // make the bars same width--------------------------------- 
	for (i = 0; i < arrCoolBars.GetSize(); i++) 
	{ 
        (bHorz ? arrCoolBars[i]->m_szHorz.cy : arrCoolBars[i]->m_szVert.cx) = nWidth; 
	} 
 
	// no change------------------------------------------------ 
    if (nActualLength == nLengthAvail) 
	{ 
        return FALSE;  
	} 
	 
    int nLengthDelta = nLengthAvail - nActualLength - 2; 
	int nCount = arrCoolBars.GetSize(); 
	int bSizingBar = -1; 
	int nlength = 0; 
 
	//查看有否有控制栏处于拖动中---------------------------- 
	for (i = 0; i < nCount; i++) 
	{ 
		if (arrCoolBars[i]->m_bTracking) 
		{ 
			if ((!arrCoolBars[i]->IsHorizontal() && (arrCoolBars[i]->m_bTrackType == HTLEFT || arrCoolBars[i]->m_bTrackType == HTRIGHT)) 
			  || (arrCoolBars[i]->IsHorizontal() && (arrCoolBars[i]->m_bTrackType == HTTOP  || arrCoolBars[i]->m_bTrackType == HTBOTTOM))) 
			{ 
				return FALSE; 
			} 
			bSizingBar = i; 
			break; 
		} 
	} 
	 
	// 分配各控制栏尺寸. 
    // distribute the difference between the bars, but----------- 
    // don't shrink them below minsize 
	BOOL bChangeDefaultSize = FALSE; 
	while (nLengthDelta != 0) 
	{ 
		BOOL bDefaultSize = TRUE; 
		BOOL bMinSize = TRUE; 
		 
		for (i = 0; i < nCount; i++) 
		{ 
			pCoolBar = arrCoolBars[i]; 
			int nLenght = bHorz ? pCoolBar->m_szHorz.cx : pCoolBar->m_szVert.cy; 
 
			if (nLenght == TITLE_HEIGHT && nLengthDelta < 0) // already at min length-- 
			{ 
				continue; 
			} 
			 
			bMinSize = FALSE; 
 
			if (nLenght < m_szDefault.cy && nLengthDelta < 0 && !bChangeDefaultSize) // already at default length-- 
			{ 
				continue; 
			} 
			 
			// sign of nLengthDelta------------------------------------------- 
			(bHorz ? pCoolBar->m_szHorz.cx : pCoolBar->m_szVert.cy) += nLengthDelta / abs(nLengthDelta); 
			nLengthDelta -= nLengthDelta / abs(nLengthDelta); 
			bDefaultSize = FALSE; 
			if (nLengthDelta == 0) break; 
 
		}// end for 
		 
		if (bMinSize)	return FALSE; 
		bChangeDefaultSize = bDefaultSize; 
 
	}// end while 
    return TRUE; 
} 
 
void CCoolControlBar::AutoAlign() 
{ 
	int nFirst = GetFirstBar(); 
	int nLast  = GetLastBar(); 
	 
    BOOL bHorz = (m_dwStyle & (CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM)); 
	 
    //是否需要重新调整------------------------------- 
	BOOL bNeedRecalc = FALSE; 
    int nPos, nAlign = bHorz ? -2 : 0; 
 
    CRect rcControlWnd, rcDockWnd; 
    m_pDockBar->GetWindowRect(&rcDockWnd); 
 
    for (int i = nFirst; i <= nLast; i++) 
    { 
        CControlBar* pControlBar = (CControlBar*)m_pDockBar->m_arrBars[i]; 
		//placeholder----------------------------- 
		if (HIWORD(pControlBar) == 0) 		continue; 
		//it's not visible------------------------ 
        else if (!pControlBar->IsVisible()) continue; 
		 
		//Get rect and offset--------------------- 
        pControlBar->GetWindowRect(&rcControlWnd); 
        rcControlWnd.OffsetRect(-rcDockWnd.TopLeft()); 
 
		//Is CCoolControlBar---------------------- 
        if ((nPos = FindCoolBar(pControlBar)) >= 0) 
		{ 
            rcControlWnd = CRect(rcControlWnd.TopLeft(), bHorz ? 
                m_arrBars[nPos]->m_szHorz : m_arrBars[nPos]->m_szVert); 
		} 
 
		 
		//Align----------------------------------- 
        if ((bHorz ? rcControlWnd.left : rcControlWnd.top) != nAlign) 
        { 
            if (!bHorz) 
			{ 
                rcControlWnd.OffsetRect(0, nAlign - rcControlWnd.top -2); 
			} 
            else 
			{ 
                rcControlWnd.OffsetRect(nAlign - rcControlWnd.left, -2); 
			} 
            pControlBar->MoveWindow(rcControlWnd); 
            bNeedRecalc = TRUE; 
        } 
        nAlign += (bHorz ? rcControlWnd.Width() - 2 : rcControlWnd.Height() - 2); 
    } 
	 
	//if need recalc------------------------------- 
    if (bNeedRecalc) 
    { 
        m_pDockSite->DelayRecalcLayout(); 
    } 
} 
 
inline BOOL CCoolControlBar::IsHorizontal() 
{ 
    return (m_dwStyle & (CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM)); 
} 
 
/*#################################################################### 
			------------------------------------------------ 
					 Load / Save controlbar states 
			------------------------------------------------ 
  ####################################################################*/ 
 
void CCoolControlBar::LoadState(LPCTSTR lpszProfileName) 
{ 
    ASSERT_VALID(this); 
    ASSERT(GetSafeHwnd() != NULL); // must be called after Create() 
 
    CWinApp* pApp = AfxGetApp(); 
 
    TCHAR szSection[256]; 
    wsprintf(szSection, _T("%s\\CoolControlBar(%d)"), lpszProfileName, GetDlgCtrlID()); 
 
    m_szHorz.cx  = (int)pApp->GetProfileInt(szSection, _T("sizeHorzCX"), m_szHorz.cx); 
    m_szHorz.cy  = (int)pApp->GetProfileInt(szSection, _T("sizeHorzCY"), m_szHorz.cy); 
 
    m_szVert.cx  = (int)pApp->GetProfileInt(szSection, _T("sizeVertCX"), m_szVert.cx); 
    m_szVert.cy  = (int)pApp->GetProfileInt(szSection, _T("sizeVertCY"), m_szVert.cy); 
 
    m_szFloat.cx = (int)pApp->GetProfileInt(szSection, _T("sizeFloatCX"), m_szFloat.cx); 
    m_szFloat.cy = (int)pApp->GetProfileInt(szSection, _T("sizeFloatCY"), m_szFloat.cy); 
} 
 
void CCoolControlBar::SaveState(LPCTSTR lpszProfileName) 
{ 
    // place your SaveState or GlobalSaveState call in 
    // CMainFrame::DestroyWindow(), not in OnDestroy() 
    ASSERT_VALID(this); 
    ASSERT(GetSafeHwnd() != NULL); 
 
    CWinApp* pApp = AfxGetApp(); 
 
    TCHAR szSection[256]; 
    wsprintf(szSection, _T("%s\\CoolControlBar(%d)"), lpszProfileName, GetDlgCtrlID()); 
 
    pApp->WriteProfileInt(szSection, _T("sizeHorzCX"), m_szHorz.cx); 
    pApp->WriteProfileInt(szSection, _T("sizeHorzCY"), m_szHorz.cy); 
 
    pApp->WriteProfileInt(szSection, _T("sizeVertCX"), m_szVert.cx); 
    pApp->WriteProfileInt(szSection, _T("sizeVertCY"), m_szVert.cy); 
 
    pApp->WriteProfileInt(szSection, _T("sizeFloatCX"), m_szFloat.cx); 
    pApp->WriteProfileInt(szSection, _T("sizeFloatCY"), m_szFloat.cy); 
} 
 
void CCoolControlBar::LoadStates(LPCTSTR lpszProfileName) 
{ 
    for (int i = 0; i < m_arrBars.GetSize(); i++) 
	{ 
        ((CCoolControlBar*) m_arrBars[i])->LoadState(lpszProfileName); 
	} 
} 
 
void CCoolControlBar::SaveStates(LPCTSTR lpszProfileName) 
{ 
    for (int i = 0; i < m_arrBars.GetSize(); i++) 
	{ 
        ((CCoolControlBar*) m_arrBars[i])->SaveState(lpszProfileName); 
	} 
} 
 
/*######################################################################## 
			  ------------------------------------------------ 
							   绘制标题栏函数 
			  ------------------------------------------------ 
  ########################################################################*/ 
 
void CCoolControlBar::DrawTitleBar(CDC *pDC, const CRect &rect, BOOL bHorz) 
{ 
	CRect rcTitleBar(rect); 
	CPen pen(0, 1, ::GetSysColor(COLOR_3DSHADOW)); 
	CPen *oldpen = pDC->SelectObject(&pen); 
	pDC->SetTextColor(RGB(0, 0, 0)); 
	CString strWindowText; 
	GetWindowText(strWindowText); 
	 
	if (bHorz) 
	{ 
		CFont font, *oldfont; 
		font.CreateFont(-12,0,900,0,400,0,0,0,0,0,0,0,0,"宋体"); 
		oldfont = pDC->SelectObject(&font); 
		pDC->TextOut(rcTitleBar.left + 3, rcTitleBar.bottom - 3, strWindowText); 
		pDC->FillSolidRect(4, 2, 14, 16, ::GetSysColor(COLOR_3DFACE)); 
		pDC->SelectObject(&oldfont); 
		rcTitleBar.DeflateRect(2, -1, 1, -1); 
		pDC->Draw3dRect(rcTitleBar, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DSHADOW)); 
	} 
	else 
	{ 
		rcTitleBar.DeflateRect(-1, 2, -1, 1); 
		pDC->Draw3dRect(rcTitleBar, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DSHADOW)); 
		CFont font, *oldfont; 
		font.CreateFont(-12,0,0,0,400,0,0,0,0,0,0,0,0,"宋体"); 
		oldfont = pDC->SelectObject(&font); 
 
		rcTitleBar.DeflateRect(5, 0, 15, 0); 
 
		pDC->DrawText(strWindowText, rcTitleBar, DT_SINGLELINE | DT_LEFT | DT_VCENTER); 
		pDC->SelectObject(&oldfont); 
	} 
	pDC->SelectObject(oldpen); 
} 
 
void CCoolControlBar::DrawCloseButton(CDC *pDC, DWORD dwState) 
{ 
	//hot----------------------- 
	if (dwState == 1) 
	{ 
		pDC->FillSolidRect(m_rcCloseButton, RGB(225,225,255)); 
		pDC->Draw3dRect(m_rcCloseButton, RGB(80,80,100), RGB(80,80,100)); 
	} 
	//pressed-------------------- 
	else if(dwState == 2) 
	{ 
		pDC->FillSolidRect(m_rcCloseButton, RGB(130,150,200)); 
		pDC->Draw3dRect(m_rcCloseButton, RGB(80,80,100), RGB(80,80,100)); 
		pDC->SelectStockObject(WHITE_PEN); 
	} 
	//draw 'x' sign--------------------------------------- 
	pDC->MoveTo(m_rcCloseButton.left + 3, m_rcCloseButton.top + 3); 
	pDC->LineTo(m_rcCloseButton.left + 9, m_rcCloseButton.top + 9); 
	pDC->MoveTo(m_rcCloseButton.left + 3, m_rcCloseButton.top + 8); 
	pDC->LineTo(m_rcCloseButton.left + 9, m_rcCloseButton.top + 2); 
	 
	pDC->MoveTo(m_rcCloseButton.left + 3, m_rcCloseButton.top + 4); 
	pDC->LineTo(m_rcCloseButton.left + 9, m_rcCloseButton.top + 10); 
	pDC->MoveTo(m_rcCloseButton.left + 3, m_rcCloseButton.top + 9); 
	pDC->LineTo(m_rcCloseButton.left + 9, m_rcCloseButton.top + 3); 
	 
	pDC->SelectStockObject(BLACK_PEN); 
}