SDC C-Project CF Review 프로그램
LYW
2021-10-14 26e2541b87ca76e16cf69399eb9a3cce62d2e864
ReviewHistory/ReveiwHistory/CHRectTracker.cpp
새 파일
@@ -0,0 +1,316 @@
#include "StdAfx.h"
#include "CHRectTracker.h"
AFX_STATIC_DATA HCURSOR _afxCursors[10] = { 0, };
AFX_STATIC_DATA HBRUSH _afxHatchBrush = 0;
AFX_STATIC_DATA HPEN _afxBlackDottedPen = 0;
AFX_STATIC_DATA int _afxHandleSize = 0;
CCHRectTracker::CCHRectTracker(void)
{
}
CCHRectTracker::CCHRectTracker(LPCRECT lpSrcRect, UINT nStyle)
{
   CRectTracker(lpSrcRect, nStyle);
}
CCHRectTracker::~CCHRectTracker(void)
{
}
BOOL CCHRectTracker::TrackRubberBand(CWnd* pWnd, CPoint point, BOOL bAllowInvert)
{
   // simply call helper function to track from bottom right handle
   m_bAllowInvert = bAllowInvert;
   m_rect.SetRect(point.x, point.y, point.x, point.y);
   return TrackHandle(hitBottomRight, pWnd, point, NULL);
}
BOOL CCHRectTracker::Track(CWnd* pWnd, CPoint point, BOOL bAllowInvert, CWnd* pWndClipTo)
{
   // perform hit testing on the handles
   int nHandle = HitTestHandles(point);
   if (nHandle < 0)
   {
      // didn't hit a handle, so just return FALSE
      return FALSE;
   }
   // otherwise, call helper function to do the tracking
   m_bAllowInvert = bAllowInvert;
   return TrackHandle(nHandle, pWnd, point, pWndClipTo);
}
void CCHRectTracker::Draw(CDC* pDC) const
{
   // set initial DC state
   VERIFY(pDC->SaveDC() != 0);
#ifndef _AFX_NO_GDITRANSFORM_SUPPORT
   pDC->SetMapMode(MM_TEXT);
   pDC->SetViewportOrg(0, 0);
   pDC->SetWindowOrg(0, 0);
#endif // !_AFX_NO_GDITRANSFORM_SUPPORT
   // get normalized rectangle
   CRect rect = m_rect;
   rect.NormalizeRect();
   CPen* pOldPen = NULL;
   CBrush* pOldBrush = NULL;
   CGdiObject* pTemp;
   int nOldROP;
   CPen pen;
   //pen.CreatePen(PS_DOT, 1, RGB(255,255,255));
   pen.CreatePen(PS_DOT, 1, RGB(255,0,0));
   rect.InflateRect(+1, +1);   // borders are one pixel outside
   // draw lines
   if ((m_nStyle & (dottedLine|solidLine)) != 0)
   {
      if (m_nStyle & dottedLine)
         pOldPen = pDC->SelectObject(&pen);
         //pOldPen = (CPen*)pDC->SelectStockObject(WHITE_PEN);
      else
         pOldPen = (CPen*)pDC->SelectStockObject(BLACK_PEN);
      pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
      nOldROP = pDC->SetROP2(R2_COPYPEN);
      // rect
      pDC->Rectangle(rect.left, rect.top, rect.right, rect.bottom);
      // cross line
      if ((m_nStyle & (crossLine)) != 0)
      {
         pDC->MoveTo(rect.left+rect.Width()/2, rect.top);
         pDC->LineTo(rect.left+rect.Width()/2, rect.bottom);
         pDC->MoveTo(rect.left, rect.top+rect.Height()/2);
         pDC->LineTo(rect.right, rect.top+rect.Height()/2);
      }
      // x line
      if ((m_nStyle & (xLine)) != 0)
      {
         pDC->MoveTo(rect.left, rect.top);
         pDC->LineTo(rect.right, rect.bottom);
         pDC->MoveTo(rect.right, rect.top);
         pDC->LineTo(rect.left, rect.bottom);
      }
      pDC->SetROP2(nOldROP);
   }
#ifndef _WIN32_WCE // unsupported win32 api call to UnrealizeObject
   // if hatchBrush is going to be used, need to unrealize it
   if ((m_nStyle & (hatchInside|hatchedBorder)) != 0)
      UnrealizeObject(_afxHatchBrush);
#endif // !_WIN32_WCE
   // hatch inside
   if ((m_nStyle & hatchInside) != 0)
   {
      pTemp = pDC->SelectStockObject(NULL_PEN);
      if (pOldPen == NULL)
         pOldPen = (CPen*)pTemp;
      pTemp = pDC->SelectObject(CBrush::FromHandle(_afxHatchBrush));
      if (pOldBrush == NULL)
         pOldBrush = (CBrush*)pTemp;
      pDC->SetBkMode(TRANSPARENT);
      nOldROP = pDC->SetROP2(R2_MASKNOTPEN);
      pDC->Rectangle(rect.left+1, rect.top+1, rect.right, rect.bottom);
      pDC->SetROP2(nOldROP);
   }
   // draw hatched border
   if ((m_nStyle & hatchedBorder) != 0)
   {
      pTemp = pDC->SelectObject(CBrush::FromHandle(_afxHatchBrush));
      if (pOldBrush == NULL)
         pOldBrush = (CBrush*)pTemp;
      pDC->SetBkMode(OPAQUE);
      CRect rectTrue;
      GetTrueRect(&rectTrue);
      pDC->PatBlt(rectTrue.left, rectTrue.top, rectTrue.Width(),
         rect.top-rectTrue.top, 0x000F0001 /* Pn */);
      pDC->PatBlt(rectTrue.left, rect.bottom,
         rectTrue.Width(), rectTrue.bottom-rect.bottom, 0x000F0001 /* Pn */);
      pDC->PatBlt(rectTrue.left, rect.top, rect.left-rectTrue.left,
         rect.Height(), 0x000F0001 /* Pn */);
      pDC->PatBlt(rect.right, rect.top, rectTrue.right-rect.right,
         rect.Height(), 0x000F0001 /* Pn */);
   }
   // draw resize handles
   if ((m_nStyle & (resizeInside|resizeOutside)) != 0)
   {
      UINT mask = GetHandleMask();
      for (int i = 0; i < 8; ++i)
      {
         if (mask & (1<<i))
         {
            GetHandleRect((TrackerHit)i, &rect);
            pDC->FillSolidRect(rect, RGB(255, 255, 255));
         }
      }
   }
   // cleanup pDC state
   if (pOldPen != NULL)
      pDC->SelectObject(pOldPen);
   if (pOldBrush != NULL)
      pDC->SelectObject(pOldBrush);
   VERIFY(pDC->RestoreDC(-1));
}
BOOL CCHRectTracker::TrackHandle(int nHandle, CWnd* pWnd, CPoint point, CWnd* pWndClipTo)
{
   ASSERT(nHandle >= 0);
   ASSERT(nHandle <= 8);   // handle 8 is inside the rect
   // don't handle if capture already set
   if (::GetCapture() != NULL)
      return FALSE;
   AfxLockTempMaps();  // protect maps while looping
   ASSERT(!m_bFinalErase);
   // save original width & height in pixels
   int nWidth = m_rect.Width();
   int nHeight = m_rect.Height();
   // set capture to the window which received this message
   pWnd->SetCapture();
   ASSERT(pWnd == CWnd::GetCapture());
   pWnd->UpdateWindow();
   if (pWndClipTo != NULL)
      pWndClipTo->UpdateWindow();
   CRect rectSave = m_rect;
   // find out what x/y coords we are supposed to modify
   int *px, *py;
   int xDiff, yDiff;
   GetModifyPointers(nHandle, &px, &py, &xDiff, &yDiff);
   xDiff = point.x - xDiff;
   yDiff = point.y - yDiff;
   // get DC for drawing
   CDC* pDrawDC;
   if (pWndClipTo != NULL)
   {
      // clip to arbitrary window by using adjusted Window DC
      pDrawDC = pWndClipTo->GetDCEx(NULL, DCX_CACHE);
   }
   else
   {
      // otherwise, just use normal DC
      pDrawDC = pWnd->GetDC();
   }
   ENSURE_VALID(pDrawDC);
   CRect rectOld;
   BOOL bMoved = FALSE;
   // get messages until capture lost or cancelled/accepted
   for (;;)
   {
      MSG msg;
      VERIFY(::GetMessage(&msg, NULL, 0, 0));
      if (CWnd::GetCapture() != pWnd)
         break;
      switch (msg.message)
      {
         // handle movement/accept messages
      case WM_LBUTTONUP:
         {
            if (pWnd)
               pWnd->SendMessage(WM_LBUTTONUP, static_cast<WPARAM>(0), MAKELPARAM(0, 0));
         }
      case WM_MOUSEMOVE:
         rectOld = m_rect;
         // handle resize cases (and part of move)
         if (px != NULL)
            *px = GET_X_LPARAM(msg.lParam) - xDiff;
         if (py != NULL)
            *py = GET_Y_LPARAM(msg.lParam) - yDiff;
         // handle move case
         if (nHandle == hitMiddle)
         {
            m_rect.right = m_rect.left + nWidth;
            m_rect.bottom = m_rect.top + nHeight;
         }
         // allow caller to adjust the rectangle if necessary
         AdjustRect(nHandle, &m_rect);
         // only redraw and callback if the rect actually changed!
         m_bFinalErase = (msg.message == WM_LBUTTONUP);
         if (!rectOld.EqualRect(&m_rect) || m_bFinalErase)
         {
            if (bMoved)
            {
               m_bErase = TRUE;
               DrawTrackerRect(&rectOld, pWndClipTo, pDrawDC, pWnd);
            }
            OnChangedRect(rectOld);
            if (msg.message != WM_LBUTTONUP)
               bMoved = TRUE;
         }
         if (m_bFinalErase)
            goto ExitLoop;
         if (!rectOld.EqualRect(&m_rect))
         {
            m_bErase = FALSE;
            DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd);
         }
         break;
         // handle cancel messages
      case WM_KEYDOWN:
         if (msg.wParam != VK_ESCAPE)
            break;
      case WM_RBUTTONDOWN:
         if (bMoved)
         {
            m_bErase = m_bFinalErase = TRUE;
            DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd);
         }
         m_rect = rectSave;
         goto ExitLoop;
      case WM_LBUTTONDBLCLK:
         if (pWnd)
            pWnd->SendMessage(WM_LBUTTONDBLCLK, static_cast<WPARAM>(0), MAKELPARAM(0, 0));
         break;
         // just dispatch rest of the messages
      default:
         DispatchMessage(&msg);
         break;
      }
   }
ExitLoop:
   if (pWndClipTo != NULL)
      pWndClipTo->ReleaseDC(pDrawDC);
   else
      pWnd->ReleaseDC(pDrawDC);
   ReleaseCapture();
   AfxUnlockTempMaps(FALSE);
   // restore rect in case bMoved is still FALSE
   if (!bMoved)
      m_rect = rectSave;
   m_bFinalErase = FALSE;
   m_bErase = FALSE;
   // return TRUE only if rect has changed
   return !rectSave.EqualRect(&m_rect);
}