#include "stdafx.h" #include "HTrackerTransform.h" HTrackerTransform::HTrackerTransform() :m_handle(0) ,m_bDrag(false) ,m_bCanMoved(false) ,m_nAllowMovePixel(5) ,m_kind(HTRACKER_TRANSFORM_KIND_SCALE) { m_StartPhi = 0.0f; m_Transform.Reset(); } //参数:mousePt 开始拖拽时,鼠标的坐标. void HTrackerTransform::Init(int handle, const CRect & boundRect, CPoint mousePt) { m_bDrag = true; m_bCanMoved = false; m_StartPhi = 0.0f; m_StartPoint = mousePt; if (handle == 8) //平移 m_kind = HTRACKER_TRANSFORM_KIND_MOVE; else m_kind = HTRACKER_TRANSFORM_KIND_SCALE; m_Transform.Reset(); m_boundRect = boundRect; m_calculator.Calculate(m_boundRect); m_handle = handle; SetFixedPoints(); } void HTrackerTransform::Draging(CPoint mousePt) { if (m_bDrag == false) return; if (m_kind == HTRACKER_TRANSFORM_KIND_SCALE) Scale(mousePt); else if (m_kind == HTRACKER_TRANSFORM_KIND_MOVE) Move(mousePt); else if (m_kind == HTRACKER_TRANSFORM_KIND_ROTATION) Rotate(mousePt); else //KIND_SHEAR Shear(mousePt); } void HTrackerTransform::EndDrag() { m_bDrag = false; m_Transform.Reset(); m_handle = 0; m_bCanMoved = false; m_StartPhi = 0.0f; m_kind = HTRACKER_TRANSFORM_KIND_SCALE; } Gdiplus::Matrix * HTrackerTransform::GetMatrix() { return &m_Transform; } void HTrackerTransform::SetKind(HTRACKER_TRANSFORM_KIND kind) { m_kind = kind; SetFixedPoints(); } //函数功能:设置选中的handle对应的不动点。 // HandleTopLeft HandleTop HandleTopRight // 0 1 2 // *-----------*-----------* // | | // | | // HandleLeft 7 * * 8 * 3 HandleRight // | HandleCenter | // | | // *-----------*-----------* // 6 5 4 //拖拽Handle时的不动点 //拖拽0Handle时,对应的不动点为4。拖拽1Handle时,对应的不动点为5。依次为2-->6,3-->7, //4-->0,5-->1,6-->2,7-->3. //handle ^ 4, 会找到对应的不动点。 void HTrackerTransform::SetFixedPoints() { //m_handle的范围:[0,8] if (m_handle < 0 || m_handle>8) return ; int hFixed = m_handle ^ 4; //m_FixedSrc = GetHandlePoint(m_PointSrc, hFixed); //m_FixedDest = GetHandlePoint(m_PointDest, hFixed); m_FixedSrc = m_calculator.GetHandlePoint(hFixed); m_FixedDest = m_FixedSrc; if (m_kind == HTRACKER_TRANSFORM_KIND_ROTATION) { CSize sz = CPoint(m_calculator.Test(m_handle / 2)) - m_FixedSrc; m_StartPhi = 180.0f * (Gdiplus::REAL) (atan2((double)sz.cy, sz.cx) / PI); } } //参数:point 鼠标点 void HTrackerTransform::Scale(CPoint & point) { //m_FixedDest is the selected handle point of destination rectangle CSize sz = point - m_FixedDest; //m_FixedSrc is the selected handle point of source rectangle CSize szSrc = m_StartPoint - m_FixedSrc; Gdiplus::REAL scaleX = 1.0f; Gdiplus::REAL scaleY = 1.0f; if ((m_handle & 1) == 0) //偶数点为角点,X,Y方向缩放。 { 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)) // maintain proportions, //当按下SHIFT键时等比例缩放 // { // 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; //当按下SHIFT键时等比例缩放 } 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; //当按下SHIFT键时等比例缩放 } 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); } void HTrackerTransform::Move(CPoint & point) { CSize sz = point - m_StartPoint; //为了防止不小心移动元素,当超过该值时才起作用(允许移动像素个数) if (IsCanMove(point, m_StartPoint)) { m_Transform.Reset(); m_Transform.Translate((Gdiplus::REAL)sz.cx, (Gdiplus::REAL)sz.cy); } } bool HTrackerTransform::IsCanMove(const CPoint& nPrevPoint, const CPoint& nCurPoint) { if (m_bCanMoved) return true; CSize sz = nCurPoint - nPrevPoint; //为了防止不小心移动元素,当超过该值时才起作用(允许移动像素个数) if (abs(sz.cx) >= m_nAllowMovePixel || abs(sz.cy) >= m_nAllowMovePixel) { m_bCanMoved = true; return true; } return false; } void HTrackerTransform::Rotate(CPoint & point) { 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] 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); } void HTrackerTransform::Shear(CPoint & point) { 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; } 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; } 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 //if ((nFlags & MK_SHIFT) == 0) 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); }