home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / CTLTRACK.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  9.3 KB  |  327 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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. static const int _nResizeStyle =
  25.     CRectTracker::resizeInside | CRectTracker::resizeOutside;
  26.  
  27. static void PASCAL _OffsetTrackerRect(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.     ASSERT(bHandles || bHatching);
  50.     ASSERT(!m_bOpen);
  51.     ASSERT(m_bUIActive);
  52.     ASSERT(m_pRectTracker == NULL);
  53.  
  54.     UINT nStyle = 0;
  55.     if (bHandles)
  56.         nStyle |= CRectTracker::resizeOutside;
  57.     if (bHatching)
  58.         nStyle |= CRectTracker::hatchedBorder;
  59.  
  60.     ASSERT(nStyle != 0);
  61.  
  62.     TRY
  63.     {
  64.         // Create the tracker.
  65.         CRect rectTmp = m_rcPos;
  66.         _OffsetTrackerRect(rectTmp, this);
  67.         m_pRectTracker = new CRectTracker(rectTmp, nStyle);
  68.         UINT nHandleSize = m_pRectTracker->m_nHandleSize++;
  69.  
  70.         // Enlarge window to expose non-client area.
  71.         CWnd* pWndOuter = GetOuterWindow();
  72.         CRect rectWindow;
  73.         pWndOuter->GetWindowRect(rectWindow);
  74.         rectWindow.InflateRect(nHandleSize, nHandleSize);
  75.         ::MapWindowPoints(HWND_DESKTOP, pWndOuter->GetParent()->m_hWnd, (POINT*)(LPRECT)rectWindow, 2);
  76.         ::MoveWindow(pWndOuter->m_hWnd, rectWindow.left, rectWindow.top,
  77.             rectWindow.Width(), rectWindow.Height(), TRUE);
  78.     }
  79.     CATCH (CException, e)
  80.     {
  81.         // If anything went wrong, just continue without the tracker.
  82.         if (m_pRectTracker != NULL)
  83.         {
  84.             delete m_pRectTracker;
  85.             m_pRectTracker = NULL;
  86.         }
  87.     }
  88.     END_CATCH
  89. }
  90.  
  91. /////////////////////////////////////////////////////////////////////////////
  92. // COleControl::DestroyTracker - destroys tracker when control UIDeactivates
  93.  
  94. void COleControl::DestroyTracker()
  95. {
  96.     ASSERT(!m_bOpen);
  97.     ASSERT(m_bUIActive);
  98.  
  99.     if (m_pRectTracker == NULL)
  100.         return;
  101.  
  102.     UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  103.  
  104.     // Destroy the tracker.
  105.     delete m_pRectTracker;
  106.     m_pRectTracker = NULL;
  107.  
  108.     // Restore window to its original (pre-UIActive) size.
  109.         CWnd* pWndOuter = GetOuterWindow();
  110.         CRect rectWindow;
  111.         pWndOuter->GetWindowRect(rectWindow);
  112.         rectWindow.InflateRect(-(int)nHandleSize, -(int)nHandleSize);
  113.         ::MapWindowPoints(HWND_DESKTOP, pWndOuter->GetParent()->m_hWnd, (POINT*)(LPRECT)rectWindow, 2);
  114.         ::MoveWindow(pWndOuter->m_hWnd, rectWindow.left, rectWindow.top,
  115.             rectWindow.Width(), rectWindow.Height(), TRUE);
  116. }
  117.  
  118. /////////////////////////////////////////////////////////////////////////////
  119. // COleControl::OnNcPaint - handler for WM_NCPAINT message
  120.  
  121. void COleControl::OnNcPaint()
  122. {
  123.     if (m_bOpen || m_pRectTracker == NULL)
  124.     {
  125.         Default();
  126.         return;
  127.     }
  128.  
  129.     DWORD dwStyle = GetStyle();
  130.     DWORD dwExStyle = GetExStyle();
  131.     DWORD dwScrollStyle = dwStyle & (WS_HSCROLL | WS_VSCROLL);
  132.  
  133.     // Paint scrollbars, if any.
  134.     if (dwScrollStyle != 0)
  135.         Default();
  136.  
  137.     UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  138.     CWindowDC dc(this);
  139.  
  140.     // Convert client coords to window coords, draw tracker, and convert back.
  141.     CRect& rectTrack = m_pRectTracker->m_rect;
  142.     int dx = rectTrack.left - nHandleSize;
  143.     int dy = rectTrack.top - nHandleSize;
  144.     rectTrack.OffsetRect(-dx, -dy);
  145.     CRect rc = rectTrack;
  146.     m_pRectTracker->Draw(&dc);
  147.     m_pRectTracker->m_rect.OffsetRect(dx, dy);
  148.  
  149.     // Draw border, if any.
  150.     _AfxDrawBorders(&dc, rc, (dwStyle & WS_BORDER),
  151.         (dwExStyle & WS_EX_CLIENTEDGE));
  152.  
  153.     if (dwScrollStyle == (WS_HSCROLL | WS_VSCROLL))
  154.     {
  155.         // Workaround for Windows bug:
  156.         // Draw the corner between the scrollbars
  157.  
  158.         int cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
  159.  
  160.         if (dwExStyle & WS_EX_LEFTSCROLLBAR)    // Middle East Windows only
  161.             rc.right = rc.left + cxVScroll;
  162.         else
  163.             rc.left = rc.right - cxVScroll;
  164.  
  165.         rc.top = rc.bottom - GetSystemMetrics(SM_CYVSCROLL);
  166.  
  167.         CBrush brushGUI(GetSysColor(COLOR_3DFACE));
  168.         dc.FillRect(rc, &brushGUI);
  169.     }
  170. }
  171.  
  172. /////////////////////////////////////////////////////////////////////////////
  173. // COleControl::OnNcCalcSize - handler for WM_NCCALCSIZE message
  174.  
  175. void COleControl::OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS* lpParams)
  176. {
  177.     Default();
  178.  
  179.     if (m_bOpen || m_pRectTracker == NULL)
  180.         return;
  181.  
  182.     // Adjust client rect to make room for tracker.
  183.     UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  184.     ::InflateRect(lpParams->rgrc, -(int)nHandleSize, -(int)nHandleSize);
  185.  
  186.     m_pRectTracker->m_rect = m_rcPos;
  187.     _OffsetTrackerRect(m_pRectTracker->m_rect, this);
  188. }
  189.  
  190. /////////////////////////////////////////////////////////////////////////////
  191. // COleControl::OnNcHitTest - handler for WM_NCHITTEST message
  192.  
  193. UINT COleControl::OnNcHitTest(CPoint point)
  194. {
  195.     if (m_bOpen || m_pRectTracker == NULL ||
  196.         !(m_pRectTracker->m_nStyle & _nResizeStyle))
  197.     {
  198.         return (UINT)Default();
  199.     }
  200.  
  201.     UINT nHitCode = (UINT)Default();
  202.  
  203.     // Check for scrollbar or sizebox hit.
  204.     if ((nHitCode == HTHSCROLL) || (nHitCode == HTVSCROLL) ||
  205.         (nHitCode == HTSIZE))
  206.     {
  207.         return nHitCode;
  208.     }
  209.  
  210.     // Check for client area hit.
  211.     CPoint pointClient(point);
  212.     ScreenToClient(&pointClient);
  213.     CRect rect;
  214.     GetClientRect(rect);
  215.     if (rect.PtInRect(pointClient))
  216.         return HTCLIENT;
  217.  
  218.     // Check for border hit.
  219.     UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  220.     GetWindowRect(rect);
  221.     rect.InflateRect(-(int)nHandleSize, -(int)nHandleSize);
  222.     if (rect.PtInRect(point))
  223.         return HTBORDER;
  224.  
  225.     // If tracker detects a hit, return HTBORDER; otherwise HTNOWHERE.
  226.     nHitCode = m_pRectTracker->HitTest(pointClient);
  227.     return (nHitCode == CRectTracker::hitNothing) ? HTNOWHERE : HTBORDER;
  228. }
  229.  
  230. /////////////////////////////////////////////////////////////////////////////
  231. // COleControl::OnNcLButtonDown - handler for WM_NCLBUTTONDOWN message
  232.  
  233. void COleControl::OnNcLButtonDown(UINT nHitTest, CPoint point)
  234. {
  235.     if (m_bOpen || m_pRectTracker == NULL ||
  236.         !(m_pRectTracker->m_nStyle & _nResizeStyle) ||
  237.         (nHitTest == HTHSCROLL) || (nHitTest == HTVSCROLL))
  238.     {
  239.         Default();
  240.         return;
  241.     }
  242.  
  243.     ScreenToClient(&point);
  244.  
  245.     // Setup a (semi-)permanent CWnd for the control's parent window
  246.     CRect rectBefore = m_pRectTracker->m_rect;
  247.     CWnd* pWndClip = CWnd::FromHandle(::GetParent(GetOuterWindow()->m_hWnd));
  248.  
  249.     // Move or resize the tracker.
  250.     BOOL bTrack = m_pRectTracker->Track(this, point, FALSE, pWndClip);
  251.  
  252.     if (bTrack)
  253.     {
  254.         ASSERT(m_pInPlaceSite);
  255.  
  256.         CRect rectAfter = m_pRectTracker->m_rect;
  257.         if (rectBefore != rectAfter)
  258.         {
  259.             // If rectangle changed, adjust the tracker's rectangle and move
  260.             // the control.
  261.             m_pRectTracker->m_rect.OffsetRect(-m_pRectTracker->m_rect.left,
  262.                 -m_pRectTracker->m_rect.top);
  263.             CWnd* pWndOuter = GetOuterWindow();
  264.             CWnd* pWndParent = pWndOuter->GetParent();
  265.             CRect rectWindow;
  266.             CRect rectParent;
  267.             pWndOuter->GetWindowRect(rectWindow);
  268.             pWndParent->GetClientRect(rectParent);
  269.             pWndParent->ClientToScreen(rectParent);
  270.             UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  271.             rectAfter.OffsetRect(rectWindow.left - rectParent.left +
  272.                 nHandleSize, rectWindow.top - rectParent.top + nHandleSize);
  273.  
  274.             // Update the control's extents.
  275.             SIZEL szlPixels;
  276.             SIZEL szlHimetric;
  277.             szlPixels.cx = (long)rectAfter.Width();
  278.             szlPixels.cy = (long)rectAfter.Height();
  279.             _AfxXformSizeInPixelsToHimetric(NULL, &szlPixels, &szlHimetric);
  280.             if ((m_cxExtent != szlHimetric.cx) ||
  281.                 (m_cyExtent != szlHimetric.cy))
  282.             {
  283.                 m_cxExtent = szlHimetric.cx;
  284.                 m_cyExtent = szlHimetric.cy;
  285.                 SetModifiedFlag();
  286.             }
  287.  
  288.             // Move/resize the control's window.
  289.             m_pInPlaceSite->OnPosRectChange(rectAfter);
  290.         }
  291.     }
  292. }
  293.  
  294. /////////////////////////////////////////////////////////////////////////////
  295. // COleControl::OnSetCursor - handler for WM_SETCURSOR message
  296.  
  297. BOOL COleControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT)
  298. {
  299.     if (m_bOpen || m_pRectTracker == NULL ||
  300.         !(m_pRectTracker->m_nStyle & _nResizeStyle))
  301.     {
  302.         return (BOOL)Default();
  303.     }
  304.  
  305.     if ((nHitTest == HTCLIENT) || (nHitTest == HTHSCROLL) ||
  306.         (nHitTest == HTVSCROLL) || (nHitTest == HTSIZE))
  307.     {
  308.         // In client area: use default cursor or arrow.
  309.         if (!Default())
  310.             ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
  311.     }
  312.     else
  313.     {
  314.         // In non-client area: use tracker-supplied cursor.
  315.         m_pRectTracker->SetCursor(pWnd, HTCLIENT);
  316.     }
  317.  
  318.     return TRUE;
  319. }
  320.  
  321. /////////////////////////////////////////////////////////////////////////////
  322. // Force any extra compiler-generated code into AFX_INIT_SEG
  323.  
  324. #ifdef AFX_INIT_SEG
  325. #pragma code_seg(AFX_INIT_SEG)
  326. #endif
  327.