sizecbar.cpp
上传用户:netltd
上传日期:2013-02-12
资源大小:7234k
文件大小:15k
源码类别:

绘图程序

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1998 by Cristi Posea
  3. // All rights reserved
  4. /////////////////////////////////////////////////////////////////////////
  5. // SizingControlBar.cpp : implementation file
  6. //
  7. #include "stdafx.h"
  8. #include "afxpriv.h"    // for CDockContext
  9. #include "sizecbar.h"
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. /////////////////////////////////////////////////////////////////////////
  16. // CSizingControlBar
  17. CSizingControlBar::CSizingControlBar()
  18. {
  19.     m_sizeMin = CSize(32, 32);
  20.     m_sizeHorz = CSize(200, 200);
  21.     m_sizeVert = CSize(200, 200);
  22.     m_sizeFloat = CSize(200, 200);
  23.     m_bTracking = FALSE;
  24.     m_bInRecalcNC = FALSE;
  25.     m_cxEdge = 5;
  26. m_bDragShowContent = FALSE;
  27. }
  28. CSizingControlBar::~CSizingControlBar()
  29. {
  30. }
  31. BEGIN_MESSAGE_MAP(CSizingControlBar, CControlBar)
  32.     //{{AFX_MSG_MAP(CSizingControlBar)
  33.     ON_WM_LBUTTONUP()
  34.     ON_WM_MOUSEMOVE()
  35.     ON_WM_SETCURSOR()
  36.     ON_WM_WINDOWPOSCHANGED()
  37.     ON_WM_NCPAINT()
  38.     ON_WM_NCLBUTTONDOWN()
  39.     ON_WM_NCHITTEST()
  40.     ON_WM_NCCALCSIZE()
  41.     ON_WM_LBUTTONDOWN()
  42.     ON_WM_CAPTURECHANGED()
  43.     ON_WM_LBUTTONDBLCLK()
  44.     ON_WM_PAINT()
  45.     ON_WM_SIZE()
  46. ON_WM_RBUTTONDOWN()
  47. //}}AFX_MSG_MAP
  48. END_MESSAGE_MAP()
  49. /////////////////////////////////////////////////////////////////////////
  50. // CSizingControlBar message handlers
  51. //sizeDefault.x是停靠或浮动的Bar的宽度,sizeDefault.y是浮动的Bar的高度
  52. BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
  53.                                CSize sizeDefault, BOOL bHasGripper,
  54.                                UINT nID, DWORD dwStyle)
  55. {
  56.     ASSERT_VALID(pParentWnd);   // must have a parent
  57.     ASSERT (!((dwStyle & CBRS_SIZE_FIXED)
  58.         && (dwStyle & CBRS_SIZE_DYNAMIC)));
  59.     // save the style
  60.     SetBarStyle(dwStyle & CBRS_ALL);
  61.     CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
  62.         ::LoadCursor(NULL, IDC_ARROW),
  63.         ::GetSysColorBrush(COLOR_BTNFACE), 0); // COLOR_BTNFACE = RGB(192, 192, 192)
  64.     dwStyle &= ~CBRS_ALL;
  65.     dwStyle &= WS_VISIBLE | WS_CHILD;
  66.     if (!CWnd::Create(wndclass, lpszWindowName, dwStyle, CRect(0,0,0,0),
  67.         pParentWnd, nID))
  68.         return FALSE;
  69.     m_sizeHorz = sizeDefault;
  70.     m_sizeVert = sizeDefault;
  71.     m_sizeFloat = sizeDefault;
  72.     m_bHasGripper = bHasGripper;
  73.     m_cyGripper = m_bHasGripper ? 12 : 0;
  74.     return TRUE;
  75. }
  76. BOOL CSizingControlBar::IsHorzDocked() const
  77. {
  78.     return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
  79.         m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
  80. }
  81. BOOL CSizingControlBar::IsVertDocked() const
  82. {
  83.     return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
  84.         m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
  85. }
  86. CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  87. {
  88.     CRect rc;
  89.     m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP)->GetWindowRect(rc);
  90.     int nHorzDockBarWidth = bStretch ? 32767 : rc.Width() + 4;
  91.     m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT)->GetWindowRect(rc);
  92.     int nVertDockBarHeight = bStretch ? 32767 : rc.Height() + 4;
  93.     if (bHorz)
  94.         return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  95.     else
  96.         return CSize(m_sizeVert.cx, nVertDockBarHeight);
  97. }
  98. CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
  99. {
  100.     if (dwMode & (LM_HORZDOCK | LM_VERTDOCK))
  101.     {
  102.         if (nLength == -1)
  103.             GetDockingFrame()->DelayRecalcLayout();
  104.         return CControlBar::CalcDynamicLayout(nLength,dwMode);
  105.     }
  106.     if (dwMode & LM_MRUWIDTH)
  107.         return m_sizeFloat;
  108.     if (dwMode & LM_COMMIT)
  109.     {
  110.         m_sizeFloat.cx = nLength;
  111.         return m_sizeFloat;
  112.     }
  113.     if (dwMode & LM_LENGTHY)
  114.         return CSize(m_sizeFloat.cx,
  115.             m_sizeFloat.cy = max(m_sizeMin.cy, nLength));
  116.     else
  117.         return CSize(max(m_sizeMin.cx, nLength), m_sizeFloat.cy);
  118. }
  119. void CSizingControlBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) 
  120. {
  121.     CControlBar::OnWindowPosChanged(lpwndpos);
  122.     // Find on which side are we docked
  123.     m_nDockBarID = GetParent()->GetDlgCtrlID();
  124.     if (!m_bInRecalcNC)
  125.     {
  126.         m_bInRecalcNC = TRUE;
  127.         // Force recalc the non-client area
  128.         SetWindowPos(NULL, 0, 0, 0, 0,
  129.             SWP_NOMOVE | SWP_NOSIZE |
  130.             SWP_NOACTIVATE | SWP_NOZORDER |
  131.             SWP_FRAMECHANGED);
  132.         m_bInRecalcNC = FALSE;
  133.     }
  134. }
  135. BOOL CSizingControlBar::OnSetCursor(CWnd* pWnd, UINT nHitTest,
  136.                                     UINT message) 
  137. {
  138.     if ((nHitTest != HTSIZE) || m_bTracking)
  139.         return CControlBar::OnSetCursor(pWnd, nHitTest, message);
  140.     if (IsHorzDocked())
  141.         ::SetCursor(::LoadCursor(NULL, IDC_SIZENS));
  142.     else
  143.         ::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
  144.     return TRUE;
  145. }
  146. /////////////////////////////////////////////////////////////////////////
  147. // Mouse Handling
  148. //
  149. void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point) 
  150. {
  151.     if (m_pDockBar != NULL)
  152.     {
  153.         // start the drag
  154.         ASSERT(m_pDockContext != NULL);
  155.         ClientToScreen(&point);
  156.         m_pDockContext->StartDrag(point);
  157.     }
  158.     else
  159.         CWnd::OnLButtonDown(nFlags, point);
  160. }
  161. void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point) 
  162. {
  163.     if (m_pDockBar != NULL)
  164.     {
  165.         // toggle docking
  166.         ASSERT(m_pDockContext != NULL);
  167.         m_pDockContext->ToggleDocking();
  168.     }
  169.     else
  170.         CWnd::OnLButtonDblClk(nFlags, point);
  171. }
  172. void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point) 
  173. {
  174.     if (m_bTracking) return;
  175.     if ((nHitTest == HTSIZE) && !IsFloating())
  176.         StartTracking();
  177.     else    
  178.         CControlBar::OnNcLButtonDown(nHitTest, point);
  179. }
  180. void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point) 
  181. {
  182.     if (m_bTracking)
  183.         StopTracking(TRUE);
  184.     CControlBar::OnLButtonUp(nFlags, point);
  185. }
  186. void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point) 
  187. {
  188.     if (m_bTracking)
  189.         StopTracking(FALSE);
  190. CControlBar::OnRButtonDown(nFlags, point);
  191. }
  192. void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point) 
  193. {
  194.     if (m_bTracking)
  195.     {
  196. ASSERT (!IsFloating());
  197. CPoint pt = point;
  198. ClientToScreen(&pt);
  199. OnTrackUpdateSize(pt);
  200.     }
  201.     CControlBar::OnMouseMove(nFlags, point);
  202. }
  203. void CSizingControlBar::OnCaptureChanged(CWnd *pWnd) 
  204. {
  205.     if (m_bTracking && pWnd != this)
  206.         StopTracking(FALSE); // cancel tracking
  207.     CControlBar::OnCaptureChanged(pWnd);
  208. }
  209. void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
  210.                                      NCCALCSIZE_PARAMS FAR* lpncsp) 
  211. {
  212.     // Compute the rectangle of the mobile edge
  213.     GetWindowRect(m_rectBorder);
  214.     m_rectBorder.OffsetRect(-m_rectBorder.left, -m_rectBorder.top);
  215.     m_rectBorder.DeflateRect(1, 1);
  216.     
  217.     m_rectGripper = m_rectBorder;
  218.     m_rectGripper.DeflateRect(5, 5);
  219.     m_rectGripper.right -= m_cxEdge;
  220.     m_rectGripper.bottom -= m_cxEdge;
  221.     CRect rc = lpncsp->rgrc[0];
  222.     DWORD dwBorderStyle = m_dwStyle | CBRS_BORDER_ANY;
  223.     switch(m_nDockBarID)
  224.     {
  225.     case AFX_IDW_DOCKBAR_TOP:
  226.         dwBorderStyle &= ~CBRS_BORDER_BOTTOM;
  227.         rc.DeflateRect(m_cyGripper + 2, 2, 2, m_cxEdge + 2);
  228.         m_rectBorder.top = m_rectBorder.bottom - m_cxEdge;
  229.         break;
  230.     case AFX_IDW_DOCKBAR_BOTTOM:
  231.         dwBorderStyle &= ~CBRS_BORDER_TOP;
  232.         rc.DeflateRect(m_cyGripper + 2, m_cxEdge + 2, 2, 2);
  233.         m_rectBorder.bottom = m_rectBorder.top + m_cxEdge;
  234.         m_rectGripper.OffsetRect(0, m_cxEdge);
  235.         break;
  236.     case AFX_IDW_DOCKBAR_LEFT:
  237.         dwBorderStyle &= ~CBRS_BORDER_RIGHT;
  238.         rc.DeflateRect(2, m_cyGripper + 2, m_cxEdge + 2, 6);
  239.         m_rectBorder.left = m_rectBorder.right - m_cxEdge;
  240.         break;
  241.     case AFX_IDW_DOCKBAR_RIGHT:
  242.         dwBorderStyle &= ~CBRS_BORDER_LEFT;
  243.         rc.DeflateRect(m_cxEdge + 2, m_cyGripper + 2, 2, 6);
  244.         m_rectBorder.right = m_rectBorder.left + m_cxEdge;
  245.         m_rectGripper.OffsetRect(m_cxEdge, 0);
  246.         break;
  247.     default:
  248.         m_rectBorder.SetRectEmpty();
  249.         break;
  250.     }
  251.     lpncsp->rgrc[0] = rc;
  252.     SetBarStyle(dwBorderStyle);
  253. }
  254. void CSizingControlBar::OnNcPaint() 
  255. {
  256.     // get window DC that is clipped to the non-client area
  257.     CWindowDC dc(this);
  258.     CRect rectClient;
  259.     GetClientRect(rectClient);
  260.     CRect rectWindow;
  261.     GetWindowRect(rectWindow);
  262.     ScreenToClient(rectWindow);
  263.     rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
  264.     dc.ExcludeClipRect(rectClient);
  265.     // draw borders in non-client area
  266.     rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
  267.     DrawBorders(&dc, rectWindow);
  268.     // erase parts not drawn
  269.     dc.IntersectClipRect(rectWindow);
  270.     // erase NC background the hard way
  271.     HBRUSH hbr = (HBRUSH)GetClassLong(m_hWnd, GCL_HBRBACKGROUND);
  272.     ::FillRect(dc.m_hDC, rectWindow, hbr);
  273.     // paint the mobile edge
  274.     dc.Draw3dRect(m_rectBorder, ::GetSysColor(COLOR_BTNHIGHLIGHT),
  275.         ::GetSysColor(COLOR_BTNSHADOW));
  276.     if (m_bHasGripper)
  277.     {
  278.         // paint the gripper
  279.         CRect gripper = m_rectGripper;
  280.         
  281.         if (IsHorzDocked())
  282.         {
  283.             // gripper at left
  284.             gripper.right = gripper.left + 3;
  285.             dc.Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
  286.                 ::GetSysColor(COLOR_BTNSHADOW));
  287.             gripper.OffsetRect(3, 0);
  288.             dc.Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
  289.                 ::GetSysColor(COLOR_BTNSHADOW));
  290.         }
  291.         else if (IsVertDocked())
  292.         {
  293.             // gripper at top
  294.             gripper.bottom = gripper.top + 3;
  295.             dc.Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
  296.                 ::GetSysColor(COLOR_BTNSHADOW));
  297.             gripper.OffsetRect(0, 3);
  298.             dc.Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
  299.                 ::GetSysColor(COLOR_BTNSHADOW));
  300.         }
  301.     }
  302.     ReleaseDC(&dc);
  303. }
  304. void CSizingControlBar::OnPaint() 
  305. {
  306.     // overridden to skip border painting based on clientrect
  307.     CPaintDC dc(this);
  308. }
  309. UINT CSizingControlBar::OnNcHitTest(CPoint point) 
  310. {
  311.     if (IsFloating())
  312.         return CControlBar::OnNcHitTest(point);
  313.     CRect rc;
  314.     GetWindowRect(rc);
  315.     point.Offset(-rc.left, -rc.top);
  316.     if (m_rectBorder.PtInRect(point))
  317.         return HTSIZE;
  318.     else
  319.         return HTCLIENT;
  320. }
  321. /////////////////////////////////////////////////////////////////////////
  322. // CSizingControlBar implementation helpers
  323. void CSizingControlBar::StartTracking()
  324. {
  325.     SetCapture();
  326.     // make sure no updates are pending
  327.     RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
  328. m_bDragShowContent = QueryDragFullWindows();
  329. if (!m_bDragShowContent)
  330.     m_pDockSite->LockWindowUpdate();
  331. m_sizeOld = IsHorzDocked() ? m_sizeHorz : m_sizeVert;
  332. CRect rect;
  333. GetWindowRect(&rect);
  334.     m_ptOld = m_rectBorder.CenterPoint() + rect.TopLeft();
  335. m_sizeMax = CalcMaxSize();
  336.     m_bTracking = TRUE;
  337.     
  338. if (!m_bDragShowContent)
  339.     OnTrackInvertTracker();
  340. }
  341. void CSizingControlBar::StopTracking(BOOL bAccept)
  342. {
  343. if (!m_bDragShowContent)
  344. {
  345. OnTrackInvertTracker();
  346.     m_pDockSite->UnlockWindowUpdate();
  347. }
  348.     m_bTracking = FALSE;
  349.     ReleaseCapture();
  350.     
  351.     if (!bAccept) // resize canceled?
  352. {
  353. // restore old size
  354. if (IsHorzDocked())
  355.         m_sizeHorz = m_sizeOld;
  356. else
  357. m_sizeVert = m_sizeOld;
  358. }
  359.     m_pDockSite->DelayRecalcLayout();
  360. }
  361. void CSizingControlBar::OnTrackUpdateSize(CPoint& point)
  362. {
  363. BOOL bHorz = IsHorzDocked();
  364.     CSize sizeNew = m_sizeOld;
  365.     if ((m_nDockBarID == AFX_IDW_DOCKBAR_TOP) ||
  366. (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT))
  367.         sizeNew += point - m_ptOld;
  368. else
  369.         sizeNew -= point - m_ptOld;
  370. // check limits
  371.    sizeNew.cx = max(m_sizeMin.cx, sizeNew.cx);
  372.    sizeNew.cy = max(m_sizeMin.cy, sizeNew.cy);
  373.    sizeNew.cx = min(m_sizeMax.cx, sizeNew.cx);
  374.    sizeNew.cy = min(m_sizeMax.cy, sizeNew.cy);
  375.     if ((sizeNew.cy == m_sizeHorz.cy) && bHorz ||
  376. (sizeNew.cx == m_sizeVert.cx) && !bHorz)
  377. return; // no size change
  378. if (!m_bDragShowContent)
  379. OnTrackInvertTracker();
  380.     if (bHorz)
  381. m_sizeHorz = sizeNew;
  382. else
  383. m_sizeVert = sizeNew;
  384. if (!m_bDragShowContent)
  385. OnTrackInvertTracker();
  386. else
  387.     m_pDockSite->DelayRecalcLayout();
  388. }
  389. CSize CSizingControlBar::CalcMaxSize()
  390. {
  391. // the control bar cannot grow with more than the size of 
  392. // remaining client area of the frame
  393. CRect rect;
  394. m_pDockSite->GetClientRect(&rect);
  395. CSize size = rect.Size();
  396. CWnd* pBar;
  397. if (IsHorzDocked())
  398. {
  399. if (pBar = m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP))
  400. {
  401. pBar->GetWindowRect(&rect);
  402. size -= rect.Size();
  403. }
  404. if (pBar = m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_BOTTOM))
  405. {
  406. pBar->GetWindowRect(&rect);
  407. size -= rect.Size();
  408. }
  409. if (pBar = m_pDockSite->GetControlBar(AFX_IDW_STATUS_BAR))
  410. {
  411. pBar->GetWindowRect(&rect);
  412. size -= rect.Size();
  413. }
  414. }
  415. else
  416. {
  417. if (pBar = m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT))
  418. {
  419. pBar->GetWindowRect(&rect);
  420. size -= rect.Size();
  421. }
  422. if (pBar = m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_RIGHT))
  423. {
  424. pBar->GetWindowRect(&rect);
  425. size -= rect.Size();
  426. }
  427. }
  428. size -= CSize(4, 4);
  429.     size += IsHorzDocked() ? m_sizeHorz : m_sizeVert;
  430. return size;
  431. }
  432. void CSizingControlBar::OnTrackInvertTracker()
  433. {
  434.     ASSERT_VALID(this);
  435.     ASSERT(m_bTracking);
  436. CRect rect = m_rectBorder;
  437.     CRect rectBar, rectFrame;
  438.     GetWindowRect(rectBar);
  439.     rect.OffsetRect(rectBar.TopLeft());
  440.     m_pDockSite->GetWindowRect(rectFrame);
  441.     rect.OffsetRect(-rectFrame.left, -rectFrame.top);
  442. switch (m_nDockBarID)
  443. {
  444. case AFX_IDW_DOCKBAR_TOP:
  445. rect.OffsetRect(0, m_sizeHorz.cy - m_sizeOld.cy); break;
  446. case AFX_IDW_DOCKBAR_BOTTOM:
  447. rect.OffsetRect(0, m_sizeOld.cy - m_sizeHorz.cy); break;
  448. case AFX_IDW_DOCKBAR_LEFT:
  449. rect.OffsetRect(m_sizeVert.cx - m_sizeOld.cx, 0); break;
  450. case AFX_IDW_DOCKBAR_RIGHT:
  451. rect.OffsetRect(m_sizeOld.cx - m_sizeVert.cx, 0); break;
  452. }
  453. if (IsVertDocked())
  454.     rect.bottom -= 4;
  455.     rect.DeflateRect(1, 1);
  456.     CDC *pDC = m_pDockSite->GetDCEx(NULL,
  457.         DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  458.     CBrush* pBrush = CDC::GetHalftoneBrush();
  459.     HBRUSH hOldBrush = NULL;
  460.     if (pBrush != NULL)
  461.         hOldBrush = (HBRUSH)::SelectObject(pDC->m_hDC, pBrush->m_hObject);
  462.     pDC->PatBlt(rect.left, rect.top,
  463. rect.Width(), rect.Height(), PATINVERT);
  464.     if (hOldBrush != NULL)
  465.         ::SelectObject(pDC->m_hDC, hOldBrush);
  466.     m_pDockSite->ReleaseDC(pDC);
  467. }
  468. BOOL CSizingControlBar::QueryDragFullWindows() const
  469. {
  470. TCHAR sDragfullWindows[2];
  471. DWORD cbDragfullWindows = sizeof(DWORD);
  472. DWORD dwType;
  473. HKEY hKey;
  474. BOOL bRet = FALSE;
  475. RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\desktop"),
  476. 0, KEY_QUERY_VALUE, &hKey);
  477. if (!FAILED(RegQueryValueEx(hKey, _T("DragfullWindows"),
  478. NULL, &dwType, (LPBYTE)&sDragfullWindows, &cbDragfullWindows)))
  479. if (!_tcscmp(sDragfullWindows, _T("1")))
  480. bRet = TRUE;
  481. RegCloseKey(hKey);
  482. return bRet;
  483. }