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

1592 lines
41 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//===============================
// 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);
}
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;
}