⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recttracker.cpp

📁 BCAM 1394 Driver
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
//  (c) 2002 by Basler Vision Technologies
//  Section:  Vision Components
//  Project:  BCAM
//  $Header: RectTracker.cpp, 3, 12.12.2002 17:26:08, Happe, A.$
//-----------------------------------------------------------------------------
/**
  \file     RectTracker.cpp
  \brief    implementation of the CRectTracker class.
*/
//////////////////////////////////////////////////////////////////////

// adopted from MFC CRectTrack
#include "stdafx.h"
#include "resource.h"
#include "RectTracker.h"

#ifndef _countof
#define _countof(s) (sizeof(s)/sizeof(*(s)))
#endif
#define CX_BORDER   1
#define CY_BORDER   1
static HCURSOR Cursors[10] = { 0, };
static HBRUSH HatchBrush = 0;
static HPEN BlackDottedPen = 0;
static int HandleSize = 0;


struct HANDLEINFO
{
  size_t nOffsetX;    // offset within RECT for X coordinate
  size_t nOffsetY;    // offset within RECT for Y coordinate
  int nCenterX;       // adjust X by Width()/2 * this number
  int nCenterY;       // adjust Y by Height()/2 * this number
  int nHandleX;       // adjust X by handle size * this number
  int nHandleY;       // adjust Y by handle size * this number
  int nInvertX;       // handle converts to this when X inverted
  int nInvertY;       // handle converts to this when Y inverted
};

// this array describes all 8 handles (clock-wise)
static const HANDLEINFO HandleInfo[] =
{
  // corner handles (top-left, top-right, bottom-right, bottom-left
  { offsetof(RECT, left), offsetof(RECT, top),        0, 0,  0,  0, 1, 3 },
  { offsetof(RECT, right), offsetof(RECT, top),       0, 0, -1,  0, 0, 2 },
  { offsetof(RECT, right), offsetof(RECT, bottom),    0, 0, -1, -1, 3, 1 },
  { offsetof(RECT, left), offsetof(RECT, bottom),     0, 0,  0, -1, 2, 0 },

  // side handles (top, right, bottom, left)
  { offsetof(RECT, left), offsetof(RECT, top),        1, 0,  0,  0, 4, 6 },
  { offsetof(RECT, right), offsetof(RECT, top),       0, 1, -1,  0, 7, 5 },
  { offsetof(RECT, left), offsetof(RECT, bottom),     1, 0,  0, -1, 6, 4 },
  { offsetof(RECT, left), offsetof(RECT, top),        0, 1,  0,  0, 5, 7 }
};

// the struct below gives us information on the layout of a RECT struct and
//  the relationship between its members
struct RECTINFO
{
  size_t nOffsetAcross;   // offset of opposite point (ie. left->right)
  int nSignAcross;        // sign relative to that point (ie. add/subtract)
};

// this array is indexed by the offset of the RECT member / sizeof(int)
static const RECTINFO RectInfo[] =
{
  { offsetof(RECT, right), +1 },
  { offsetof(RECT, bottom), +1 },
  { offsetof(RECT, left), -1 },
  { offsetof(RECT, top), -1 },
};

/////////////////////////////////////////////////////////////////////////////
// CRectTracker intitialization

int CRectTracker::m_cInstances = 0;

CRectTracker::CRectTracker(LPCRECT lpSrcRect, UINT nStyle) : m_bIsTracking(FALSE), m_nHandle(hitNothing)
{
  Construct();
  m_rect.CopyRect(lpSrcRect);
  m_nStyle = nStyle;
}

