class CCropTracker
: public CRectTracker
{
public:
CCropTracker()
{
m_fRatio = 0.;
m_rcRange.SetRectEmpty();
m_rect.SetRectEmpty();
m_bKeepAspectRatio = FALSE;
}
public:
void Draw(CDC* pDC) const
{
CRectTracker::Draw(pDC);
// draw resize handles
if ((m_nStyle & (resizeInside|resizeOutside)) != 0)
{
CRect rect = m_rect;
rect.NormalizeRect();
UINT mask = GetHandleMask();
for (int i = 0; i < 8; ++i)
{
if (mask & (1<<i))
{
GetHandleRect((TrackerHit)i, &rect);
pDC->FillSolidRect(rect, RGB(255, 0, 0));
}
}
}
}
BOOL SetCursor(CWnd* pWnd, 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);
pWnd->ScreenToClient(&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);
if(nHandle == 0 || nHandle == 2)
{
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
}
else if(nHandle == 1 || nHandle == 3)
{
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
}
else if(nHandle == 4 || nHandle == 6)
{
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENS)));
}
else if(nHandle == 5 || nHandle == 7)
{
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
}
else
{
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEALL)));
}
return TRUE;
}
protected:
virtual void AdjustRect(int nHandle, LPRECT lpRect)
{
CRectTracker::AdjustRect(nHandle, lpRect);
if(m_rcRange.IsRectEmpty() || nHandle == hitMiddle)
return;
if(m_rect.left < m_rcRange.left)
m_rect.left = m_rcRange.left;
if(m_rect.right > m_rcRange.right)
m_rect.right = m_rcRange.right;
if(m_rect.top < m_rcRange.top)
m_rect.top = m_rcRange.top;
if(m_rect.bottom > m_rcRange.bottom)
m_rect.bottom = m_rcRange.bottom;
if(m_bKeepAspectRatio)
{
switch(nHandle)
{
case hitTop:
case hitBottom:
{
int nWidth = m_rect.Height() * m_rcRange.Width() / m_rcRange.Height();
int dx = (nWidth - m_rect.Width()) / 2;
m_rect.left -= dx;
m_rect.right += dx;
}
break;
break;
case hitLeft:
case hitRight:
{
int nHeight = m_rect.Width() * m_rcRange.Height() / m_rcRange.Width();
int dy = (nHeight - m_rect.Height()) / 2;
m_rect.top -= dy;
m_rect.bottom += dy;
}
break;
case hitTopLeft:
{
if(m_rect.Height() == 0)
break;
float fRatio = (float)m_rect.Width() / m_rect.Height();
if(fRatio - m_fRatio > 0.001)
{
int nHeight = m_rect.Width() * m_rcRange.Height() / m_rcRange.Width();
int dy = nHeight - m_rect.Height();
m_rect.top -= dy;
}
else
{
int nWidth = m_rect.Height() * m_rcRange.Width() / m_rcRange.Height();
int dx = nWidth - m_rect.Width();
m_rect.left -= dx;
}
}
break;
case hitTopRight:
{
if(m_rect.Height() == 0)
break;
float fRatio = (float)m_rect.Width() / m_rect.Height();
if(fRatio - m_fRatio > 0.001)
{
int nHeight = m_rect.Width() * m_rcRange.Height() / m_rcRange.Width();
int dy = nHeight - m_rect.Height();
m_rect.top -= dy;
}
else
{
int nWidth = m_rect.Height() * m_rcRange.Width() / m_rcRange.Height();
int dx = nWidth - m_rect.Width();
m_rect.right += dx;
}
}
break;
case hitBottomLeft:
{
if(m_rect.Height() == 0)
break;
float fRatio = (float)m_rect.Width() / m_rect.Height();
if(fRatio - m_fRatio > 0.001)
{
int nHeight = m_rect.Width() * m_rcRange.Height() / m_rcRange.Width();
int dy = nHeight - m_rect.Height();
m_rect.bottom += dy;
}
else
{
int nWidth = m_rect.Height() * m_rcRange.Width() / m_rcRange.Height();
int dx = nWidth - m_rect.Width();
m_rect.left -= dx;
}
}
break;
case hitBottomRight:
{
if(m_rect.Height() == 0)
break;
float fRatio = (float)m_rect.Width() / m_rect.Height();
if(fRatio - m_fRatio > 0.001)
{
int nHeight = m_rect.Width() * m_rcRange.Height() / m_rcRange.Width();
int dy = nHeight - m_rect.Height();
m_rect.bottom += dy;
}
else
{
int nWidth = m_rect.Height() * m_rcRange.Width() / m_rcRange.Height();
int dx = nWidth - m_rect.Width();
m_rect.right += dx;
}
}
break;
}
}
}
virtual void OnChangedRect(const CRect& rectOld)
{
if(m_rcRange.IsRectEmpty())
return;
if(m_rect.left < m_rcRange.left)
m_rect.OffsetRect(m_rcRange.left - m_rect.left, 0);
if(m_rect.top < m_rcRange.top)
m_rect.OffsetRect(0, m_rcRange.top - m_rect.top);
if(m_rect.right > m_rcRange.right)
m_rect.OffsetRect(m_rcRange.right - m_rect.right, 0);
if(m_rect.bottom > m_rcRange.bottom)
m_rect.OffsetRect(0, m_rcRange.bottom - m_rect.bottom);
}
public:
float m_fRatio;
CRect m_rcRange;
BOOL m_bKeepAspectRatio;
};