#include "stdafx.h" #include "HTracker.h" #include "SigmaDoc.h" #include "ScaleMotionGraphDrawer.h" #include "PanMotionGraphDrawer.h" #include "RotationMotionGraphDrawer.h" #include "ShearMotionGraphDrawer.h" #include "SelectedItemMotionGraphDrawer.h" bool GraphItemTransform(Gdiplus::Matrix * pMat, CPositionList & selectionSet, CSigmaDoc * pDoc); //Tracker的状态 //未拖拽状态 //拖拽状态 //未拖拽状态的条件:用户刚选中图元 //拖拽状态: //进入拖拽状态的条件:[鼠标左键单击]且[选择集不空]且[击中Handle],简化为:[鼠标左键单击]且[击中Handle] //退出拖拽状态的条件:[鼠标左键松开]/[鼠标移动]且[未击中Handle] //隐藏状态的条件:[鼠标左键下按或抬起]且[未击中Handle] HTracker::HTracker() :m_status(HTRACKER_STATUS_HIDE), m_HandleSize(12), m_pDoc(NULL), m_motionCount(0), m_transformKind(HTRACKER_TRANSFORM_KIND_SCALE) { m_pScaleMotionGraphDrawer = new ScaleMotionGraphDrawer(); m_pPanMotionGraphDrawer = new PanMotionGraphDrawer(); m_pRotationMotionGraphDrawer = new RotationMotionGraphDrawer() ; m_pShearMotionGraphDrawer = new ShearMotionGraphDrawer(); m_pTMGDrawer = m_pScaleMotionGraphDrawer; m_pSIMGDrawer = new SelectedItemMotionGraphDrawer(); } HTracker::~HTracker() { delete m_pSIMGDrawer; m_pSIMGDrawer = NULL; delete m_pScaleMotionGraphDrawer; m_pScaleMotionGraphDrawer = NULL; delete m_pPanMotionGraphDrawer; m_pPanMotionGraphDrawer = NULL; delete m_pRotationMotionGraphDrawer; m_pRotationMotionGraphDrawer = NULL; delete m_pShearMotionGraphDrawer; m_pShearMotionGraphDrawer = NULL; } bool HTracker::Create(CSigmaDoc * pDoc, CPositionList & selectionSet) { if (selectionSet.IsEmpty() || pDoc == NULL) return false; m_boundRect.SetRectEmpty(); m_pDoc = pDoc; m_motionCount = 0; m_switch.Reset(); m_drawer.Reset(); m_transformKind = HTRACKER_TRANSFORM_KIND_SCALE; CopySelectionSet(selectionSet); m_pSIMGDrawer->Init(pDoc, &selectionSet); m_pTMGDrawer = m_pScaleMotionGraphDrawer; m_pTMGDrawer->SetSIMGDrawer(m_pSIMGDrawer); m_pTMGDrawer->CopyMatrix(m_trackerTransform.GetMatrix()); if (m_bound.CreateBoundRect(pDoc, selectionSet, m_boundRect) == false) return false; m_handleCalctor.Calculate(m_boundRect); return true; } void HTracker::LButtonDown(int mouseX, int mouseY) { HTRACKER_HANDLE_KIND handleKind = HitTest(mouseX, mouseY); m_motionCount = 0; if (handleKind == HTRACKER_HANDLE_KIND_INVALID) { m_status = HTRACKER_STATUS_HIDE; return; } m_pTMGDrawer->LButtonDown(mouseX, mouseY); m_switch.HitHandle(); //击中Handle,进入拖拽状态 m_status = HTRACKER_STATUS_DRAGING; CPoint mousePt(mouseX, mouseY); m_trackerTransform.Init((int)handleKind, m_boundRect, mousePt); //缩放或平移变换 m_transformKind = JudgeTransformKind(handleKind); ChangeGraphDrawer(); ChangeHtrackerDrawerState(); } void HTracker::MouseMove(CDC * pDC, int mouseX, int mouseY) { if (m_status == HTRACKER_STATUS_HIDE) return; if (m_status == HTRACKER_STATUS_NOT_DRAG) return; CPoint mousePt(mouseX, mouseY); m_switch.MouseMove(); m_trackerTransform.SetKind(this->m_transformKind); m_trackerTransform.Draging(mousePt); //之前处于拖拽状态 //判断退出拖拽状态的条件 //1、鼠标左键处于释放状态 //2、鼠标点不在Handle上 //一旦判断出不在拖拽状态,则说明刚推出拖拽状态 HTRACKER_HANDLE_KIND handleKind = HitTest(mouseX, mouseY); SHORT lbttonStatus = ::GetAsyncKeyState(VK_LBUTTON); if (handleKind == HTRACKER_HANDLE_KIND_INVALID && lbttonStatus == 0) { m_status = HTRACKER_STATUS_NOT_DRAG; //保持未拖拽状态的原因是,程序要继续绘制出tracker. GraphItemTransform(m_trackerTransform.GetMatrix(), m_selectionSet, m_pDoc); m_trackerTransform.EndDrag(); return; } m_motionCount++; if (m_motionCount == 1) { m_drawer.Draw(pDC, m_boundRect); //擦掉tracker m_pTMGDrawer->FirstDraw(pDC, m_trackerTransform.GetMatrix(), mouseX, mouseY); } else m_pTMGDrawer->Draw(pDC, m_trackerTransform.GetMatrix(), mouseX, mouseY); } void HTracker::LButtonUp(int mouseX, int mouseY) { //进入旋转切错状态的条件: //在Handle上先按左键.在鼠标抬起时,鼠标没有移动. HTRACKER_HANDLE_KIND handleKind = HitTest(mouseX, mouseY); if (m_motionCount == 0) { m_switch.ButtonUp(handleKind); m_transformKind = JudgeTransformKind(handleKind); } ChangeGraphDrawer(); ChangeHtrackerDrawerState(); m_status = HTRACKER_STATUS_NOT_DRAG; m_motionCount = 0; GraphItemTransform(m_trackerTransform.GetMatrix(), m_selectionSet, m_pDoc); m_pSIMGDrawer->Init(m_pDoc, &m_selectionSet); m_bound.CreateBoundRect(m_pDoc, m_selectionSet, m_boundRect); m_trackerTransform.EndDrag(); } void HTracker::Draw(CDC * pDC) { if (m_boundRect.IsRectEmpty()) return; CRect boundRect; TranslateBoundRect(boundRect); m_drawer.Draw(pDC, boundRect); m_handleCalctor.Calculate(boundRect); } bool HTracker::IsDraging() { return m_status == HTRACKER_STATUS_DRAGING; } void HTracker::Reset() { m_status = HTRACKER_STATUS_HIDE; m_selectionSet.RemoveAll(); m_boundRect.SetRectEmpty(); m_handleCalctor.Reset(); m_trackerTransform.EndDrag(); m_motionCount = 0; m_switch.Reset(); } HTRACKER_HANDLE_KIND HTracker::HitTest(int mouseX, int mouseY) { if (m_selectionSet.IsEmpty()) return HTRACKER_HANDLE_KIND_INVALID; CPoint point(mouseX, mouseY); int i = -1; for (i = 0; i < 9; i++) { if (m_handleCalctor.GetHandleRect(i).PtInRect(point)) break; } if (i == -1) return HTRACKER_HANDLE_KIND_INVALID; //i的取值范围:[0,8] return HTRACKER_HANDLE_KIND(i); } bool HTracker::IsRotateAndShearState() { return m_switch.IsRotationAndShear(); } void HTracker::CopySelectionSet(CPositionList & selectionSet) { m_selectionSet.RemoveAll(); m_selectionSet.AddTail(&selectionSet); } void HTracker::TranslateBoundRect(CRect & boundRectOut) { //角点与索引的对应关系 // 0----------1 // | | // | | // 3----------2 Gdiplus::Point cornerPts[4]; cornerPts[0].X = cornerPts[3].X = m_boundRect.left; cornerPts[0].Y = cornerPts[1].Y = m_boundRect.top; cornerPts[1].X = cornerPts[2].X = m_boundRect.right; cornerPts[2].Y = cornerPts[3].Y = m_boundRect.bottom; Gdiplus::Matrix * matrix = m_trackerTransform.GetMatrix(); matrix->TransformPoints(cornerPts, 4); boundRectOut.SetRect(cornerPts[0].X, cornerPts[0].Y, cornerPts[2].X, cornerPts[2].Y); } //只有在LButtonDown和LButtonUp中有效 HTRACKER_TRANSFORM_KIND HTracker::JudgeTransformKind(HTRACKER_HANDLE_KIND kind) { if (kind == HTRACKER_HANDLE_KIND_INVALID) return HTRACKER_TRANSFORM_KIND_SCALE; if (kind == HTRACKER_HANDLE_KIND_CENTER) return HTRACKER_TRANSFORM_KIND_MOVE; if (m_switch.IsRotationAndShear()) { switch (kind) { case HTRACKER_HANDLE_KIND_TOP_LEFT: case HTRACKER_HANDLE_KIND_TOP_RIGHT: case HTRACKER_HANDLE_KIND_BOTTOM_RIGHT: case HTRACKER_HANDLE_KIND_BOTTOM_LEFT: return HTRACKER_TRANSFORM_KIND_ROTATION; case HTRACKER_HANDLE_KIND_TOP: case HTRACKER_HANDLE_KIND_RIGTH: case HTRACKER_HANDLE_KIND_BOTTOM: case HTRACKER_HANDLE_KIND_LEFT: return HTRACKER_TRANSFORM_KIND_SHEAR; } return HTRACKER_TRANSFORM_KIND_SHEAR; } return HTRACKER_TRANSFORM_KIND_SCALE; } void HTracker::ChangeGraphDrawer() { switch (m_transformKind) { case HTRACKER_TRANSFORM_KIND_SCALE: m_pTMGDrawer = m_pScaleMotionGraphDrawer; break; case HTRACKER_TRANSFORM_KIND_MOVE: m_pTMGDrawer = m_pPanMotionGraphDrawer; break; case HTRACKER_TRANSFORM_KIND_ROTATION: m_pTMGDrawer = m_pRotationMotionGraphDrawer; break; case HTRACKER_TRANSFORM_KIND_SHEAR: m_pTMGDrawer = m_pShearMotionGraphDrawer; break; default: m_pTMGDrawer = m_pScaleMotionGraphDrawer; } m_pTMGDrawer->SetSIMGDrawer(m_pSIMGDrawer); m_pTMGDrawer->CopyMatrix(m_trackerTransform.GetMatrix()); m_pTMGDrawer->SetBoundRect(m_boundRect); } void HTracker::ChangeHtrackerDrawerState() { //如果是平移状态,则不改变drawer的旋转状态。 //因为在旋转和非旋转状态中,都可以平移图元。 //这么做修复了这个Bug:Tracker图形在旋转切错状态中,执行平移操作。 //之后,tracker图形变成平移图形。 if (m_transformKind == HTRACKER_TRANSFORM_KIND_SCALE) { m_drawer.SetRotateAndShearState(false); } else if (m_transformKind == HTRACKER_TRANSFORM_KIND_ROTATION || m_transformKind == HTRACKER_TRANSFORM_KIND_SHEAR) { m_drawer.SetRotateAndShearState(true); } }