You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/Module/GeoSigmaDraw/QTransformTracker.cpp

1611 lines
41 KiB
C++

1 month ago
//===============================
// QTransformTracker.cpp
//===============================
// Version 1.0, August 20, 2003
// (c) Sjaak Priester, Amsterdam
// www.sjaakpriester.nl
#include "StdAfx.h"
#include <math.h>
#include "QTransformTracker.h"
using namespace NItem;
HCURSOR QTransformTracker::g_hCursor[10] = { 0 };
QTransformTracker::QTransformTracker(CWnd * pWnd)
: QTracker(pWnd)
{
InitParameter();
LoadDefaultCursors();
}
QTransformTracker::QTransformTracker()
: QTracker()
{
InitParameter();
//LoadDefaultCursors();
}
void QTransformTracker::InitParameter(void)
{
m_Options=OptionDefault;
m_Mode=TransformNone;
m_Handle=HandleNothing;
m_bLoaded=false;
m_bSpace=false;
m_bMapFlip=false;
m_bAlt = false;
m_colorPath=RGB(0,153,255);
m_colorCrossLine=RGB(100,100,100);
m_colorMark=RGB(192, 192, 192);
m_colorHandles=RGB(0, 0, 0);
m_colorCenter=RGB(0, 0, 0);
m_colorTrack=RGB(192, 192, 192);
m_HandleSize=8;
m_InnerMargin=0;
m_OuterMargin=0;
m_FixedSrc=0;
m_FixedDest=0;
m_StartPhi=0.0f;
m_IndicatorString=_T("");
m_bCopyObject=FALSE;
m_bOnlyMove=FALSE;
m_bCrossLine=FALSE;
}
QTransformTracker::~QTransformTracker(void)
{
Clear();
}
void QTransformTracker::SetParent(CWnd* pWnd)
{
QTracker::SetParent(pWnd);
if(pWnd)
LoadDefaultCursors();
}
void QTransformTracker::LoadDefaultCursors(void)
{
if (g_hCursor[0] != NULL) return;
return;
// Load static default cursors
HINSTANCE hInst = ::AfxFindResourceHandle( MAKEINTRESOURCE(AFX_IDC_TRACKNWSE), RT_GROUP_CURSOR );
UINT DefaultCursorIDs[] =
{
AFX_IDC_TRACKNWSE, AFX_IDC_TRACKNESW, AFX_IDC_TRACKNS, AFX_IDC_TRACKWE,
AFX_IDC_TRACK4WAY, AFX_IDC_MOVE4WAY, AFX_IDC_MOVE4WAY,
AFX_IDC_TRACK4WAY, AFX_IDC_TRACK4WAY, AFX_IDC_TRACK4WAY
};
for (int i = 0; i < sizeof(DefaultCursorIDs)/sizeof(UINT); i++)
{
if (g_hCursor[i] != NULL) continue; // already loaded by user
LoadCursor(i, DefaultCursorIDs[i], hInst);
ASSERT(g_hCursor[i]);
// If you get an assert here, there's probably something wrong
// with your resources.
}
}
int QTransformTracker::NormalizeHit(int handle)
{
int mode=TransformNone;
if (handle==HandleNothing)
return mode;
else if (handle == HandleCenter)
mode = TransformCenter;
else if (handle == HandleBody)
mode = TransformMove;
else if(IsRotateState())
{
if ((handle & 1) && (m_Options & OptionShear))
mode = TransformShear;
if (! (handle & 1) && (m_Options & OptionRotate))
mode = TransformRotate;
}
else
mode = TransformScale;
return mode;
}
bool QTransformTracker::SetTrackModeOnClick(UINT nFlags, CPoint point)
{
TRACE(_T("QTransformTracker::SetTrackModeOnClick\n"));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E2A3AC><EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF>Ƶ㣬<C6B5><E3A3AC><EFBFBD>߲<EFBFBD><DFB2>ǵ<EFBFBD><C7B5><EFBFBD>
if (m_Mode == TransformNone || (Handle)HitTest(point) != HandleBody
|| m_StartPoint != point)
{
return FALSE;
}
CSize sz = point - m_StartPoint;
//Ϊ<>˷<EFBFBD>ֹ<EFBFBD><D6B9>С<EFBFBD><D0A1><EFBFBD>ƶ<EFBFBD>Ԫ<EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵʱ<D6B5><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>
if (abs(sz.cx) < m_nAllowMovePixel && abs(sz.cy) < m_nAllowMovePixel)
{
bool bAlt = ::IsKeyDown(VK_MENU);
bool bShift = ::IsKeyDown(VK_SHIFT);
bool bCtrl = ::IsKeyDown(VK_CONTROL);
// <20><><EFBFBD><EFBFBD>º<EFBFBD>̧<EFBFBD><CCA7><EFBFBD><EFBFBD>ͬһλ<D2BB><CEBB>ʱ<EFBFBD><CAB1><EFBFBD>л<EFBFBD>״̬
if (!bShift && !bCtrl && !bAlt)
{
SetRotateState(!IsRotateState());
return TRUE;
}
}
return FALSE;
}
int QTransformTracker::OnBeginTrack(UINT nFlags, CPoint point)
{
m_nSteps = 0;
TRACE(_T("QTransformTracker::OnBeginTrack\n"));
m_Transform.Reset();
if (!m_bLoaded)
{
m_TrackResult = TrackFailed;
return TrackFailed;
}
//Handle handle = (Handle)HitTest(point);// m_Handle
if (m_Handle == HandleNothing)
{
m_TrackResult = TrackFailed;
return TrackFailed;
}
if(IsRotateState())//<2F><>ת״̬
{
if (m_Handle == HandleCenter)
m_Mode = TransformCenter;
else if (m_Handle == HandleBody)
m_Mode = TransformMove;
else
{
if ( (m_Handle & 1) && (m_Options & OptionShear )) m_Mode = TransformShear;
if (!(m_Handle & 1) && (m_Options & OptionRotate)) m_Mode = TransformRotate;
m_bAlt = false;
if (m_Mode == TransformRotate && (m_Options & OptionRotateReverseAlt)) m_bAlt ^= true;
SetFixedPoints(m_bAlt);
}
}
else
{
if (m_Handle == HandleBody || m_Handle == HandleCenter)
{
m_Mode = TransformMove;
}
else
{
m_Mode = TransformScale;
SetFixedPoints(false);
}
}
//SetCursor((int&)m_Handle);
//////////////////////////////////////////////
m_bCanMoved = false;
bool m_bDirty = false;
m_Point = point;
m_PreviousPoint = m_Point;
m_StartPoint = m_Point;
nFlags &= UpdateMouseFlags; // to be sure
//m_Handle = handle;
m_bTracking = true;
m_TrackResult = TrackContinue;
return TrackContinue;
}
int QTransformTracker::OnEndTrack(int trackResult)
{
TRACE(_T("QTransformTracker::OnEndTrack\n"));
//if (m_Mode == TransformCenter && trackResult == TrackCopy)
// trackResult = TrackSucceeded;
//else {
// trackResult = TrackFailed;
//}
if (trackResult < 0)
{
m_Transform.Reset();
::CopyMemory(m_PointDest, m_PointSrc, 5 * sizeof(POINT));
}
m_Mode = TransformNone;
m_IndicatorString.Empty();
//m_TrackResult = (TrackResult)trackResult;
//m_Handle = QTracker::HandleNothing;
return trackResult;
}
int QTransformTracker::OnMouseMessage(UINT msg, UINT nFlags, CPoint point)
{
CPoint curpoint=point;
if(IsRotateState())
{
bool bPrevAlt = m_bAlt;
m_bAlt = false;
if (m_Mode == TransformRotate && (m_Options & OptionRotateReverseAlt))
m_bAlt ^= true;
// Alt key changed; change fixed points
if (m_bAlt != bPrevAlt) SetFixedPoints(m_bAlt);
}
if (::IsKeyDown(VK_SPACE))
{
// Space bar pressed, accumulate move in m_Transform
CSize sz = point - m_PreviousPoint;
m_Transform.Translate((Gdiplus::REAL) sz.cx, (Gdiplus::REAL) sz.cy, Gdiplus::MatrixOrderAppend);
SetIndicatorString(TransformMove, curpoint, (Gdiplus::REAL) sz.cx, (Gdiplus::REAL) sz.cy);
m_bSpace = true;
return QTracker::OnMouseMessage(msg, nFlags, point);
}
if (m_bSpace) // Space bar released
{
SetFixedPoints(m_bAlt);
m_bSpace = false;
}
if(m_Mode==TransformMove)
{
//if (nFlags & MK_SHIFT) point = RestrictPoint(point, m_StartPoint);
if (::IsKeyDown(VK_SHIFT)) point = RestrictPoint(point, m_StartPoint);
CSize sz = point - m_StartPoint;
//Ϊ<>˷<EFBFBD>ֹ<EFBFBD><D6B9>С<EFBFBD><D0A1><EFBFBD>ƶ<EFBFBD>Ԫ<EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵʱ<D6B5><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>
if(IsCanMove(point,m_StartPoint))
//if(abs(sz.cx)>=m_nAllowMovePixel || abs(sz.cy)>=m_nAllowMovePixel || m_bCanMoved==true)
{
m_Transform.Reset();
m_Transform.Translate((Gdiplus::REAL) sz.cx, (Gdiplus::REAL) sz.cy);
}
else sz.SetSize(0,0);
//SetIndicatorString(TransformMove, curpoint, (Gdiplus::REAL) sz.cx, (Gdiplus::REAL) sz.cy);
}
else if (IsRotateState())
{
switch (m_Mode)//<2F><>ת״̬
{
case TransformCenter:
{
CSize sz = point - m_StartPoint;
//if (nFlags & MK_SHIFT) point = RestrictPoint(point, m_StartPoint);
if (::IsKeyDown(VK_SHIFT)) point = RestrictPoint(point, m_StartPoint);
m_PointSrc[4] = m_PointDest[4] = point;
// Center point is in m_PointSrc[4], no transformation, so Dest == Src
SetIndicatorString(TransformCenter, curpoint, (Gdiplus::REAL) sz.cx, (Gdiplus::REAL) sz.cy);
}
break;
case TransformRotate:
{
CSize sz = point - m_FixedDest;
Gdiplus::REAL phi = 180.0f * (Gdiplus::REAL)(atan2((double)sz.cy, (double)sz.cx) / PI) - m_StartPhi;
while (phi <= -180.0f) phi += 360.0f; // (-180, 180]
//if (nFlags & MK_SHIFT)
if (::IsKeyDown(VK_SHIFT))
{
int a = 15 * (int)((phi + 367.5f) / 15.0f); // multiple of 15 degrees
while (a > 180) a -= 360; // (-180, 180]
phi = (Gdiplus::REAL)a;
}
m_Transform.Reset();
m_Transform.Translate((Gdiplus::REAL) - m_FixedSrc.x, (Gdiplus::REAL) - m_FixedSrc.y);
m_Transform.Rotate(phi, Gdiplus::MatrixOrderAppend);
m_Transform.Translate((Gdiplus::REAL) m_FixedDest.x, (Gdiplus::REAL) m_FixedDest.y, Gdiplus::MatrixOrderAppend);
//SetIndicatorString(TransformRotate, curpoint, m_bMapFlip ? phi : -phi);
}
break;
case TransformShear:
{
CSize sz = point - m_FixedDest;
CSize szSrc = m_StartPoint - m_FixedSrc;
Gdiplus::REAL shearX = 0.0f;
Gdiplus::REAL shearY = 0.0f;
Gdiplus::REAL scaleX = 1.0f;
Gdiplus::REAL scaleY = 1.0f;
if (m_Handle & 2) // vertical edge
{
if (sz.cx != 0) shearY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) sz.cx;
if (szSrc.cx != 0) scaleX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) szSrc.cx;
if (!(m_Options&OptionAllowMirror) && scaleX < 0.0f) scaleX = 0.0f;
SetIndicatorString(TransformShear, curpoint, shearY * -100.0f);
}
else // horizontal edge
{
if (sz.cy != 0) shearX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) sz.cy;
if (szSrc.cy != 0) scaleY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) szSrc.cy;
if (!(m_Options&OptionAllowMirror) && scaleY < 0.0f) scaleY = 0.0f;
SetIndicatorString(TransformShear, curpoint, shearX * -100.0f);
}
m_Transform.Reset();
m_Transform.Translate((Gdiplus::REAL) - m_FixedSrc.x, (Gdiplus::REAL) - m_FixedSrc.y);
// Don't scale the other direction if Shift is pressed
// ((nFlags & MK_SHIFT) == 0) m_Transform.Scale(scaleX, scaleY, Gdiplus::MatrixOrderAppend);
if (::IsKeyDown(VK_SHIFT)) m_Transform.Scale(scaleX, scaleY, Gdiplus::MatrixOrderAppend);
m_Transform.Shear(shearX, shearY, Gdiplus::MatrixOrderAppend);
m_Transform.Translate((Gdiplus::REAL) m_FixedDest.x, (Gdiplus::REAL) m_FixedDest.y, Gdiplus::MatrixOrderAppend);
}
break;
default:
break;
}
}
else
{
switch (m_Mode)//<2F>ƶ<EFBFBD>״̬
{
case TransformScale:
{
//<2F><>ǰ<EFBFBD>϶<EFBFBD><CFB6><EFBFBD><EFBFBD>ͱ任<CDB1><E4BBBB><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>ֵ
CSize sz = point - m_FixedDest; //m_FixedDest is the selected handle point of destination rectangle
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭʼ<D4AD><CABC>ק<EFBFBD><D7A7><EFBFBD><EFBFBD>ԭʼ<D4AD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>ֵ
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ק<EFBFBD><D7A7><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ߵ<EFBFBD>֮һ <20><>m_StartPoint<6E><74><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ק<EFBFBD><D7A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CSize szSrc = m_StartPoint - m_FixedSrc; //m_FixedSrc is the selected handle point of source rectangle
Gdiplus::REAL scaleX = 1.0f;
Gdiplus::REAL scaleY = 1.0f;
if ((m_Handle & 1) == 0) // corner, scale both
{
if (szSrc.cx != 0)
scaleX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) szSrc.cx;
if (!(m_Options & OptionAllowMirror) && scaleX < 0.0f)
scaleX = 0.0f; //no allow mirror x
if (szSrc.cy != 0)
scaleY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) szSrc.cy;
if (!(m_Options & OptionAllowMirror) && scaleY < 0.0f)
scaleY = 0.0f; //no allow mirror y
//if (!(nFlags & MK_SHIFT))
if (::IsKeyDown(VK_SHIFT)) // maintain proportions, //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SHIFT<46><54>ʱ<EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
Gdiplus::REAL scaleXabs = fabsf(scaleX);
Gdiplus::REAL scaleYabs = fabsf(scaleY);
if (scaleXabs > scaleYabs) scaleX = (scaleX < 0) ? -scaleYabs : scaleYabs;
else scaleY = (scaleY < 0) ? -scaleXabs : scaleXabs;
}
// Set cursor; might be changed after flipping
int curs = (m_Handle & 2) / 2; // 0 or 1
if (m_bMapFlip) curs ^= 1;
curs ^= scaleX < 0;
curs ^= scaleY < 0;
HCURSOR h = g_hCursor[curs];
if (h) ::SetCursor(h);
}
else if ((m_Handle & 3) == 1) // horizontal edge, scale vertical
{
if (szSrc.cy != 0) scaleY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) szSrc.cy;
if (!(m_Options & OptionAllowMirror) && scaleY < 0.0f) scaleY = 0.0f;
//if (nFlags & MK_SHIFT) scaleX = scaleY; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SHIFT<46><54>ʱ<EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (::IsKeyDown(VK_SHIFT)) scaleX = scaleY; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SHIFT<46><54>ʱ<EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
else if ((m_Handle & 3) == 3) // vertical edge, scale horizontal
{
if (szSrc.cx != 0) scaleX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) szSrc.cx;
if (!(m_Options & OptionAllowMirror) && scaleX < 0.0f) scaleX = 0.0f;
//if (nFlags & MK_SHIFT) scaleY = scaleX; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SHIFT<46><54>ʱ<EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (::IsKeyDown(VK_SHIFT)) scaleY = scaleX; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SHIFT<46><54>ʱ<EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
m_Transform.Reset();
// Translate the fixed point to the origin.
m_Transform.Translate((Gdiplus::REAL) - m_FixedSrc.x, (Gdiplus::REAL) - m_FixedSrc.y, Gdiplus::MatrixOrderAppend);
// Scale the object.
m_Transform.Scale(scaleX, scaleY, Gdiplus::MatrixOrderAppend);
// Translate back to fixed point (which may be different).
m_Transform.Translate((Gdiplus::REAL)m_FixedDest.x, (Gdiplus::REAL)m_FixedDest.y, Gdiplus::MatrixOrderAppend);
}
break;
default:
break;
}
}
return QTracker::OnMouseMessage(msg, nFlags, point);
}
void QTransformTracker::SetIndicatorString(Mode mode, CPoint point, Gdiplus::REAL x, Gdiplus::REAL y)
{
int xi = (int) x;
int yi = (int) y;
CString coor;coor.Format("%d %d",point.x,point.y);
switch (mode)
{
case TransformMove:
case TransformCenter:
m_IndicatorString.Format(_T("%s DX=%lf,DY=%lf"), coor,x,y);
break;
case TransformScale:
m_IndicatorString.Format(_T("%s ScaleX=%.2f%%,ScaleY=%.2f%%"), coor,x,y);
break;
case TransformRotate:
m_IndicatorString.Format(_T("%s Rotate:%.2f\xb0"), coor, x);
break;
case TransformShear:
m_IndicatorString.Format(_T("%s Shear:%.2f%%"), coor, x);
break;
default:
ASSERT(0);
break;
}
}
void QTransformTracker::DrawFull(CDC* pDC, UINT nMode)
{
//CPoint point(0, 0);
m_Transform.Reset();
CSize sz = CPoint(0, 0) - m_PointSrc[0];
m_Transform.Translate((Gdiplus::REAL) sz.cx, (Gdiplus::REAL) sz.cy);
// Copy four untransformed points of the Track Rectangle, plus center point
::CopyMemory(m_PointDest, m_PointSrc, 5 * sizeof(POINT));
// Transform them
m_Transform.TransformPoints((Gdiplus::Point *) m_PointDest, 5);
// Draw the Track Rectangle.
CPen * pTrackPen = new CPen(PS_SOLID, 0, m_colorTrack);
CGdiObject * pOldPen = NULL;
if (pTrackPen) pOldPen = pDC->SelectObject(pTrackPen);
pDC->Polygon(m_PointDest, 4);
if (pOldPen) pDC->SelectObject(pOldPen);
delete pTrackPen;
// If a path is loaded, and it has some points...m_Transform
if (!m_ArrayPath.IsEmpty())
{
for (int i = 0; i < m_ArrayPath.GetCount(); i++)
{
m_ArrayPath[i]->TransformPoints(m_Transform);
}
CPen * pPathPen = new CPen(PS_SOLID, 0, m_colorPath);
CGdiObject * pOldPen = NULL;
if (pPathPen) pOldPen = pDC->SelectObject(pPathPen);
// CPoint pPT = m_ArrayPath.GetAt(0)->m_pPathPoints[0];
for (int i = 0; i < m_ArrayPath.GetCount(); i++)
m_ArrayPath[i]->OnUpdate(pDC, nMode);
if (pOldPen) pDC->SelectObject(pOldPen);
delete pPathPen;
}
DrawCenter(pDC, m_PointDest[4], TRUE);
m_Transform.Reset();
sz = m_PointSrc[0];
m_Transform.Translate((Gdiplus::REAL) sz.cx, (Gdiplus::REAL) sz.cy);
// Transform them
m_Transform.TransformPoints((Gdiplus::Point *) m_PointDest, 5);
// If a path is loaded, reset to start point ...
if (!m_ArrayPath.IsEmpty())
{
for (int i = 0; i < m_ArrayPath.GetCount(); i++)
m_ArrayPath[i]->m_pGraphicsPath->Transform(&m_Transform);
}
m_Transform.Reset();
}
void QTransformTracker::OnUpdate(CDC * pDC, UINT nMode)
{
//QTracker::OnUpdate(pDC,nMode);
if (m_Handle == HandleCenter)
{
DrawCenter(pDC, m_PointSrc[4], TRUE);
return;
}
if (nMode & UpdateDraw) // Apply transformation
{
// The transformed Track Rectangle and the path are cached, so they won't
// have to be transformed again when OnUpdate() is called with UpdateRemove.
// Copy four untransformed points of the Track Rectangle, plus center point
::CopyMemory(m_PointDest, m_PointSrc, 5 * sizeof(POINT));
// Transform them
m_Transform.TransformPoints((Gdiplus::Point *) m_PointDest, 5);
// If a path is loaded, and it has some points...
if(!m_ArrayPath.IsEmpty())
{
for(int i=0;i<m_ArrayPath.GetCount();i++)
m_ArrayPath[i]->TransformPoints(m_Transform);
}
}
// Draw the Track Rectangle. QTracker has set the ROP-mode to NOT-XOR.
CPen * pTrackPen = NULL;
if (m_Options & OptionTrackDotted)
{
LOGBRUSH lb;
lb.lbColor = m_colorTrack;
lb.lbHatch = 0;
lb.lbStyle = BS_SOLID;
pTrackPen = new CPen(PS_COSMETIC | PS_ALTERNATE, 1, & lb);
}
else pTrackPen = new CPen(PS_SOLID, 0, m_colorTrack);
CGdiObject * pOldPen = NULL;
if (pTrackPen) pOldPen = pDC->SelectObject(pTrackPen);
pDC->Polygon(m_PointDest, 4);
if (pOldPen) pDC->SelectObject(pOldPen);
delete pTrackPen;
if(!m_ArrayPath.IsEmpty())
{
// Draw the path. We do this in 'ordinary' gdi, because GDI+ doesn't
// understand NOT-XOR.
CPen * pPathPen = NULL;
if (m_Options & OptionPathDotted)
{
LOGBRUSH lb;
lb.lbColor = m_colorPath;
lb.lbHatch = 0;
lb.lbStyle = BS_SOLID;
pPathPen = new CPen(PS_COSMETIC | PS_ALTERNATE, 1, & lb);
}
else pPathPen = new CPen(PS_SOLID, 0, m_colorPath);
CGdiObject * pOldPen = NULL;
if (pPathPen) pOldPen = pDC->SelectObject(pPathPen);
CPoint pPT = m_ArrayPath.GetAt(0)->m_pPathPoints[0];
for(int i=0;i<m_ArrayPath.GetCount();i++)
m_ArrayPath[i]->OnUpdate(pDC,nMode);
if (pOldPen) pDC->SelectObject(pOldPen);
delete pPathPen;
}
DrawCenter(pDC, m_PointDest[4], TRUE);
if (m_bCrossLine)
{
DrawCrossLine(pDC, m_Point);
}
}
void QTransformTracker::DrawPath(CDC * pDC)
{
CPen * pPathPen = NULL;
LOGBRUSH lb;
lb.lbColor = RGB(255, 0, 0); // m_colorPath;
lb.lbHatch = 0;
lb.lbStyle = BS_SOLID;
m_colorPath = RGB(190, 88, 0);
pPathPen = new CPen(PS_SOLID, 0, m_colorPath);
CGdiObject * pOldPen = NULL;
if (pPathPen) pOldPen = pDC->SelectObject(pPathPen);
pDC->MoveTo(0, 0);
pDC->LineTo(500, 500);
for (int i = 0; i < m_ArrayPath.GetCount(); i++)
m_ArrayPath[i]->OnUpdate(pDC, UpdateDraw);
if (pOldPen) pDC->SelectObject(pOldPen);
delete pPathPen;
}
int QTransformTracker::OnKeyMessage(UINT msg, UINT nChar, UINT nRepCnt, UINT nFlags)
{
ASSERT(m_Handle != HandleNothing);
if (nChar == VK_CONTROL || nChar == VK_SPACE) SetCursor((int&)m_Handle);
return QTracker::OnKeyMessage(msg, nChar, nRepCnt, nFlags);
}
void QTransformTracker::Draw(CDC * pDC)
{
if(!m_bLoaded) return;
// if(!m_bDrawRectangle) return;
// All drawing is done in NOT-XOR mode.
int nOldRop = pDC->SetROP2(R2_NOTXORPEN);
DrawMarkRect(pDC);
DrawCenter(pDC, m_PointSrc[4], FALSE);
pDC->SetROP2(nOldRop);
}
void QTransformTracker::DrawCrossLine(CDC* pDC,CPoint point)
{
if(m_pWnd==NULL) return;
CPen* pPen = new CPen(PS_SOLID, 0, m_colorCrossLine);
CGdiObject *pOldPen = pDC->SelectObject(pPen);
CRect rt;m_pWnd->GetClientRect(rt);
int nOldRop = pDC->SetROP2(R2_NOTXORPEN);
pDC->MoveTo(point.x,rt.top);
pDC->LineTo(point.x,rt.bottom);
pDC->MoveTo(rt.left,point.y);
pDC->LineTo(rt.right,point.y);
pDC->SetROP2(nOldRop);
if(pOldPen) pDC->SelectObject(pOldPen);
delete pPen;
}
BOOL GetArrow3LPoint(CPoint p1, CPoint p2, LPPOINT pt)
{
double cosx = p1.x - p2.x;
double sinx = p1.y - p2.y;
sinx = sqrt(sinx*sinx + cosx * cosx);
if (sinx < 1e-30)
{
return FALSE;
}
cosx = cosx / sinx;
sinx = (p1.y - p2.y) / sinx;
double cy = 7;
pt[0].x = AfxGetPublicFunction()->FloatToLong(p1.x + 1.0*cy*cosx);
pt[0].y = AfxGetPublicFunction()->FloatToLong(p1.y + 1.0*cy*sinx);
pt[1].x = AfxGetPublicFunction()->FloatToLong(p1.x + 0.4*cy*sinx);
pt[1].y = AfxGetPublicFunction()->FloatToLong(p1.y - 0.4*cy*cosx);
pt[2].x = AfxGetPublicFunction()->FloatToLong(p1.x - 0.4*cy*sinx);
pt[2].y = AfxGetPublicFunction()->FloatToLong(p1.y + 0.4*cy*cosx);
return TRUE;
}
BOOL GetArrow3Point(CPoint p1,CPoint p2, CPoint* pt)
{
double cosx=p1.x-p2.x;
double sinx=p1.y-p2.y;
sinx=sqrt( sinx*sinx+cosx*cosx );
if( sinx<1e-30)
{
return FALSE;
}
cosx=cosx/sinx;
sinx=(p1.y-p2.y)/sinx;
double cy=7;
pt[0].x=AfxGetPublicFunction()->FloatToLong(p1.x+1.0*cy*cosx);
pt[0].y=AfxGetPublicFunction()->FloatToLong(p1.y+1.0*cy*sinx);
pt[1].x=AfxGetPublicFunction()->FloatToLong(p1.x+0.4*cy*sinx);
pt[1].y=AfxGetPublicFunction()->FloatToLong(p1.y-0.4*cy*cosx);
pt[2].x=AfxGetPublicFunction()->FloatToLong(p1.x-0.4*cy*sinx);
pt[2].y=AfxGetPublicFunction()->FloatToLong(p1.y+0.4*cy*cosx);
return TRUE;
}
void _PaintArrow(CXyDC& dc, CPoint p1, CPoint p2)
{
dc.GetDC()->MoveTo(p1);
dc.GetDC()->LineTo(p2);
//static CPoint pt[3];
LPPOINT pt;
pt = new POINT[3];
if (GetArrow3LPoint(p1, p2, pt))
{
dc.PaintRgn(pt, 3);
}
delete[] pt;
pt = NULL;
}
void QTransformTracker::DrawMarkRotate(CDC* pDC, CRect rect)
{
CXyDC dc; dc.Create(pDC);
CPen pen(PS_SOLID,0,RGB(0,0,0));
CPen* pOldPen=(CPen*)pDC->SelectObject(&pen);
CGdiObject * pOldBrush = pDC->SelectStockObject(BLACK_BRUSH);
rect.InflateRect(2,2);
CPoint p1,p2;
CSize sz(6,6);
CPoint cp=rect.CenterPoint();
//<2F><><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD>
p1.SetPoint(rect.left, cp.y);
p2.SetPoint(rect.left, cp.y-sz.cy/2);
_PaintArrow(dc,p2,p1);
p2.SetPoint(rect.left, cp.y+sz.cy/2);
_PaintArrow(dc,p2,p1);
//<2F>ұ<EFBFBD><D2B1>м<EFBFBD><D0BC><EFBFBD>
p1.SetPoint(rect.right, cp.y);
p2.SetPoint(rect.right, cp.y-sz.cy/2);
_PaintArrow(dc,p2,p1);
p2.SetPoint(rect.right, cp.y+sz.cy/2);
_PaintArrow(dc,p2,p1);
//<2F>ϱ<EFBFBD><CFB1>м<EFBFBD><D0BC><EFBFBD>
p1.SetPoint(cp.x, rect.top);
p2.SetPoint(cp.x-sz.cx/2, rect.top);
_PaintArrow(dc,p2,p1);
p2.SetPoint(cp.x+sz.cx/2, rect.top);
_PaintArrow(dc,p2,p1);
//<2F>±<EFBFBD><C2B1>м<EFBFBD><D0BC><EFBFBD>
p1.SetPoint(cp.x, rect.bottom);
p2.SetPoint(cp.x-sz.cx/2, rect.bottom);
_PaintArrow(dc,p2,p1);
p2.SetPoint(cp.x+sz.cx/2, rect.bottom);
_PaintArrow(dc,p2,p1);
CSize sd(1,1);
sz.SetSize(5,5);
rect.DeflateRect(1,1);
//<2F><><EFBFBD><EFBFBD>
p1.SetPoint(rect.left,rect.bottom);
p2.SetPoint(rect.left+sz.cx,rect.bottom+sd.cy);
_PaintArrow(dc,p2,p1);
p2.SetPoint(rect.left-sd.cx,rect.bottom-sz.cx);
_PaintArrow(dc,p2,p1);
//<2F><><EFBFBD><EFBFBD>
p1.SetPoint(rect.left,rect.top);
p2.SetPoint(rect.left+sz.cx,rect.top-sd.cy);
_PaintArrow(dc,p2,p1);
p2.SetPoint(rect.left-sd.cx,rect.top+sz.cx);
_PaintArrow(dc,p2,p1);
//<2F><><EFBFBD><EFBFBD>
p1.SetPoint(rect.right,rect.top);
p2.SetPoint(rect.right-sz.cx,rect.top-sd.cy);
_PaintArrow(dc,p2,p1);
p2.SetPoint(rect.right+sd.cx,rect.top+sz.cx);
_PaintArrow(dc,p2,p1);
//<2F><><EFBFBD><EFBFBD>
p1.SetPoint(rect.right,rect.bottom);
p2.SetPoint(rect.right-sz.cx,rect.bottom+sd.cy);
_PaintArrow(dc,p2,p1);
p2.SetPoint(rect.right+sd.cx,rect.bottom-sz.cx);
_PaintArrow(dc,p2,p1);
if(pOldPen) pDC->SelectObject(pOldPen);
if(pOldBrush) pDC->SelectObject(pOldBrush);
}
void QTransformTracker::DrawMarkRect(CDC * pDC)
{
ASSERT_VALID(pDC);
CGdiObject * pOldBrush = pDC->SelectStockObject(NULL_BRUSH);
CPen * pMarkPen = NULL;
if (m_Options & OptionMarkDotted)
{
LOGBRUSH lb;
lb.lbColor = m_colorMark;
lb.lbHatch = 0;
lb.lbStyle = BS_SOLID;
pMarkPen = new CPen(PS_COSMETIC | PS_ALTERNATE, 1, & lb);
}
else pMarkPen = new CPen(PS_SOLID, 0, m_colorMark);
CGdiObject * pOldPen = NULL;
if(pMarkPen) pOldPen = pDC->SelectObject(pMarkPen);
CRect rc(m_StartRect);
if(!m_bOnlyMove) pDC->Rectangle(&rc);
if(IsRotateState() && m_bEnableRotate == true)
DrawMarkRotate(pDC, rc);
else
DrawMarkRect(pDC, rc, m_bOnlyMove);
//<2F><>ÿһ<C3BF><D2BB>ѡ<EFBFBD><D1A1>Ԫ<EFBFBD>صķ<D8B5>ΧHANDLE///////////////////
if(m_ArrayPath.GetCount()>1)
{
int nOldRop = pDC->SetROP2(R2_COPYPEN);
pDC->SelectStockObject(NULL_BRUSH);
CPen penHandles(PS_SOLID, 0, m_colorPath);// m_colorMark
CPen* op = (CPen*)pDC->SelectObject(&penHandles);
for(int i=0;i<m_ArrayPath.GetCount();i++)
{
if (m_ArrayPath[i]->m_needRect)
{
rc = m_ArrayPath[i]->m_rect;
// DrawMarkRect(pDC, rc, TRUE);
pDC->Rectangle(rc);
}
}
pDC->SelectObject(op);
pDC->SelectStockObject(NULL_BRUSH);
pDC->SetROP2(nOldRop);
}
/////////////////////////////////////////////////
if(pOldPen) pDC->SelectObject(pOldPen);
if(pOldBrush) pDC->SelectObject(pOldBrush);
delete pMarkPen;
}
void QTransformTracker::DrawMarkRect(CDC* pDC, CRect rect, BOOL bNoEditMark)
{
if(bNoEditMark)
pDC->SelectStockObject(BLACK_BRUSH);
CPen penHandles(PS_SOLID, 0, m_colorHandles);
CPen* op=(CPen*)pDC->SelectObject(&penHandles);
GetPoint(rect,m_PointTemp,!bNoEditMark);
CRect rc;
for (int i = 0; i < 8; i++)
{
rc=GetHandleRect(m_PointTemp,i);
if(bNoEditMark) rc.DeflateRect(2,2);
pDC->Rectangle(rc);
}
pDC->SelectObject(op);
if(bNoEditMark)
pDC->SelectStockObject(NULL_BRUSH);
}
void QTransformTracker::DrawCenter(CDC * pDC, POINT center, bool bTrack)
{
if(IsRotateState())
{
DrawCenterRotate(pDC, center, bTrack);
return;
}
ASSERT_VALID(pDC);
if (! (m_Options & OptionCenter)) return;
CPen pen(PS_SOLID, 2, m_colorCenter);
CGdiObject * pOldPen = pDC->SelectObject(& pen);
CRect rcInside(center,center);
rcInside.InflateRect(m_HandleSize,m_HandleSize);
pDC->MoveTo(rcInside.TopLeft());
pDC->LineTo(rcInside.BottomRight());
pDC->MoveTo(rcInside.right, rcInside.top);
pDC->LineTo(rcInside.left, rcInside.bottom);
if (pOldPen) pDC->SelectObject(pOldPen);
}
void QTransformTracker::DrawCenterRotate(CDC * pDC, POINT center, bool bTrack)
{
ASSERT_VALID(pDC);
if (! (m_Options & OptionCenter)) return;
CPen pen(PS_SOLID, 0, m_colorCenter);
CGdiObject * pOldPen = pDC->SelectObject(& pen);
CRect rcInside(center, CSize(0, 0));
int d = m_HandleSize / 2;
if (bTrack) d++;
CGdiObject * pOldBrush = pDC->SelectStockObject(NULL_BRUSH);
rcInside.InflateRect(d, d);
pDC->Ellipse(& rcInside);
rcInside.InflateRect(d, d);
CRect rcOutside(rcInside);
pDC->SelectObject(pOldBrush);
rcOutside.InflateRect(m_HandleSize, m_HandleSize);
if (bTrack && (m_Options & OptionCenterMove))
{
pDC->MoveTo(rcInside.TopLeft());
pDC->LineTo(rcOutside.TopLeft());
pDC->MoveTo(rcInside.right, rcInside.top);
pDC->LineTo(rcOutside.right, rcOutside.top);
pDC->MoveTo(rcInside.BottomRight());
pDC->LineTo(rcOutside.BottomRight());
pDC->MoveTo(rcInside.left, rcInside.bottom);
pDC->LineTo(rcOutside.left, rcOutside.bottom);
}
else
{
pDC->MoveTo(center.x, rcInside.top);
pDC->LineTo(center.x, rcOutside.top);
pDC->MoveTo(rcInside.right, center.y);
pDC->LineTo(rcOutside.right, center.y);
pDC->MoveTo(center.x, rcInside.bottom);
pDC->LineTo(center.x, rcOutside.bottom);
pDC->MoveTo(rcInside.left, center.y);
pDC->LineTo(rcOutside.left, center.y);
}
if (pOldPen) pDC->SelectObject(pOldPen);
}
void QTransformTracker::Load(CRect& rc, bool bSetCenter, CDC * pDC)
{
// Remove possible old
if (pDC) Draw(pDC);
m_StartRect = rc;
m_StartRect.NormalizeRect();
m_bLoaded = !m_StartRect.IsRectEmpty();
if (!m_bLoaded)
{
return;
}
m_StartRect.InflateRect(m_InnerMargin, m_InnerMargin);
SetPoints(bSetCenter);
if (pDC) Draw(pDC);
}
void QTransformTracker::Load(Gdiplus::Rect& rect, bool bSetCenter, CDC * pDC)
{
CRect rc(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
Load(rc, bSetCenter, pDC);
}
void QTransformTracker::Load(Gdiplus::GraphicsPath& path, bool bSetCenter, CDC * pDC)
{
Clear();
CPathItem* pItem=new CPathItem;
if(!pItem->Load(path)){delete pItem;return;}
if(pItem->m_rect.IsRectEmpty()){delete pItem;return;}
Load(pItem->m_rect, bSetCenter, pDC);
m_ArrayPath.Add(pItem);
}
void QTransformTracker::AddPath(Gdiplus::GraphicsPath& path, BOOL needRect)
{
CPathItem* pItem=new CPathItem;
if(pItem->Load(path, needRect))
{
m_ArrayPath.Add(pItem);
m_bLoaded=TRUE;
// <20><><EFBFBD><EFBFBD><EFBFBD>ܾ<EFBFBD><DCBE><EFBFBD>
if (m_totalRect.IsRectEmpty()) // <20><>ʼΪ<CABC><CEAA>ʱ
{
m_totalRect = pItem->m_rect;
}
else
{
m_totalRect |= pItem->m_rect; // <20>ϲ<EFBFBD><CFB2><EFBFBD>·<EFBFBD><C2B7><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>
}
Load(m_totalRect, TRUE, NULL);
}
else
delete pItem;
}
void QTransformTracker::Clear(CDC * pDC)
{
if (pDC) Draw(pDC);
m_bLoaded = FALSE;
if(m_ArrayPath.IsEmpty()) return;
for(INT_PTR i=0;i<m_ArrayPath.GetCount();i++)
{
delete m_ArrayPath[i];
}
m_ArrayPath.RemoveAll();
m_totalRect = CRect();
}
void QTransformTracker::SetMetrics(UINT handleSize, UINT innerMargin, UINT outerMargin, CDC * pDC)
{
// Remove possible old
if (pDC) Draw(pDC);
m_StartRect.DeflateRect(m_InnerMargin, m_InnerMargin);
m_HandleSize = handleSize;
m_InnerMargin = innerMargin;
m_OuterMargin = outerMargin;
m_StartRect.InflateRect(m_InnerMargin, m_InnerMargin);
SetPoints(FALSE);
if (pDC) Draw(pDC);
}
void QTransformTracker::GetMetrics(UINT& handleSize, UINT& innerMargin, UINT& outerMargin) const
{
handleSize = m_HandleSize;
innerMargin = m_InnerMargin;
outerMargin = m_OuterMargin;
}
CRect QTransformTracker::GetInvalidateRect(void)
{
CSize sz=GetHandleSize();
CRect rt(m_StartRect);
rt.InflateRect(sz);
return rt;
}
BOOL QTransformTracker::OnSetCursor(CDC * pDC)
{
if (! m_bLoaded || ! pDC) return FALSE;
CPoint point;
::GetCursorPos(& point);
m_pWnd->ScreenToClient(& point);
pDC->DPtoLP(& point);
CSize szVPExt = pDC->GetViewportExt();
m_bMapFlip = (szVPExt.cx ^ szVPExt.cy) < 0;
int iHandle = HitTest(point);
if (iHandle == HandleNothing) return FALSE;
return SetCursor(iHandle);
}
1 month ago
int QTransformTracker::GetHandle(CDC * pDC, CPoint point)
{
if (!m_bLoaded)
{
m_Handle = Handle::HandleNothing;
return m_Handle;
}
m_bMapFlip = false;
m_Handle = (Handle)HitTest(point);
if (m_Handle == HandleNothing)
{
//m_Handle = (Handle)nHandle;
return m_Handle;
}
SetCursor((int)m_Handle);
return (int)m_Handle;
}
1 month ago
int QTransformTracker::OnSetCursor(CDC * pDC,CPoint pt)
{
if (!m_bLoaded)
{
m_Handle = Handle::HandleNothing;
return m_Handle;
}
CPoint point = pt;
//m_pWnd->ScreenToClient(&point);
//pDC->DPtoLP(&point);
//CSize szVPExt = pDC->GetViewportExt();
//m_bMapFlip = (szVPExt.cx ^ szVPExt.cy) < 0;
m_bMapFlip = false;
m_Handle = (Handle)HitTest(point);
if (m_Handle == HandleNothing)
{
//m_Handle = (Handle)nHandle;
return m_Handle;
}
// Handle<6C><65><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD>Cursor->TODO:<3A><><EFBFBD><EFBFBD>handle<6C><65>cursor
return SetCursor((int)m_Handle);
}
void QTransformTracker::SetPoints(bool bSetCenter)
{
CRect rc(m_StartRect);
rc.InflateRect(m_OuterMargin, m_OuterMargin);
m_PointSrc[0].x = m_PointSrc[3].x = rc.left;
m_PointSrc[1].x = m_PointSrc[2].x = rc.right;
m_PointSrc[0].y = m_PointSrc[1].y = rc.top;
m_PointSrc[2].y = m_PointSrc[3].y = rc.bottom;
if (bSetCenter)
m_PointSrc[4] = m_StartRect.CenterPoint();
else
m_PointSrc[4] = m_PointDest[4];
::CopyMemory(m_PointDest, m_PointSrc, 5 * sizeof(POINT));
}
void QTransformTracker::GetPoint(LPCRECT pRect, POINT* pt, BOOL bOuterMargin)
{
CRect rc(pRect);
if(bOuterMargin)
rc.InflateRect(m_OuterMargin, m_OuterMargin);
pt[0].x = pt[3].x = rc.left;
pt[1].x = pt[2].x = rc.right;
pt[0].y = pt[1].y = rc.top;
pt[2].y = pt[3].y = rc.bottom;
pt[4] = rc.CenterPoint();
}
CRect QTransformTracker::GetHandleRect(int iHandle)
{
if (iHandle == HandleBody)
return m_StartRect;
CRect rc;
rc.SetRectEmpty();
rc.OffsetRect(GetHandlePoint(m_PointSrc, iHandle));
int d = m_HandleSize / 2;
rc.InflateRect(d, d);
return rc;
}
CRect QTransformTracker::GetHandleRect(LPPOINT pPoint,int iHandle)
{
CRect rc;
rc.SetRectEmpty();
rc.OffsetRect(GetHandlePoint(pPoint, iHandle));
int d = m_HandleSize / 2;
rc.InflateRect(d, d);
return rc;
}
CRect QTransformTracker::GetHandleRect(LPPOINT pPoint)
{
CRect rc(*pPoint,*pPoint);
int d = m_HandleSize / 2;
rc.InflateRect(d, d);
return rc;
}
CPoint QTransformTracker::GetHandlePoint(LPPOINT pPoints, int iHandle)
{
// Handles are numbered clockwise, like this:
//
// HandleTopLeft HandleTop HandleTopRight
// 0 1 2
// *-----------*-----------*
// | |
// | |
// HandleLeft 7 * * 8 * 3 HandleRight
// | HandleCenter |
// | |
// *-----------*-----------*
// 6 5 4
// HandleBottomLeft HandleBottom HandleBottomRight
//
// The center point is handle 8, the HandleBody is handle 9.
if (iHandle >= 8)
return pPoints[4]; // center
int i = iHandle / 2;
if ((iHandle & 1) == 0) return pPoints[i]; // corner
int j = i + 1;
if (j > 3) j = 0;
CPoint pnt;
pnt.x = (pPoints[i].x + pPoints[j].x) / 2;
pnt.y = (pPoints[i].y + pPoints[j].y) / 2;
return pnt; // edge
}
// logical coordinates
int QTransformTracker::HitTest(CPoint point)
{
if(!this->IsLoaded()) return HandleNothing;
int i;
for (i = 0; i < 10; i++)
{
if (GetHandleRect(i).PtInRect(point))
break;
}
//<2F>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>˻<EFBFBD>һ<EFBFBD><D2BB>ֱ<EFBFBD>߶<EFBFBD>
if (IsLineForOutRect(point))
{
if (i == HandleTop || i == HandleRight ||
i == HandleBottom || i == HandleLeft)
{
i = HandleCenter;
}
}
if (i > HandleBody)
i = HandleNothing;
else if(IsRotateState())
{
if (i == HandleCenter && !(m_Options & OptionCenterMove))
i = HandleBody;
}
else
{
if (i == HandleCenter)
i = HandleBody;
}
if(!::IsKeyDown(VK_F6)) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>F6<46><36>ʱֻҪ<D6BB><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>η<EFBFBD>Χ<EFBFBD>ھͿ<DABE><CDBF>ƶ<EFBFBD>Ԫ<EFBFBD><D4AA>
{
//***<2A><>Ҫ<EFBFBD>޸<EFBFBD>:ֻҪ<D6BB><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD>ǿ<EFBFBD><C7BF>ƶ<EFBFBD><C6B6><EFBFBD> ע<>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD>
//if (i == HandleBody && !IsEmptyPath() && ! IsVisiblePath(point))
// i = HandleNothing;
}
if(::IsKeyDown('Z')) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸZʱ<5A><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɽ<EFBFBD><C9BD><EFBFBD><EFBFBD>ƶ<EFBFBD>
i = HandleBody;
if(m_bOnlyMove && i!=HandleNothing)
i = HandleBody;
return i;
}
int QTransformTracker::SetCursor(int iHandle)
{
bool bCtrl = ::IsKeyDown(VK_CONTROL);
int curs = CursorMove; // body
if(IsRotateState())
{
if (iHandle == HandleCenter && (m_Options & OptionCenterMove))
curs = CursorCenter; // center
else if (::IsKeyDown(VK_SPACE))
iHandle = HandleBody;
// if space pressed, move rectangle
if (iHandle < 8)
{
curs = (iHandle & 2) / 2; // 0 or 1
if ((iHandle & 1) == NULL) // corner
{
if (m_Options & OptionRotate || m_Mode == TransformRotate)
curs = CursorRotate; // rotate
else if (m_bMapFlip)
curs ^= 1;
}
else
{
curs += 2; // 2 or 3
if (m_Options & OptionShear || m_Mode == TransformShear)
curs += 6; // shear, 8 or 9
}
}
// If Ctrl is pressed, change CursorMove to CursorCopy
if (bCtrl && iHandle==HandleBody)
{
curs = CursorCopy; // copy
m_bCopyObject=TRUE;
}
else
m_bCopyObject=FALSE;
}
else
{
//if (::IsKeyDown(VK_SPACE)) iHandle = HandleBody;
// if space pressed, move rectangle
if (iHandle < 8)
{
curs = (iHandle & 2) / 2; // 0 or 1
if ((iHandle & 1) == NULL) // corner
{
if (m_bMapFlip) curs ^= 1;
}
else
curs += 2; // 2 or 3
}
}
// If Ctrl is pressed, change CursorMove to CursorCopy
if (bCtrl && iHandle==HandleBody)
{
curs = CursorCopy; // copy
m_bCopyObject=TRUE;
}
else
m_bCopyObject=FALSE;
//iHandle = curs;
//m_Handle = (Handle)iHandle;
return curs;
//HCURSOR h = g_hCursor[curs];
//if (h) ::SetCursor(h);
//return h != 0;
}
void QTransformTracker::SetFixedPoints(bool bAlt)
{
// If bAlt is true, fixed point is center point, otherwise it is
// the handle opposite to m_Handle.
int hFixed = bAlt ? HandleCenter : (m_Handle ^ 4); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>m_Handleʱ<65><CAB1>m_Handle<6C><65>Ӧ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>
m_FixedSrc = GetHandlePoint(m_PointSrc, hFixed); //<2F><><EFBFBD><EFBFBD>ԭʼ<D4AD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>εIJ<CEB5><C4B2><EFBFBD><EFBFBD><EFBFBD>
m_FixedDest = GetHandlePoint(m_PointDest, hFixed); //<2F><><EFBFBD>ñ任<C3B1><E4BBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>εIJ<CEB5><C4B2><EFBFBD><EFBFBD><EFBFBD>
if (m_Mode == TransformRotate)
{
CSize sz = CPoint(m_PointSrc[m_Handle / 2]) - m_FixedSrc;
m_StartPhi = 180.0f * (Gdiplus::REAL) (atan2((double)sz.cy, sz.cx)/PI);
}
}
CPoint QTransformTracker::RestrictPoint(CPoint point, CPoint pntBase)
{
// Restrict point to horizontal, vertical or diagonal with respect to pntBase
CSize d = point - pntBase;
int cxAbs = abs(d.cx);
int cyAbs = abs(d.cy);
bool bHandled = FALSE;
if (cxAbs > 2 * cyAbs) // 0 degrees
{
point.y = pntBase.y;
bHandled = true;
}
else if (cyAbs > 2 * cxAbs) // 90 degrees
{
point.x = pntBase.x;
bHandled = true;
}
if (! bHandled) // 45 degrees
{
if (cxAbs > cyAbs)
point.x = pntBase.x + ((d.cx < 0) ? -cyAbs : cyAbs);
else point.y = pntBase.y + ((d.cy < 0) ? -cxAbs : cxAbs);
}
return point;
}
// Load one of the cursors QTransformTracker will display
/* static */
bool QTransformTracker::LoadCursor(int type, UINT nResourceID, HINSTANCE hInst)
{
ASSERT(type >= 0 && type <= 10);
HCURSOR h(0);
if (nResourceID)
{
if (hInst) h = ::LoadCursor(hInst, MAKEINTRESOURCE(nResourceID));
else h = ::AfxGetApp()->LoadCursor(nResourceID);
}
g_hCursor[type] = h;
return h != 0;
}
CSize QTransformTracker::GetHandleSize(void)
{
CSize sz(m_HandleSize,m_HandleSize);
sz.cx+=m_InnerMargin;
sz.cy+=m_InnerMargin;
sz.cx+=m_OuterMargin;
sz.cy+=m_OuterMargin;
return sz;
}
bool QTransformTracker::IsLineForOutRect(CPoint point)
{
CPoint topLeftPt = GetHandlePoint(m_PointSrc, 0);
CPoint bottomRightPt = GetHandlePoint(m_PointSrc, 4);
//<2F>ǵ<EFBFBD>x<EFBFBD><78><EFBFBD><EFBFBD><EABCB8><EFBFBD><EFBFBD>ͬ <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ˮƽ<CBAE><C6BD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD><CBBB><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ֱ<EFBFBD>߶<EFBFBD>
if (abs(topLeftPt.x - bottomRightPt.x) < 3)
return true;
if (abs(topLeftPt.y - bottomRightPt.y) < 3)
return true;
return false;
}
BOOL QTransformTracker::IsCopy(void)
{
return m_bCopyObject;
}
void QTransformTracker::SetOnlyMove(BOOL bOnlyMove)
{
m_bOnlyMove=bOnlyMove;
}
QTransformTracker::CPathItem::CPathItem()
{
m_pGraphicsPath=NULL;
m_pPathPoints=NULL;
m_pPathTypes=NULL;
m_pDrawPath = nullptr;
m_needRect = FALSE;
}
QTransformTracker::CPathItem::~CPathItem()
{
Clear();
}
BOOL QTransformTracker::CPathItem::Load(Gdiplus::GraphicsPath& path, BOOL needRect/* = FALSE*/)
{
Clear();
m_pGraphicsPath = path.Clone();
if(!m_pGraphicsPath) return FALSE;
int n = path.GetPointCount();
if (n>0)
{
// Reserve space for path points...
m_pPathPoints = new POINT[n];
// ... and for point types
m_pPathTypes = new BYTE[n];
// Get the point types. We'll retrieve the points in OnUpdate().
if (m_pPathTypes)
path.GetPathTypes(m_pPathTypes, n);
if(m_pPathPoints==NULL || m_pPathTypes==NULL)
{
Clear();
return FALSE;
}
}
this->m_needRect = needRect;
Gdiplus::Rect rt;
path.GetBounds(&rt);
//<<3C><>ʱ<EFBFBD>޸<EFBFBD>Bug:ѡ<><D1A1>ͼԪ<CDBC><D4AA><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>Ŵ<EFBFBD><C5B4><EFBFBD>С ѡ<><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B6BC><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>Ͻ<EFBFBD>>
if (rt.GetLeft() == 0 && rt.GetRight() == 1)
return TRUE;
//<2F><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5>ظ<EFBFBD> <20><><EFBFBD>³<EFBFBD><C2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//</<2F><>ʱ<EFBFBD>޸<EFBFBD>Bug>
m_rect.SetRect(rt.GetLeft(),rt.GetTop(),rt.GetRight(),rt.GetBottom());
m_rect.NormalizeRect();
// TRACE("RECT:L=%d,T=%d,R=%d,B=%d\n", rt.GetLeft(), rt.GetTop(), rt.GetRight(), rt.GetBottom());
return TRUE;
}
void QTransformTracker::CPathItem::Clear(void)
{
if (m_pGraphicsPath) delete m_pGraphicsPath;
m_pGraphicsPath = NULL;
if (m_pDrawPath != nullptr)
{
delete m_pDrawPath;
m_pDrawPath = nullptr;
}
if (m_pPathPoints) delete[] m_pPathPoints;
m_pPathPoints = NULL;
if (m_pPathTypes) delete[] m_pPathTypes;
m_pPathTypes = NULL;
}
Gdiplus::Status QTransformTracker::CPathItem::TransformPoints(Gdiplus::Matrix& transform)
{
if (m_pGraphicsPath==NULL) return Gdiplus::GenericError;
int nPathPoints = m_pGraphicsPath->GetPointCount();
if(nPathPoints<=0) return Gdiplus::GenericError;
//if (m_pDrawPath != nullptr)
//{
// delete m_pDrawPath;
//}
//m_pDrawPath = m_pGraphicsPath->Clone();
//return m_pDrawPath->Transform(&transform);
// ...refresh the points...
m_pGraphicsPath->GetPathPoints((Gdiplus::Point*)m_pPathPoints, nPathPoints);
// ... and transform them too.
return transform.TransformPoints((Gdiplus::Point*)m_pPathPoints, nPathPoints);
}
void QTransformTracker::CPathItem::GeneratePoints()
{
if (m_pGraphicsPath == NULL) return;
int nPathPoints = m_pGraphicsPath->GetPointCount();
if (nPathPoints <= 0) return;
// ...refresh the points...
m_pGraphicsPath->GetPathPoints((Gdiplus::Point*)m_pPathPoints, nPathPoints);
}
Gdiplus::Status QTransformTracker::CPathItem::TransformPointsOnly(Gdiplus::Matrix& transform)
{
if (m_pGraphicsPath == NULL) return Gdiplus::GenericError;
int nPathPoints = m_pGraphicsPath->GetPointCount();
if (nPathPoints <= 0) return Gdiplus::GenericError;
// transform them.
return transform.TransformPoints((Gdiplus::Point*)m_pPathPoints, nPathPoints);
}
void QTransformTracker::CPathItem::OnDrawFull(CDC* pDC)
{
int nPathPoints = m_pGraphicsPath->GetPointCount();
if (nPathPoints <= 0) return;
LOGPEN logpen;
pDC->GetCurrentPen()->GetLogPen(&logpen);
COLORREF color = logpen.lopnColor;
Gdiplus::Color gdipColor(255, 0, 0, 255);
gdipColor.SetFromCOLORREF(color);
Gdiplus::Graphics graphics(pDC->m_hDC);
Gdiplus::Pen curPen(gdipColor, logpen.lopnWidth.x);//logpen.lopnWidth.x
graphics.DrawPath(&curPen, m_pGraphicsPath); //m_pGraphicsPath
}
void QTransformTracker::CPathItem::OnUpdate(CDC* pDC, UINT nMode)
{
// Next is a variation of code in the MFC documentation
// for CDC::BeginPath(). Draw a GDI+ GraphicsPath in gdi.
// We could have used CDC::PolyDraw(), but it isn't supported on Win98 and WinME.
int nPathPoints = m_pGraphicsPath->GetPointCount();
if(nPathPoints<=0) return;
//LOGPEN logpen;
//pDC->GetCurrentPen()->GetLogPen(&logpen);
//COLORREF color = logpen.lopnColor;
//Color gdipColor(255, 0, 0, 255);
//gdipColor.SetFromCOLORREF(color);
//Gdiplus::Graphics graphics(pDC->m_hDC);
//Gdiplus::Pen curPen(gdipColor, 8);//logpen.lopnWidth.x
//graphics.DrawPath(&curPen, m_pDrawPath); //m_pGraphicsPath
int i;
LPPOINT pLastMoveTo = NULL;
for (i = 0; i < nPathPoints; i++)
{
BYTE type = m_pPathTypes[i];
type &= ~(Gdiplus::PathPointTypeDashMode | Gdiplus::PathPointTypePathMarker);
switch(type)
{
case Gdiplus::PathPointTypeStart:
if (pLastMoveTo && i > 0) pDC->LineTo(* pLastMoveTo);
pDC->MoveTo(m_pPathPoints[i]);
//pLastMoveTo = & m_pPathPoints[i];
break;
case Gdiplus::PathPointTypeLine | Gdiplus::PathPointTypeCloseSubpath:
pDC->LineTo(m_pPathPoints[i]);
if (pLastMoveTo) pDC->LineTo(* pLastMoveTo);
pLastMoveTo = NULL;
break;
case Gdiplus::PathPointTypeLine:
pDC->LineTo(m_pPathPoints[i]);
break;
case Gdiplus::PathPointTypeBezier | Gdiplus::PathPointTypeCloseSubpath:
pDC->PolyBezierTo(& m_pPathPoints[i], 3);
i += 2;
if (pLastMoveTo) pDC->LineTo(* pLastMoveTo);
pLastMoveTo = NULL;
break;
case Gdiplus::PathPointTypeBezier:
pDC->PolyBezierTo(&m_pPathPoints[i], 3);
i += 2;
break;
default:
break;
}
}
////if (pLastMoveTo && i > 1) pDC->LineTo(* pLastMoveTo);
}
BOOL QTransformTracker::IsEmptyPath(void)
{
if(m_ArrayPath.IsEmpty()) return TRUE;
return FALSE;
}
BOOL QTransformTracker::IsVisiblePath(CPoint point)
{
for(INT_PTR i=0;i<m_ArrayPath.GetCount();i++)
{
if(m_ArrayPath[i]->IsVisiblePath(point))return TRUE;
}
return FALSE;
}
BOOL QTransformTracker::CPathItem::IsVisiblePath(const CPoint& point)
{
return m_pGraphicsPath->IsVisible(point.x, point.y);
}
void QTransformTracker::SetCrossLineState(BOOL bView)
{
this->m_bCrossLine=bView;
}
void QTransformTracker::SetCrossLineColor(COLORREF color)
{
this->m_colorCrossLine=color;
}