www.pudn.com > mfcopentree.rar > WorkDlgBar.cpp


// WorkDlgBar.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "Mfcopen.h" 
#include "WorkDlgBar.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CWorkDlgBar dialog 
 
 
CWorkDlgBar::CWorkDlgBar(): 
m_clrBtnHilight(::GetSysColor(COLOR_BTNHILIGHT)), 
m_clrBtnShadow( ::GetSysColor(COLOR_BTNSHADOW)) 
{ 
	m_sizeMin     = CSize(32,60); 
	m_sizeHorz    = CSize(200,400); 
	m_sizeVert    = CSize(200,500); 
	m_sizeFloat   = CSize(200,500); 
	m_bTracking   = FALSE; 
	m_bInRecalcNC = FALSE; 
	m_cxEdge      = 6; 
	m_cxBorder    = 3; 
	m_cxGripper   = 20;	 
} 
 
 
void CWorkDlgBar::DoDataExchange(CDataExchange* pDX) 
{ 
	CControlBar::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CWorkDlgBar) 
	//}}AFX_DATA_MAP 
} 
 
 
BEGIN_MESSAGE_MAP(CWorkDlgBar, CControlBar) 
	//{{AFX_MSG_MAP(CWorkDlgBar) 
	ON_WM_CAPTURECHANGED() 
	ON_WM_LBUTTONDBLCLK() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_LBUTTONUP() 
	ON_WM_MOUSEMOVE() 
	ON_WM_NCCALCSIZE() 
	ON_WM_NCHITTEST() 
	ON_WM_NCLBUTTONDBLCLK() 
	ON_WM_NCLBUTTONDOWN() 
	ON_WM_NCPAINT() 
	ON_WM_SETCURSOR() 
	ON_WM_WINDOWPOSCHANGED() 
	ON_WM_PAINT() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CWorkDlgBar message handlers 
 
BOOL CWorkDlgBar::Create(CWnd *pParentWnd,  
						 CTreeCtrl *pTree,						 
						 CString &pTitle, 
						 UINT nID, 
						 DWORD dwStyle) 
{ 
	//必须有一个父窗口 
	ASSERT_VALID(pParentWnd); 
	ASSERT(!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC))); 
	//保存窗口风格 
	m_dwStyle=dwStyle; 
	m_dwStyle=(dwStyle & CBRS_ALL); 
	if(nID=AFX_IDW_TOOLBAR) 
		m_dwStyle|=CBRS_HIDE_INPLACE; 
    dwStyle &=~CBRS_ALL; 
	//创建父窗口 
	CString wndclass=AfxRegisterWndClass(CS_DBLCLKS, 
		                                 LoadCursor(NULL,IDC_ARROW), 
										 CreateSolidBrush(GetSysColor(COLOR_BTNFACE)), 
										 0); 
	if(!CWnd::Create(wndclass,pTitle,dwStyle,CRect(0,0,0,0),pParentWnd,0)) 
		return FALSE; 
	//创建子窗口:树形视图窗口 
	m_pTree=pTree;//|TVS_EDITLABELS 
	DWORD dwTreeStyle= WS_VISIBLE|WS_CHILD| 
		               TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SINGLEEXPAND; 
	pTree->Create(dwTreeStyle, 
		          CRect(0,0,150,300), 
		          this,ID_TREE_BOX); 
	SetWindowLong(pTree->GetSafeHwnd(),GWL_EXSTYLE, 
		          GetWindowLong(pTree->GetSafeHwnd(),GWL_EXSTYLE)|WS_EX_CLIENTEDGE); 
	 
	CRect rcTree;	 
	m_pTree->GetWindowRect(rcTree); 
 
	m_sizeHorz=m_sizeVert=m_sizeFloat=rcTree.Size(); 
	m_sizeHorz.cy+=m_cxEdge+m_cxBorder; 
	m_sizeVert.cx+=m_cxEdge+m_cxBorder; 
 
	return TRUE; 
} 
 
CSize CWorkDlgBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz) 
{ 
	CRect rc; 
	m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP)->GetWindowRect(rc); 
	int nHorzDockBarWidth=bStretch?32767:rc.Width()+4; 
	m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT)->GetWindowRect(rc); 
	int nVertDockBarHeight=bStretch?32767:rc.Height()+4; 
	if(IsFloating()) 
		return m_sizeFloat; 
	else if(bHorz) 
		return CSize(nHorzDockBarWidth,m_sizeHorz.cy); 
	else 
		return CSize(m_sizeVert.cx,nVertDockBarHeight); 
} 
 