void CRectTracker::Construct()
{
  // do one-time initialization if necessary
  if ( m_cInstances == 0 )
  {
    // sanity checks for assumptions we make in the code
    ATLASSERT(sizeof(((RECT*)NULL)->left) == sizeof(int));
    ATLASSERT(offsetof(RECT, top) > offsetof(RECT, left));
    ATLASSERT(offsetof(RECT, right) > offsetof(RECT, top));
    ATLASSERT(offsetof(RECT, bottom) > offsetof(RECT, right));

    if ( HatchBrush == NULL)
    {
      // create the hatch pattern + bitmap
      WORD hatchPattern[8];
      WORD wPattern = 0x1111;
      for (int i = 0; i < 4; i++)
      {
        hatchPattern[i] = wPattern;
        hatchPattern[i+4] = wPattern;
        wPattern <<= 1;
      }
      HBITMAP hatchBitmap = CreateBitmap(8, 8, 1, 1, &hatchPattern);
      if (hatchBitmap == NULL)
      {
        throw ::GetLastError();
      }

      // create black hatched brush
      HatchBrush = CreatePatternBrush(hatchBitmap);
      DeleteObject(hatchBitmap);
      if (HatchBrush == NULL)
      {
        throw ::GetLastError();
      }
    }

    if (BlackDottedPen == NULL)
    {
      // create black dotted pen
      BlackDottedPen = CreatePen(PS_DOT, 0, RGB(0, 0, 0));
      if (BlackDottedPen == NULL)
      {
        throw ::GetLastError();
      }
    }

    // Note: all track cursors must live in same module
    HINSTANCE hInst = _Module.GetResourceInstance();

    // initialize the cursor array
    Cursors[0] = ::LoadCursor(hInst, MAKEINTRESOURCE(IDC_TRACKNWSE));
    Cursors[1] = ::LoadCursor(hInst, MAKEINTRESOURCE(IDC_TRACKNESW));
    Cursors[2] = Cursors[0];
    Cursors[3] = Cursors[1];
    Cursors[4] = ::LoadCursor(hInst, MAKEINTRESOURCE(IDC_TRACKNS));
    Cursors[5] = ::LoadCursor(hInst, MAKEINTRESOURCE(IDC_TRACKWE));
    Cursors[6] = Cursors[4];
    Cursors[7] = Cursors[5];
    Cursors[8] = ::LoadCursor(hInst, MAKEINTRESOURCE(IDC_TRACK4WAY));
    Cursors[9] = ::LoadCursor(hInst, MAKEINTRESOURCE(IDC_MOVE4WAY));

    // get default handle size from Windows profile setting
    static const TCHAR szWindows[] = _T("windows");
    static const TCHAR szInplaceBorderWidth[] =
      _T("oleinplaceborderwidth");
    HandleSize = GetProfileInt(szWindows, szInplaceBorderWidth, 4);
  }

  m_nStyle = 0;
  m_nHandleSize = HandleSize;
  m_sizeMin.cy = m_sizeMin.cx = m_nHandleSize*2;

  m_rectLast.SetRectEmpty();
  m_sizeLast.cx = m_sizeLast.cy = 0;
  m_cInstances ++;
}

CRectTracker::~CRectTracker()
{
  m_cInstances --;
  if ( m_cInstances == 0 )
  {
    // last instance has been erased. Release resources
    DeleteObject(HatchBrush);
    HatchBrush = NULL;
    DeleteObject(BlackDottedPen); 
    BlackDottedPen = NULL;
  }

}

/////////////////////////////////////////////////////////////////////////////
// CRectTracker operations

