Sizecbar.cpp
上传用户:libwxy
上传日期:2007-01-02
资源大小:200k
文件大小:11k
源码类别:

工具条

开发平台:

Visual C++

  1. // SizingControlBar.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "afxpriv.h"    // for CDockContext
  5. #include "resource.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CSizingControlBar
  13. CSizingControlBar::CSizingControlBar()
  14. {
  15.     m_sizeMin = CSize(32, 32);
  16.     m_sizeHorz = CSize(200, 200);
  17.     m_sizeVert = CSize(200, 200);
  18.     m_sizeFloat = CSize(200, 200);
  19.     m_bTracking = FALSE;
  20.     m_bInRecalcNC = FALSE;
  21.     m_cxEdge = 6;
  22. }
  23. CSizingControlBar::~CSizingControlBar()
  24. {
  25. }
  26. BEGIN_MESSAGE_MAP(CSizingControlBar, CControlBar)
  27.     //{{AFX_MSG_MAP(CSizingControlBar)
  28.     ON_WM_LBUTTONUP()
  29.     ON_WM_MOUSEMOVE()
  30.     ON_WM_SETCURSOR()
  31.     ON_WM_WINDOWPOSCHANGED()
  32.     ON_WM_NCPAINT()
  33.     ON_WM_NCLBUTTONDOWN()
  34.     ON_WM_NCHITTEST()
  35.     ON_WM_NCCALCSIZE()
  36.     ON_WM_LBUTTONDOWN()
  37.     ON_WM_CAPTURECHANGED()
  38.     ON_WM_LBUTTONDBLCLK()
  39.     ON_WM_SIZE()
  40. //}}AFX_MSG_MAP
  41. END_MESSAGE_MAP()
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CSizingControlBar message handlers
  44. void CSizingControlBar::OnUpdateCmdUI(class CFrameWnd *pTarget, int bDisableIfNoHndler)
  45. {
  46.     UpdateDialogControls(pTarget, bDisableIfNoHndler);
  47. }
  48. BOOL CSizingControlBar::Create(CWnd* pParentWnd, CSize sizeDefault, UINT nID, DWORD dwStyle) 
  49. {
  50.     ASSERT_VALID(pParentWnd);   // must have a parent
  51.     ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC)));
  52.     // save the style
  53.     m_dwStyle = dwStyle;
  54.     dwStyle &= ~CBRS_ALL;
  55.     dwStyle |= CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE;
  56.     m_sizeHorz = sizeDefault;
  57.     m_sizeVert = sizeDefault;
  58.     m_sizeFloat = sizeDefault;
  59.     CString wndclass = AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(NULL, IDC_ARROW),
  60.         CreateSolidBrush(GetSysColor(COLOR_BTNFACE)), 0);
  61.     if (!CWnd::Create(wndclass, NULL, dwStyle, CRect(0,0,0,0),
  62.         pParentWnd, nID))
  63.         return FALSE;
  64.     return TRUE;
  65. }
  66. CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  67. {
  68.     CRect rc;
  69.     m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP)->GetWindowRect(rc);
  70.     int nHorzDockBarWidth = bStretch ? 32767 : rc.Width() + 4;
  71.     m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT)->GetWindowRect(rc);
  72.     int nVertDockBarHeight = bStretch ? 32767 : rc.Height() + 4;
  73.     if (bHorz)
  74.         return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  75.     else
  76.         return CSize(m_sizeVert.cx, nVertDockBarHeight);
  77. }
  78. CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
  79. {
  80.     if (dwMode & (LM_HORZDOCK | LM_VERTDOCK))
  81.         return CControlBar::CalcDynamicLayout(nLength,dwMode);
  82.     if (dwMode & LM_MRUWIDTH)
  83.         return m_sizeFloat;
  84.     if (dwMode & LM_COMMIT)
  85.     {
  86.         m_sizeFloat.cx = nLength;
  87.         return m_sizeFloat;
  88.     }
  89.     if (dwMode & LM_LENGTHY)
  90.         return CSize(m_sizeFloat.cx,
  91.             m_sizeFloat.cy = max(m_sizeMin.cy, nLength));
  92.     else
  93.         return CSize(max(m_sizeMin.cx, nLength), m_sizeFloat.cy);
  94. }
  95. void CSizingControlBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) 
  96. {
  97.     CControlBar::OnWindowPosChanged(lpwndpos);
  98.     if (m_bInRecalcNC) return;
  99.     // Find on which side are we docked
  100.     UINT nDockBarID = GetParent()->GetDlgCtrlID();
  101.     // Return if dropped at same location
  102.     if (nDockBarID == m_nDockBarID // no docking side change
  103.         && (lpwndpos->flags & SWP_NOSIZE) // no size change
  104.         && ((m_dwStyle & CBRS_BORDER_ANY) != CBRS_BORDER_ANY))
  105.         return; 
  106.     m_nDockBarID = nDockBarID;
  107.     // Force recalc the non-client area
  108.     m_bInRecalcNC = TRUE;
  109.     SetWindowPos(NULL, 0, 0, 0, 0,
  110.         SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
  111.         SWP_NOACTIVATE | SWP_FRAMECHANGED);
  112.     m_bInRecalcNC = FALSE;
  113. }
  114. BOOL CSizingControlBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  115. {
  116.     if ((nHitTest != HTSIZE) || m_bTracking)
  117.         return CControlBar::OnSetCursor(pWnd, nHitTest, message);
  118.     if (IsHorz())
  119.         SetCursor(LoadCursor(NULL, IDC_SIZENS));
  120.     else
  121.         SetCursor(LoadCursor(NULL, IDC_SIZEWE));
  122.     return TRUE;
  123. }
  124. /////////////////////////////////////////////////////////////////////////
  125. // Mouse Handling
  126. //
  127. void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point) 
  128. {
  129.     if (!m_bTracking)
  130.         CControlBar::OnLButtonUp(nFlags, point);
  131.     else
  132.     {
  133.         ClientToWnd(point);
  134.         StopTracking(TRUE);
  135.     }
  136. }
  137. void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point) 
  138. {
  139.     if (IsFloating() || !m_bTracking)
  140.     {
  141.         CControlBar::OnMouseMove(nFlags, point);
  142.         return;
  143.     }
  144.     CPoint cpt = m_rectTracker.CenterPoint();
  145.     ClientToWnd(point);
  146.     if (IsHorz())
  147.     {
  148.         if (cpt.y != point.y)
  149.         {
  150.             OnInvertTracker(m_rectTracker);
  151.             m_rectTracker.OffsetRect(0, point.y - cpt.y);
  152.             OnInvertTracker(m_rectTracker);
  153.         }
  154.     }
  155.     else 
  156.     {
  157.         if (cpt.x != point.x)
  158.         {
  159.             OnInvertTracker(m_rectTracker);
  160.             m_rectTracker.OffsetRect(point.x - cpt.x, 0);
  161.             OnInvertTracker(m_rectTracker);
  162.         }
  163.     }
  164. }
  165. void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
  166. {
  167.     // Compute the rectangle of the mobile edge
  168.     GetWindowRect(m_rectBorder);
  169.     m_rectBorder = CRect(0, 0, m_rectBorder.Width(), m_rectBorder.Height());
  170.     
  171.     DWORD dwBorderStyle = m_dwStyle | CBRS_BORDER_ANY;
  172.     switch(m_nDockBarID)
  173.     {
  174.     case AFX_IDW_DOCKBAR_TOP:
  175.         dwBorderStyle &= ~CBRS_BORDER_BOTTOM;
  176.         lpncsp->rgrc[0].bottom += -m_cxEdge;
  177.         m_rectBorder.top = m_rectBorder.bottom - m_cxEdge;
  178.         break;
  179.     case AFX_IDW_DOCKBAR_BOTTOM:
  180.         dwBorderStyle &= ~CBRS_BORDER_TOP;
  181.         lpncsp->rgrc[0].top += m_cxEdge;
  182.         m_rectBorder.bottom = m_rectBorder.top + m_cxEdge;
  183.         break;
  184.     case AFX_IDW_DOCKBAR_LEFT:
  185.         dwBorderStyle &= ~CBRS_BORDER_RIGHT;
  186.         lpncsp->rgrc[0].right += -m_cxEdge;
  187.         m_rectBorder.left = m_rectBorder.right - m_cxEdge;
  188.         break;
  189.     case AFX_IDW_DOCKBAR_RIGHT:
  190.         dwBorderStyle &= ~CBRS_BORDER_LEFT;
  191.         lpncsp->rgrc[0].left += m_cxEdge;
  192.         m_rectBorder.right = m_rectBorder.left + m_cxEdge;
  193.         break;
  194.     default:
  195.         m_rectBorder.SetRectEmpty();
  196.         break;
  197.     }
  198.     SetBarStyle(dwBorderStyle);
  199. }
  200. void CSizingControlBar::OnNcPaint() 
  201. {
  202.     EraseNonClient();
  203.     CDC *pDC = GetWindowDC();
  204.     pDC->Draw3dRect(m_rectBorder, GetSysColor(COLOR_BTNHIGHLIGHT),
  205.                     GetSysColor(COLOR_BTNSHADOW));
  206.     ReleaseDC(pDC);
  207. }
  208. void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point) 
  209. {
  210.     if (m_bTracking) return;
  211.     if ((nHitTest == HTSIZE) && !IsFloating())
  212.         StartTracking();
  213.     else    
  214.         CControlBar::OnNcLButtonDown(nHitTest, point);
  215. }
  216. UINT CSizingControlBar::OnNcHitTest(CPoint point) 
  217. {
  218.     if (IsFloating())
  219.         return CControlBar::OnNcHitTest(point);
  220.     CRect rc;
  221.     GetWindowRect(rc);
  222.     point.Offset(-rc.left, -rc.top);
  223.     if (m_rectBorder.PtInRect(point))
  224.         return HTSIZE;
  225.     else
  226.         return CControlBar::OnNcHitTest(point);
  227. }
  228. void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point) 
  229. {
  230.     // only start dragging if clicked in "void" space
  231.     if (m_pDockBar != NULL)
  232.     {
  233.         // start the drag
  234.         ASSERT(m_pDockContext != NULL);
  235.         ClientToScreen(&point);
  236.         m_pDockContext->StartDrag(point);
  237.     }
  238.     else
  239.     {
  240.         CWnd::OnLButtonDown(nFlags, point);
  241.     }
  242. }
  243. void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point) 
  244. {
  245.     // only toggle docking if clicked in "void" space
  246.     if (m_pDockBar != NULL)
  247.     {
  248.         // toggle docking
  249.         ASSERT(m_pDockContext != NULL);
  250.         m_pDockContext->ToggleDocking();
  251.     }
  252.     else
  253.     {
  254.         CWnd::OnLButtonDblClk(nFlags, point);
  255.     }
  256. }
  257. void CSizingControlBar::StartTracking()
  258. {
  259.     SetCapture();
  260.     // make sure no updates are pending
  261.     RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
  262.     m_pDockSite->LockWindowUpdate();
  263.     m_ptOld = m_rectBorder.CenterPoint();
  264.     m_bTracking = TRUE;
  265.     
  266.     m_rectTracker = m_rectBorder;
  267.     if (!IsHorz()) m_rectTracker.bottom -= 4;
  268.     OnInvertTracker(m_rectTracker);
  269. }
  270. void CSizingControlBar::OnCaptureChanged(CWnd *pWnd) 
  271. {
  272.     if (m_bTracking && pWnd != this)
  273.         StopTracking(FALSE); // cancel tracking
  274.     CControlBar::OnCaptureChanged(pWnd);
  275. }
  276. void CSizingControlBar::StopTracking(BOOL bAccept)
  277. {
  278.     OnInvertTracker(m_rectTracker);
  279.     m_pDockSite->UnlockWindowUpdate();
  280.     m_bTracking = FALSE;
  281.     ReleaseCapture();
  282.     
  283.     if (!bAccept) return;
  284.     int maxsize, minsize, newsize;
  285.     CRect rcc;
  286.     m_pDockSite->GetClientRect(rcc);
  287.     newsize = IsHorz() ? m_sizeHorz.cy : m_sizeVert.cx;
  288.     maxsize = newsize + (IsHorz() ? rcc.Height() : rcc.Width());
  289.     minsize = IsHorz() ? m_sizeMin.cy : m_sizeMin.cx;
  290.     CPoint point = m_rectTracker.CenterPoint();
  291.     switch (m_nDockBarID)
  292.     {
  293.     case AFX_IDW_DOCKBAR_TOP:
  294.         newsize += point.y - m_ptOld.y; break;
  295.     case AFX_IDW_DOCKBAR_BOTTOM:
  296.         newsize += -point.y + m_ptOld.y; break;
  297.     case AFX_IDW_DOCKBAR_LEFT:
  298.         newsize += point.x - m_ptOld.x; break;
  299.     case AFX_IDW_DOCKBAR_RIGHT:
  300.         newsize += -point.x + m_ptOld.x; break;
  301.     }
  302.     newsize = max(minsize, min(maxsize, newsize));
  303.     if (IsHorz())
  304.         m_sizeHorz.cy = newsize;
  305.     else
  306.         m_sizeVert.cx = newsize;
  307.     m_pDockSite->DelayRecalcLayout();
  308. }
  309. void CSizingControlBar::OnInvertTracker(const CRect& rect)
  310. {
  311.     ASSERT_VALID(this);
  312.     ASSERT(!rect.IsRectEmpty());
  313.     ASSERT(m_bTracking);
  314.     CRect rct = rect, rcc, rcf;
  315.     GetWindowRect(rcc);
  316.     m_pDockSite->GetWindowRect(rcf);
  317.     rct.OffsetRect(rcc.left - rcf.left, rcc.top - rcf.top);
  318.     rct.DeflateRect(1, 1);
  319.     CDC *pDC = m_pDockSite->GetDCEx(NULL,
  320.         DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  321.     CBrush* pBrush = CDC::GetHalftoneBrush();
  322.     HBRUSH hOldBrush = NULL;
  323.     if (pBrush != NULL)
  324.         hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);
  325.     pDC->PatBlt(rct.left, rct.top, rct.Width(), rct.Height(), PATINVERT);
  326.     if (hOldBrush != NULL)
  327.         SelectObject(pDC->m_hDC, hOldBrush);
  328.     m_pDockSite->ReleaseDC(pDC);
  329. }
  330. BOOL CSizingControlBar::IsHorz() const
  331. {
  332.     return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
  333.         m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
  334. }
  335. CPoint& CSizingControlBar::ClientToWnd(CPoint& point)
  336. {
  337.     if (m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM)
  338.         point.y += m_cxEdge;
  339.     else if (m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT)
  340.         point.x += m_cxEdge;
  341.     return point;
  342. }