CSize CWorkDlgBar::CalcDynamicLayout(int nLength, DWORD dwMode) 
{ 
	if(dwMode & (LM_HORZDOCK|LM_VERTDOCK)) 
	{ 
		SetWindowPos(NULL,0,0,0,0, 
			         SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER| 
			         SWP_NOACTIVATE|SWP_FRAMECHANGED); 
		m_pDockSite->RecalcLayout(); 
		return CControlBar::CalcDynamicLayout(nLength,dwMode);	 
	} 
	if(dwMode & LM_MRUWIDTH) 
		return m_sizeFloat; 
	if(dwMode & LM_COMMIT) 
	{ 
		m_sizeFloat.cx=nLength; 
		return m_sizeFloat;	 
	} 
	if(dwMode & LM_LENGTHY) 
		return CSize(m_sizeFloat.cx,m_sizeFloat.cy = max(m_sizeMin.cy,nLength)); 
	else 
		return CSize(max(m_sizeMin.cx,nLength),m_sizeFloat.cy);     
} 
 
//该函数必须重载,因为它是纯虚函数 
void CWorkDlgBar::OnUpdateCmdUI(CFrameWnd *pTarget, BOOL bDisableIfNoHndler) 
{ 
	UpdateDialogControls(pTarget,bDisableIfNoHndler); 
} 
 
//当用户在跟踪条上按住鼠标时将调用此函数,做开始拖动之前的初始化工作 
void CWorkDlgBar::StartTracking() 
{ 
	SetCapture(); 
	RedrawWindow(NULL,NULL,RDW_ALLCHILDREN|RDW_UPDATENOW); 
	m_pDockSite->LockWindowUpdate(); 
	m_ptOld=m_rectBorder.CenterPoint(); 
	m_bTracking=TRUE; 
	m_rectTracker=m_rectBorder; 
	if(!IsHorz()) 
		m_rectTracker.bottom-=4; 
	OnInvertTracker(m_rectTracker); 
} 
 
//用户拖动跟踪条到一个新位置后,放开鼠标键将调用该函数 
void CWorkDlgBar::StopTracking(BOOL bAccept) 
{ 
	OnInvertTracker(m_rectTracker); 
	m_pDockSite->UnlockWindowUpdate(); 
	m_bTracking=FALSE; 
	ReleaseCapture(); 
	if(!bAccept) 
		return; 
	int maxsize,minsize,newsize; 
	CRect rcc; 
	m_pDockSite->GetWindowRect(rcc); 
	newsize=IsHorz()?m_sizeHorz.cy:m_sizeVert.cx; 
	maxsize=newsize+(IsHorz()?rcc.Height():rcc.Width()); 
	minsize=IsHorz()?m_sizeMin.cy:m_sizeMin.cx; 
	CPoint point=m_rectTracker.CenterPoint(); 
	switch(m_nDockBarID) 
	{ 
	case AFX_IDW_DOCKBAR_TOP: 
		newsize+=point.y-m_ptOld.y; 
		break; 
	case AFX_IDW_DOCKBAR_BOTTOM: 
		newsize+=-point.y+m_ptOld.y; 
		break; 
	case AFX_IDW_DOCKBAR_LEFT: 
		newsize+=point.x-m_ptOld.x; 
		break; 
	case AFX_IDW_DOCKBAR_RIGHT: 
		newsize+=-point.x+m_ptOld.x; 
		break; 
	} 
	newsize=max(minsize,min(maxsize,newsize)); 
	if(IsHorz()) 
		m_sizeHorz.cy=newsize; 
	else 
		m_sizeVert.cx=newsize; 
	m_pDockSite->RecalcLayout(); 
} 
 
//颜色翻转、绘制跟踪条 
void CWorkDlgBar::OnInvertTracker(const CRect &rect) 
{ 
	ASSERT_VALID(this); 
	ASSERT(!rect.IsRectEmpty()); 
	ASSERT(m_bTracking); 
	CRect rct=rect; 
	CRect rcc; 
	CRect rcf; 
	GetWindowRect(rcc); 
	m_pDockSite->GetWindowRect(rcf); 
	rct.OffsetRect(rcc.left-rcf.left,rcc.top-rcf.top); 
	rct.DeflateRect(1,1); 
	CDC *pDC=m_pDockSite->GetDCEx(NULL, 
		DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE); 
	CBrush *pBrush=CDC::GetHalftoneBrush(); 
	HBRUSH hOldBrush=NULL; 
	if(pBrush!=NULL) 
		hOldBrush=(HBRUSH)SelectObject(pDC->m_hDC,pBrush->m_hObject); 
	pDC->PatBlt(rct.left,rct.top,rct.Width(),rct.Height(),PATINVERT); 
	if(hOldBrush!=NULL) 
		SelectObject(pDC->m_hDC,hOldBrush); 
	m_pDockSite->ReleaseDC(pDC); 
} 
 
//将客户坐标转换为窗口坐标 
CPoint& CWorkDlgBar::ClientToWnd(CPoint &point) 
{ 
	if(m_nDockBarID==AFX_IDW_DOCKBAR_BOTTOM) 
		point.y+=m_cxEdge; 
	else if(m_nDockBarID==AFX_IDW_DOCKBAR_RIGHT) 
		point.x+=m_cxEdge; 
	return point; 
} 
 
 
BOOL CWorkDlgBar::IsHorz() const 
{ 
	return (m_nDockBarID==AFX_IDW_DOCKBAR_TOP|| 
		    m_nDockBarID==AFX_IDW_DOCKBAR_BOTTOM); 
} 
 
//该函数用于绘制“把手” 
void CWorkDlgBar::DrawGripper(CDC &dc) 
{ 
	//浮动时不绘制把手 
	if(m_dwStyle & CBRS_FLOATING) 
		return; 
	m_pDockSite->RecalcLayout(); 
	CRect gripper; 
	GetWindowRect(gripper); 
	ScreenToClient(gripper); 
	gripper.OffsetRect(-gripper.left,-gripper.top); 
	if(m_dwStyle & CBRS_ORIENT_HORZ) 
	{ 
		//“把手”在左边 
		m_rectGripper.top=gripper.top+40; 
		m_rectGripper.bottom=gripper.bottom; 
		m_rectGripper.left=gripper.left; 
		m_rectGripper.right=gripper.left+20; 
 
 
		m_rectClose.left=gripper.left+7; 
		m_rectClose.right=m_rectClose.left+12; 
		m_rectClose.top=gripper.top+10; 
		m_rectClose.bottom=m_rectClose.top+12; 
/*		//绘制关闭框 
		dc.DrawFrameControl(m_rectClose,DFC_CAPTION,DFCS_CAPTIONCLOSE); 
*/ 
		//绘制切换停泊状态框 
		m_rectUndock=m_rectClose; 
		m_rectUndock.OffsetRect(0,13); 
		dc.DrawFrameControl(m_rectUndock,DFC_CAPTION,DFCS_CAPTIONMAX); 
 
		gripper.top+=38; 
		gripper.bottom-=10; 
		gripper.left+=10; 
		gripper.right=gripper.left+3; 
		dc.Draw3dRect(gripper,m_clrBtnHilight,m_clrBtnShadow); 
		gripper.OffsetRect(4,0); 
		dc.Draw3dRect(gripper,m_clrBtnHilight,m_clrBtnShadow); 
	} 
	else 
	{ 
		//“把手”在上边 
		m_rectGripper.top=gripper.top; 
		m_rectGripper.bottom=gripper.top+20; 
		m_rectGripper.left=gripper.left; 
		m_rectGripper.right=gripper.right-40; 
 
		m_rectClose.right=gripper.right-10; 
		m_rectClose.left=m_rectClose.right-11; 
		m_rectClose.top=gripper.top=7; 
		m_rectClose.bottom=m_rectClose.top+11; 
/*		//绘制关闭框 
		dc.DrawFrameControl(m_rectClose,DFC_CAPTION,DFCS_CAPTIONCLOSE); 
*/ 
		//绘制切换停泊框 
		m_rectUndock=m_rectClose; 
		m_rectUndock.OffsetRect(-2,0); 
		dc.DrawFrameControl(m_rectUndock,DFC_CAPTION,DFCS_CAPTIONMAX); 
 
		gripper.right-=30; 
		gripper.left+=10; 
		gripper.top+=2; 
		gripper.bottom=gripper.top+3; 
		dc.Draw3dRect(gripper,m_clrBtnHilight,m_clrBtnShadow); 
		gripper.OffsetRect(0,4); 
		dc.Draw3dRect(gripper,m_clrBtnHilight,m_clrBtnShadow); 
	} 
} 
 
void CWorkDlgBar::OnCaptureChanged(CWnd *pWnd)  
{ 
	if(m_bTracking && pWnd!=this) 
		StopTracking(FALSE);//停止拖动跟踪条 
	CWnd::OnCaptureChanged(pWnd); 
} 
 