void CRectTracker::Draw(HDC hDC) const
{
  CDCHandle DC(hDC);
  // set initial DC state
  DC.SaveDC();
  DC.SetMapMode(MM_TEXT);
  DC.SetViewportOrg(0, 0);
  DC.SetWindowOrg(0, 0);  

  // get normalized rectangle
  CRect rect = m_rect;
  rect.NormalizeRect();
  LPtoDP((LPPOINT) &rect, 2);

  HPEN OldPen = NULL;
  HBRUSH OldBrush = NULL;
  int nOldROP;

  // draw lines
  if ((m_nStyle & (dottedLine|solidLine)) != 0)
  {
    if (m_nStyle & dottedLine)
      OldPen = DC.SelectPen(BlackDottedPen);
    else
      OldPen = DC.SelectStockPen(BLACK_PEN);
    OldBrush = DC.SelectStockBrush(NULL_BRUSH);
    nOldROP = DC.SetROP2(R2_COPYPEN);
    rect.InflateRect(+1, +1);   // borders are one pixel outside
    DC.Rectangle(rect.left, rect.top, rect.right, rect.bottom);
    DC.SetROP2(nOldROP);
  }

  // if hatchBrush is going to be used, need to unrealize it
  if ((m_nStyle & (hatchInside|hatchedBorder)) != 0)
    UnrealizeObject(HatchBrush);

  // hatch inside
  if ((m_nStyle & hatchInside) != 0)
  {
    HPEN TempPen = DC.SelectStockPen(NULL_PEN);
    if (OldPen == NULL)
      OldPen = TempPen;
    HBRUSH TempBrush = DC.SelectBrush(HatchBrush);
    if (OldBrush == NULL)
      OldBrush = TempBrush;
    DC.SetBkMode(TRANSPARENT);
    nOldROP = DC.SetROP2(R2_MASKNOTPEN);
    DC.Rectangle(rect.left+1, rect.top+1, rect.right, rect.bottom);
    DC.SetROP2(nOldROP);
  }

  // draw hatched border
  if ((m_nStyle & hatchedBorder) != 0)
  {
    HBRUSH TempBrush = DC.SelectBrush(HatchBrush);
    if (OldBrush == NULL)
      OldBrush = TempBrush;
    DC.SetBkMode(OPAQUE);
    CRect rectTrue;
    GetTrueRect(&rectTrue);
    DC.PatBlt(rectTrue.left, rectTrue.top, rectTrue.Width(),
      rect.top-rectTrue.top, 0x000F0001 /* Pn */);
    DC.PatBlt(rectTrue.left, rect.bottom,
      rectTrue.Width(), rectTrue.bottom-rect.bottom, 0x000F0001 /* Pn */);
    DC.PatBlt(rectTrue.left, rect.top, rect.left-rectTrue.left,
      rect.Height(), 0x000F0001 /* Pn */);
    DC.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);
        DC.FillSolidRect(rect, RGB(0, 0, 0));
      }
    }
  }

  // cleanup pDC state
  if (OldPen != NULL)
    DC.SelectPen(OldPen);
  if (OldBrush != NULL)
    DC.SelectBrush(OldBrush);
  DC.RestoreDC(-1);
}

BOOL CRectTracker::SetCursor(HWND hWnd, UINT nHitTest) const
{
  // trackers should only be in client area
  if (nHitTest != HTCLIENT)
    return FALSE;

  // convert cursor position to client co-ordinates
  CPoint point;
  GetCursorPos(&point);
  ScreenToClient(hWnd, &point);

  // do hittest and normalize hit
  int nHandle = HitTestHandles(point);
  if (nHandle < 0)
    return FALSE;

  // need to normalize the hittest such that we get proper cursors
  nHandle = NormalizeHit(nHandle);

  // handle special case of hitting area between handles
  //  (logically the same -- handled as a move -- but different cursor)
  if (nHandle == hitMiddle && !m_rect.PtInRect(point))
  {
    // only for trackers with hatchedBorder (ie. in-place resizing)
    if (m_nStyle & hatchedBorder)
      nHandle = (TrackerHit)9;
  }

  ATLASSERT(nHandle < _countof(Cursors));
  ::SetCursor(Cursors[nHandle]);
  return TRUE;
}


int CRectTracker::NormalizeHit(int nHandle) const
{
  ATLASSERT(nHandle <= 8 && nHandle >= -1);
  if (nHandle == hitMiddle || nHandle == hitNothing)
    return nHandle;
  const HANDLEINFO* pHandleInfo = &HandleInfo[nHandle];
  if (m_rect.Width() < 0)
  {
    nHandle = (TrackerHit)pHandleInfo->nInvertX;
    pHandleInfo = &HandleInfo[nHandle];
  }
  if (m_rect.Height() < 0)
    nHandle = (TrackerHit)pHandleInfo->nInvertY;
  return nHandle;
}

BOOL CRectTracker::Track(HWND hWnd, CPoint point, BOOL bAllowInvert)
{
  // 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;
  m_rectSave = m_rect;
  return TrackHandle(nHandle, hWnd, point);
}

BOOL CRectTracker::TrackRubberBand(HWND hWnd, CPoint point, BOOL bAllowInvert)
{
  // simply call helper function to track from bottom right handle
  m_rectSave = m_rect;
  m_bAllowInvert = bAllowInvert;
  CPoint lpoint = point;
  DPtoLP(&lpoint);
  AdjustPoint(&lpoint);
  m_rect.SetRect(lpoint.x, lpoint.y, lpoint.x, lpoint.y);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -