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