home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / ctltrack.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  10KB  |  349 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFXCTL_CORE2_SEG
  14. #pragma code_seg(AFXCTL_CORE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. AFX_STATIC_DATA const int _afxResizeStyle =
  25.     CRectTracker::resizeInside | CRectTracker::resizeOutside;
  26.  
  27. AFX_STATIC void AFXAPI _AfxOffsetTrackerRect(CRect& rect, CWnd* pWnd)
  28. {
  29.     DWORD dwStyle = pWnd->GetStyle();
  30.     DWORD dwExStyle = pWnd->GetExStyle();
  31.  
  32.     int nBorders = ((dwStyle & WS_BORDER) != 0) +
  33.         ((dwExStyle & WS_EX_CLIENTEDGE) != 0) * 2;
  34.  
  35.     int dx = -nBorders * GetSystemMetrics(SM_CXBORDER);
  36.     int dy = -nBorders * GetSystemMetrics(SM_CYBORDER);
  37.  
  38.     if (dwExStyle & WS_EX_LEFTSCROLLBAR)
  39.         dx -= GetSystemMetrics(SM_CXVSCROLL);
  40.  
  41.     rect.OffsetRect(dx - rect.left, dy - rect.top);
  42. }
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // COleControl::CreateTracker - Creates tracker for UIActive control
  46.  
  47. void COleControl::CreateTracker(BOOL bHandles, BOOL bHatching)
  48. {
  49.     CreateTracker(bHandles, bHatching, NULL);
  50. }
  51.  
  52. void COleControl::CreateTracker(BOOL bHandles, BOOL bHatching, LPCRECT prcClip)
  53. {
  54.     ASSERT(bHandles || bHatching);
  55. #ifdef _AFXDLL
  56.     ASSERT(!m_bOpen);
  57. #endif
  58.     ASSERT(m_bUIActive);
  59.     ASSERT(m_pRectTracker == NULL);
  60.  
  61.     UINT nStyle = 0;
  62.     if (bHandles)
  63.         nStyle |= CRectTracker::resizeOutside;
  64.     if (bHatching)
  65.         nStyle |= CRectTracker::hatchedBorder;
  66.  
  67.     ASSERT(nStyle != 0);
  68.  
  69.     TRY
  70.     {
  71.         // Create the tracker.
  72.         CRect rectTmp = m_rcPos;
  73.         _AfxOffsetTrackerRect(rectTmp, this);
  74.         m_pRectTracker = new CControlRectTracker(rectTmp, nStyle);
  75.  
  76.         // Reset the window sizes, reflecting the tracker
  77.         if (prcClip != NULL)
  78.             m_pRectTracker->m_rectClip = *prcClip;
  79.         else
  80.             prcClip = m_rcPos;
  81.         OnSetObjectRects(m_rcPos, prcClip);
  82.     }
  83.     CATCH (CException, e)
  84.     {
  85.         // If anything went wrong, just continue without the tracker.
  86.         if (m_pRectTracker != NULL)
  87.         {
  88.             delete m_pRectTracker;
  89.             m_pRectTracker = NULL;
  90.         }
  91.     }
  92.     END_CATCH
  93. }
  94.  
  95. /////////////////////////////////////////////////////////////////////////////
  96. // COleControl::DestroyTracker - destroys tracker when control UIDeactivates
  97.  
  98. void COleControl::DestroyTracker()
  99. {
  100. #ifdef _AFXDLL
  101.     ASSERT(!m_bOpen);
  102. #endif
  103.     ASSERT(m_bUIActive);
  104.  
  105.     if (m_pRectTracker == NULL)
  106.         return;
  107.  
  108.     // Destroy the tracker.
  109.     CRect rectClip = m_pRectTracker->m_rectClip;
  110.     delete m_pRectTracker;
  111.     m_pRectTracker = NULL;
  112.  
  113.     // Reset the position based on no tracker present
  114.     OnSetObjectRects(m_rcPos, rectClip);
  115. }
  116.  
  117. /////////////////////////////////////////////////////////////////////////////
  118. // COleControl::OnNcPaint - handler for WM_NCPAINT message
  119.  
  120. void COleControl::OnNcPaint()
  121. {
  122. #ifdef _AFXDLL
  123.     if (m_bOpen || m_pRectTracker == NULL)
  124. #else
  125.     if (m_pRectTracker == NULL)
  126. #endif
  127.     {
  128.         Default();
  129.         return;
  130.     }
  131.  
  132.     DWORD dwStyle = GetStyle();
  133.     DWORD dwExStyle = GetExStyle();
  134.     DWORD dwScrollStyle = dwStyle & (WS_HSCROLL | WS_VSCROLL);
  135.  
  136.     // Paint scrollbars, if any.
  137.     if (dwScrollStyle != 0)
  138.         Default();
  139.  
  140.     UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  141.     CWindowDC dc(this);
  142.  
  143.     // Convert client coords to window coords, draw tracker, and convert back.
  144.     CRect& rectTrack = m_pRectTracker->m_rect;
  145.     int dx = rectTrack.left - nHandleSize;
  146.     int dy = rectTrack.top - nHandleSize;
  147.     rectTrack.OffsetRect(-dx, -dy);
  148.     CRect rc = rectTrack;
  149.     m_pRectTracker->Draw(&dc);
  150.     m_pRectTracker->m_rect.OffsetRect(dx, dy);
  151.  
  152.     // Draw border, if any.
  153.     _AfxDrawBorders(&dc, rc, (dwStyle & WS_BORDER),
  154.         (dwExStyle & WS_EX_CLIENTEDGE));
  155.  
  156.     if (dwScrollStyle == (WS_HSCROLL | WS_VSCROLL))
  157.     {
  158.         // Workaround for Windows bug:
  159.         // Draw the corner between the scrollbars
  160.  
  161.         int cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
  162.  
  163.         if (dwExStyle & WS_EX_LEFTSCROLLBAR)    // Middle East Windows only
  164.             rc.right = rc.left + cxVScroll;
  165.         else
  166.             rc.left = rc.right - cxVScroll;
  167.  
  168.         rc.top = rc.bottom - GetSystemMetrics(SM_CYVSCROLL);
  169.  
  170.         CBrush brushGUI(GetSysColor(COLOR_3DFACE));
  171.         dc.FillRect(rc, &brushGUI);
  172.     }
  173. }
  174.  
  175. /////////////////////////////////////////////////////////////////////////////
  176. // COleControl::OnNcCalcSize - handler for WM_NCCALCSIZE message
  177.  
  178. void COleControl::OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS* lpParams)
  179. {
  180.     Default();
  181.  
  182. #ifdef _AFXDLL
  183.     if (m_bOpen || m_pRectTracker == NULL)
  184. #else
  185.     if (m_pRectTracker == NULL)
  186. #endif
  187.         return;
  188.  
  189.     // Adjust client rect to make room for tracker.
  190.     UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  191.     ::InflateRect(lpParams->rgrc, -(int)nHandleSize, -(int)nHandleSize);
  192.  
  193.     m_pRectTracker->m_rect = m_rcPos;
  194.     _AfxOffsetTrackerRect(m_pRectTracker->m_rect, this);
  195. }
  196.  
  197. /////////////////////////////////////////////////////////////////////////////
  198. // COleControl::OnNcHitTest - handler for WM_NCHITTEST message
  199.  
  200. UINT COleControl::OnNcHitTest(CPoint point)
  201. {
  202. #ifdef _AFXDLL
  203.     if (m_bOpen || m_pRectTracker == NULL ||
  204. #else
  205.     if (m_pRectTracker == NULL ||
  206. #endif
  207.         !(m_pRectTracker->m_nStyle & _afxResizeStyle))
  208.     {
  209.         return (UINT)Default();
  210.     }
  211.  
  212.     UINT nHitCode = (UINT)Default();
  213.  
  214.     // Check for scrollbar or sizebox hit.
  215.     if ((nHitCode == HTHSCROLL) || (nHitCode == HTVSCROLL) ||
  216.         (nHitCode == HTSIZE))
  217.     {
  218.         return nHitCode;
  219.     }
  220.  
  221.     // Check for client area hit.
  222.     CPoint pointClient(point);
  223.     ScreenToClient(&pointClient);
  224.     CRect rect;
  225.     GetClientRect(rect);
  226.     if (rect.PtInRect(pointClient))
  227.         return HTCLIENT;
  228.  
  229.     // Check for border hit.
  230.     UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  231.     GetWindowRect(rect);
  232.     rect.InflateRect(-(int)nHandleSize, -(int)nHandleSize);
  233.     if (rect.PtInRect(point))
  234.         return HTBORDER;
  235.  
  236.     // If tracker detects a hit, return HTBORDER; otherwise HTNOWHERE.
  237.     nHitCode = m_pRectTracker->HitTest(pointClient);
  238.     return (nHitCode == CRectTracker::hitNothing) ? HTNOWHERE : HTBORDER;
  239. }
  240.  
  241. /////////////////////////////////////////////////////////////////////////////
  242. // COleControl::OnNcLButtonDown - handler for WM_NCLBUTTONDOWN message
  243.  
  244. void COleControl::OnNcLButtonDown(UINT nHitTest, CPoint point)
  245. {
  246. #ifdef _AFXDLL
  247.     if (m_bOpen || m_pRectTracker == NULL ||
  248. #else
  249.     if (m_pRectTracker == NULL ||
  250. #endif
  251.         !(m_pRectTracker->m_nStyle & _afxResizeStyle) ||
  252.         (nHitTest == HTHSCROLL) || (nHitTest == HTVSCROLL))
  253.     {
  254.         Default();
  255.         return;
  256.     }
  257.  
  258.     ScreenToClient(&point);
  259.  
  260.     // Setup a (semi-)permanent CWnd for the control's parent window
  261.     CRect rectBefore = m_pRectTracker->m_rect;
  262.     CWnd* pWndClip = CWnd::FromHandle(::GetParent(GetOuterWindow()->m_hWnd));
  263.  
  264.     // Move or resize the tracker.
  265.     BOOL bTrack = m_pRectTracker->Track(this, point, FALSE, pWndClip);
  266.  
  267.     if (bTrack)
  268.     {
  269.         ASSERT(m_pInPlaceSite);
  270.  
  271.         CRect rectAfter = m_pRectTracker->m_rect;
  272.         if (rectBefore != rectAfter)
  273.         {
  274.             // If rectangle changed, adjust the tracker's rectangle and move
  275.             // the control.
  276.             m_pRectTracker->m_rect.OffsetRect(-m_pRectTracker->m_rect.left,
  277.                 -m_pRectTracker->m_rect.top);
  278.             CWnd* pWndOuter = GetOuterWindow();
  279.             CWnd* pWndParent = pWndOuter->GetParent();
  280.             CRect rectWindow;
  281.             CRect rectParent;
  282.             pWndOuter->GetWindowRect(rectWindow);
  283.             pWndParent->GetClientRect(rectParent);
  284.             pWndParent->ClientToScreen(rectParent);
  285.          int nBorderWidth = GetBorderStyle()*GetSystemMetrics( SM_CXBORDER );
  286.          int nBorderHeight = GetBorderStyle()*GetSystemMetrics( SM_CYBORDER );
  287.             UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  288.             rectAfter.OffsetRect(rectWindow.left - rectParent.left +
  289.                 nHandleSize + nBorderWidth, rectWindow.top - rectParent.top +
  290.             nHandleSize + nBorderHeight);
  291.  
  292.             // Update the control's extents.
  293.             SIZEL szlPixels;
  294.             SIZEL szlHimetric;
  295.             szlPixels.cx = (long)rectAfter.Width();
  296.             szlPixels.cy = (long)rectAfter.Height();
  297.             _AfxXformSizeInPixelsToHimetric(NULL, &szlPixels, &szlHimetric);
  298.             if ((m_cxExtent != szlHimetric.cx) ||
  299.                 (m_cyExtent != szlHimetric.cy))
  300.             {
  301.                 m_cxExtent = szlHimetric.cx;
  302.                 m_cyExtent = szlHimetric.cy;
  303.                 SetModifiedFlag();
  304.             }
  305.  
  306.             // Move/resize the control's window.
  307.             m_pInPlaceSite->OnPosRectChange(rectAfter);
  308.         }
  309.     }
  310. }
  311.  
  312. /////////////////////////////////////////////////////////////////////////////
  313. // COleControl::OnSetCursor - handler for WM_SETCURSOR message
  314.  
  315. BOOL COleControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT)
  316. {
  317. #ifdef _AFXDLL
  318.     if (m_bOpen || m_pRectTracker == NULL ||
  319. #else
  320.     if (m_pRectTracker == NULL ||
  321. #endif
  322.         !(m_pRectTracker->m_nStyle & _afxResizeStyle))
  323.     {
  324.         return (BOOL)Default();
  325.     }
  326.  
  327.     if ((nHitTest == HTCLIENT) || (nHitTest == HTHSCROLL) ||
  328.         (nHitTest == HTVSCROLL) || (nHitTest == HTSIZE))
  329.     {
  330.         // In client area: use default cursor or arrow.
  331.         if (!Default())
  332.             ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
  333.     }
  334.     else
  335.     {
  336.         // In non-client area: use tracker-supplied cursor.
  337.         m_pRectTracker->SetCursor(pWnd, HTCLIENT);
  338.     }
  339.  
  340.     return TRUE;
  341. }
  342.  
  343. /////////////////////////////////////////////////////////////////////////////
  344. // Force any extra compiler-generated code into AFX_INIT_SEG
  345.  
  346. #ifdef AFX_INIT_SEG
  347. #pragma code_seg(AFX_INIT_SEG)
  348. #endif
  349.