void CWorkDlgBar::OnLButtonDblClk(UINT nFlags, CPoint point)  
{ 
	if(m_pDockBar!=NULL) 
	{ 
		//切换停泊浮动条 
		ASSERT(m_pDockContext!=NULL); 
		m_pDockContext->ToggleDocking(); 
	} 
	else 
	{ 
		CWnd::OnLButtonDblClk(nFlags,point); 
	} 
} 
 
void CWorkDlgBar::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	//当用户在窗口中“void”区域按住鼠标拖动时 
	if(m_pDockBar!=NULL) 
	{ 
		//开始拖动 
		ASSERT(m_pDockContext!=NULL); 
		ClientToScreen(&point); 
		m_pDockContext->StartDrag(point); 
	} 
	else 
	{ 
		CWnd::OnLButtonDown(nFlags, point); 
	} 
} 
 
void CWorkDlgBar::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	if(!m_bTracking) 
		CControlBar::OnLButtonUp(nFlags,point); 
	else 
	{ 
		ClientToWnd(point); 
		StopTracking(TRUE); 
	} 
} 
 
void CWorkDlgBar::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	if(IsFloating()||!m_bTracking) 
	{ 
		CControlBar::OnMouseMove(nFlags,point); 
		return; 
	} 
	CPoint cpt=m_rectTracker.CenterPoint(); 
	ClientToWnd(point); 
	if(IsHorz()) 
	{ 
		if(cpt.y!=point.y) 
		{ 
			OnInvertTracker(m_rectTracker); 
			m_rectTracker.OffsetRect(0,point.y-cpt.y); 
			OnInvertTracker(m_rectTracker); 
		} 
	} 
	else 
	{ 
		if(cpt.x!=point.x) 
		{ 
			OnInvertTracker(m_rectTracker); 
			m_rectTracker.OffsetRect(point.x-cpt.x,0); 
			OnInvertTracker(m_rectTracker); 
		} 
	} 
} 
 
void CWorkDlgBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)  
{ 
	//计算可动边界的区域 
	GetWindowRect(m_rectBorder); 
	m_rectBorder=CRect(0,0,m_rectBorder.Width(),m_rectBorder.Height()); 
	DWORD dwBorderStyle=m_dwStyle|CBRS_BORDER_ANY; 
	switch(m_nDockBarID) 
	{ 
	case AFX_IDW_DOCKBAR_TOP: 
		dwBorderStyle &=~CBRS_BORDER_BOTTOM; 
		lpncsp->rgrc[0].left+=m_cxGripper; 
		lpncsp->rgrc[0].bottom+=-m_cxEdge; 
		lpncsp->rgrc[0].top+=m_cxBorder; 
		lpncsp->rgrc[0].right+=-m_cxBorder; 
		m_rectBorder.top=m_rectBorder.bottom-m_cxEdge; 
		break; 
	case AFX_IDW_DOCKBAR_BOTTOM: 
		dwBorderStyle &=~CBRS_BORDER_TOP; 
		lpncsp->rgrc[0].left+=m_cxGripper; 
		lpncsp->rgrc[0].bottom+=-m_cxEdge; 
		lpncsp->rgrc[0].top+=m_cxBorder; 
		lpncsp->rgrc[0].right+=-m_cxBorder; 
		m_rectBorder.bottom=m_rectBorder.top+m_cxEdge; 
		break; 
	case AFX_IDW_DOCKBAR_LEFT: 
		dwBorderStyle &=~CBRS_BORDER_RIGHT; 
		lpncsp->rgrc[0].right+=-m_cxEdge; 
		lpncsp->rgrc[0].left+=m_cxBorder; 
		lpncsp->rgrc[0].bottom+=-m_cxBorder; 
		lpncsp->rgrc[0].top+=m_cxGripper; 
		m_rectBorder.left=m_rectBorder.right-m_cxEdge; 
		break; 
	case AFX_IDW_DOCKBAR_RIGHT: 
		dwBorderStyle &=~CBRS_BORDER_LEFT; 
		lpncsp->rgrc[0].left+=m_cxEdge; 
		lpncsp->rgrc[0].right+=-m_cxBorder; 
		lpncsp->rgrc[0].bottom+=-m_cxBorder; 
		lpncsp->rgrc[0].top+=m_cxGripper; 
		m_rectBorder.right=m_rectBorder.left+m_cxEdge; 
		break; 
	default: 
		m_rectBorder.SetRectEmpty(); 
		break; 
	} 
	SetBarStyle(dwBorderStyle); 
} 
 
