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
}