//=============================== // QTransformTracker.cpp //=============================== // Version 1.0, August 20, 2003 // (c) Sjaak Priester, Amsterdam // www.sjaakpriester.nl #include "StdAfx.h" #include #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")); // 点击的是选择以外,或者点击的是控制点,或者不是点击 if (m_Mode == TransformNone || (Handle)HitTest(point) != HandleBody || m_StartPoint != point) { return FALSE; } CSize sz = point - m_StartPoint; //为了防止不小心移动元素,当超过该值时才起作用(允许移动像素个数) 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); // 鼠标按下和抬起在同一位置时,切换状态 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())//旋转状态 { 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; //为了防止不小心移动元素,当超过该值时才起作用(允许移动像素个数) 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)//旋转状态 { 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)//移动状态 { case TransformScale: { //当前拖动点和变换后的不动点的差值 CSize sz = point - m_FixedDest; //m_FixedDest is the selected handle point of destination rectangle //计算出原始拖拽点和原始的不动点的差值 //如果拖拽的是四个角点和四个边点之一 则m_StartPoint近似等于这个拖拽点坐标 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, //当按下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键时等比例缩放 if (::IsKeyDown(VK_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键时等比例缩放 if (::IsKeyDown(VK_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); } 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;iTransformPoints(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;iOnUpdate(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(); //左边中间点 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); //右边中间点 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); //上边中间点 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); //下边中间点 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); //左下 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); //左上 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); //右上 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); //右下 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); //画每一个选中元素的范围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;im_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; // 更新总矩形 if (m_totalRect.IsRectEmpty()) // 初始为空时 { m_totalRect = pItem->m_rect; } else { m_totalRect |= pItem->m_rect; // 合并新路径的矩形 } 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;iScreenToClient(& 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::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; } 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完成,计算Cursor->TODO:分离handle与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; } //判断外包矩形是否退化一条直线段 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)) //当按下F6键时只要在最大矩形范围内就可移动元素 { //***重要修改:只要鼠标点在外包矩形内 就认为是可移动的 注释调下面这两句代码就可实现这个功能点 //if (i == HandleBody && !IsEmptyPath() && ! IsVisiblePath(point)) // i = HandleNothing; } if(::IsKeyDown('Z')) //当按下字母Z时,不管是点击哪里都可进行移动 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); //计算出移动m_Handle时,m_Handle对应的不动点 m_FixedSrc = GetHandlePoint(m_PointSrc, hFixed); //获得原始外包矩形的不动点 m_FixedDest = GetHandlePoint(m_PointDest, hFixed); //获得变换后的外包矩形的不动点 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); //角点x坐标几乎相同 可认为是水平线 所以外包矩形退化成了一条直线段 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); //<临时修复Bug:选择图元,绘制出的选择框,无论怎么放大缩小 选择框的起点都在屏幕左上角> if (rt.GetLeft() == 0 && rt.GetRight() == 1) return TRUE; //根本原因可能是数据点重复 导致出现了这个问题。 // 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;iIsVisiblePath(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; }