UINT CWorkDlgBar::OnNcHitTest(CPoint point)  
{ 
	if(IsFloating()) 
		return CControlBar::OnNcHitTest(point); 
	CRect rc; 
	GetWindowRect(rc); 
	point.Offset(-rc.left,-rc.top); 
	if(m_rectClose.PtInRect(point)) 
		return HTSYSMENU; 
	else if(m_rectUndock.PtInRect(point)) 
		return HTMINBUTTON; 
	else if(m_rectGripper.PtInRect(point)) 
		return HTCAPTION; 
	else if(m_rectBorder.PtInRect(point)) 
		return HTSIZE; 
	else 
		return CControlBar::OnNcHitTest(point); 
} 
 
void CWorkDlgBar::OnNcLButtonDblClk(UINT nHitTest, CPoint point)  
{ 
	if((m_pDockBar!=NULL) && (nHitTest==HTCAPTION)) 
	{ 
		//切换停泊和浮动状态 
		ASSERT(m_pDockContext!=NULL); 
		m_pDockContext->ToggleDocking(); 
	} 
	else 
	{ 
		CWnd::OnNcLButtonDblClk(nHitTest, point); 
	} 
} 
 
void CWorkDlgBar::OnNcLButtonDown(UINT nHitTest, CPoint point)  
{ 
	if(m_bTracking) 
		return; 
	if((nHitTest==HTSYSMENU) && !IsFloating()) 
	{ 
		m_pDockContext->ToggleDocking(); 
	} 
	//鼠标单击切换停泊状态按钮 
	else if((nHitTest==HTMINBUTTON) && !IsFloating()) 
		m_pDockContext->ToggleDocking(); 
	else if((nHitTest==HTCAPTION) && !IsFloating() && (m_pDockBar!=NULL)) 
	{ 
		//开始拖动 
		ASSERT(m_pDockContext!=NULL); 
		m_pDockContext->StartDrag(point); 
	} 
	else if((nHitTest==HTSIZE) && !IsFloating()) 
		StartTracking(); 
	else 
		CControlBar::OnNcLButtonDown(nHitTest, point); 
} 
 
//绘制非客户区 
void CWorkDlgBar::OnNcPaint()  
{ 
	EraseNonClient(); 
	CWindowDC dc(this); 
	dc.Draw3dRect(m_rectBorder,GetSysColor(COLOR_BTNHIGHLIGHT),GetSysColor(COLOR_BTNSHADOW)); 
	DrawGripper(dc); 
	CRect pRect; 
	GetClientRect(&pRect); 
	InvalidateRect(&pRect,TRUE); 
} 
 
//当鼠标位于跟踪条上时,改变鼠标形状 
BOOL CWorkDlgBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)  
{ 
	if((nHitTest!=HTSIZE)||m_bTracking) 
		return CControlBar::OnSetCursor(pWnd,nHitTest,message); 
	if(IsHorz()) 
		SetCursor(LoadCursor(NULL,IDC_SIZENS)); 
	else 
		SetCursor(LoadCursor(NULL,IDC_SIZEWE)); 
	return TRUE; 
} 
 
void CWorkDlgBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)  
{ 
	CControlBar::OnWindowPosChanged(lpwndpos); 
	if(m_bInRecalcNC) 
	{ 
		CRect rect; 
		GetWindowRect(rect); 
		 
		CRect rc; 
		GetClientRect(rc); 
		rc.DeflateRect(4,4); 
 
		CRect rcTree;		 
		rcTree.left=rc.left; 
		rcTree.right=rc.right; 
		rcTree.top=rc.top; 
	    rcTree.bottom=rc.bottom; 
		m_pTree->MoveWindow(rcTree);		 
		return; 
	} 
	//判断窗口停泊在哪边 
	UINT nDockBarID=GetParent()->GetDlgCtrlID(); 
	//若落在同一位置则返回 
	if(nDockBarID==m_nDockBarID 
		&& (lpwndpos->flags & SWP_NOSIZE) 
		&& ((m_dwStyle & CBRS_BORDER_ANY)!=CBRS_BORDER_ANY)) 
		return; 
	m_nDockBarID=nDockBarID; 
	//强迫重新绘制非客户区 
	m_bInRecalcNC=TRUE; 
	SetWindowPos(NULL,0,0,0,0, 
		SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_FRAMECHANGED); 
	m_bInRecalcNC=FALSE; 
} 
 
 
 
 
 
void CWorkDlgBar::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
	 
	// TODO: Add your message handler code here 
	 
	// Do not call CControlBar::OnPaint() for painting messages 
}