#include "stdafx.h" #include "resource.h" #include "GsPreviewCtrl.h" #include "acgsmanager.h" #include "EarThwormDef.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define WM_VIEWDBLCLKSEL (WM_USER + 0x1200) BOOL IsKeyPressed(int vk) { SHORT nState = ::GetKeyState(vk); return ((nState & 256) != 0); } double g_nWalkDistStep = 1000.0, g_nWalkAngleStep = 5.0*PI / 180;; #define RXASSERT ASSERT double GetLatitude(AcGePoint3d ptCam, AcGePoint3d ptTar) { double nDist = ptTar.distanceTo(ptCam); if (nDist < 1.e-6) return 0.0; if (ptTar.distanceTo(ptCam) < 1.e-5) { return ((ptTar.z > ptCam.z) ? PI / 2 : -PI / 2); } return asin((ptTar.z - ptCam.z) / nDist); } double GetLongitude(AcGePoint3d ptCam, AcGePoint3d ptTar) // 0 ~ 2*PI { if (ptTar.distanceTo(ptCam) < 1.e-6) return 0.0; return ads_angle(asDblArray(ptCam), asDblArray(ptTar)); } IMPLEMENT_DYNAMIC(CGsPreviewCtrl, CStatic) CGsPreviewCtrl::CGsPreviewCtrl(int nOrbitFlag) : CStatic(), mOrbitFlag(nOrbitFlag), mpManager(NULL), mpFactory(NULL), mpDevice(NULL), mpView(NULL), mpModel(NULL), mbModelCreated(false), mbPanning(false), mbOrbiting(false), mDistStep(g_nWalkDistStep), mAngStep(g_nWalkAngleStep) { } BOOL CGsPreviewCtrl::DestroyWindow() { clearAll(); return CStatic::DestroyWindow(); } BEGIN_MESSAGE_MAP(CGsPreviewCtrl, CStatic) //{{AFX_MSG_MAP(CGsPreviewCtrl) ON_WM_PAINT() ON_WM_SIZE() ON_WM_MOUSEWHEEL() ON_WM_LBUTTONDOWN() ON_WM_MBUTTONDOWN() ON_WM_MBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_NCHITTEST() ON_WM_SETFOCUS() ON_WM_LBUTTONUP() ON_WM_KEYDOWN() ON_WM_LBUTTONDBLCLK() //}}AFX_MSG_MAP ON_WM_SETCURSOR() END_MESSAGE_MAP() void CGsPreviewCtrl::OnPaint() { CPaintDC dc(this); //update the gs view if (mpView) { mpView->invalidate(); mpView->update(); } } // Erase view and delete model void CGsPreviewCtrl::erasePreview() { if (mpView) mpView->eraseAll(); if (mpManager && mpModel) { mpManager->destroyAutoCADModel(mpModel); mpModel = NULL; } } void CGsPreviewCtrl::setModel(AcGsModel* pModel) { erasePreview(); mpModel = pModel; mbModelCreated = false; } void CGsPreviewCtrl::clearAll() { if (mpView) { mpView->eraseAll(); } if (mpDevice) { bool b = mpDevice->erase(mpView); RXASSERT(b); } if (mpFactory) { if (mpView) { mpFactory->deleteView(mpView); mpView = NULL; } if (mpGhostModel) { mpFactory->deleteModel(mpGhostModel); mpGhostModel = NULL; } mpFactory = NULL; } if (mpManager) { if (mpModel) { if (mbModelCreated) mpManager->destroyAutoCADModel(mpModel); mpModel = NULL; } if (mpDevice) { mpManager->destroyAutoCADDevice(mpDevice); mpDevice = NULL; } mpManager = NULL; } } BOOL CGsPreviewCtrl::GetCurrentViewInfo(const AcDbExtents& exts, AcGePoint3d & ptPosition, AcGePoint3d & ptTarget, AcGeVector3d& vecUpVector, double& dFieldWidth, double& dFieldHeight) { // get the view port information - see parameter list double dHeight = 0.0, dWidth = 0.0, dViewTwist = 0.0; AcGePoint3d ptTargetView; AcGeVector3d vecViewDir; GetActiveViewPortInfo(dHeight, dWidth, ptTargetView, vecViewDir, dViewTwist, TRUE); // we are only interested in the directions of the view, not the sizes, so we normalise. vecViewDir.normalize(); // Our view coordinate space consists of z direction // get a perp vector off the z direction // Make sure its normalised AcGeVector3d vecViewXDir = vecViewDir.perpVector().normal(); // correct the x angle by applying the twist vecViewXDir = vecViewXDir.rotateBy(dViewTwist, -vecViewDir); // now we can work out y, this is of course perp to the x and z directions. No need to normalise this, // as we know that x and z are of unit length, and perpendicular, so their cross product must be on unit length vecUpVector = vecViewDir.crossProduct(vecViewXDir); // Calculate the extents in WCS AcGePoint3d ptExtMax = exts.maxPoint(); AcGePoint3d ptExtMin = exts.minPoint(); // find a nice point around which to transform the view. We'll use the same point as the center of the view. ptTarget = ptExtMin + 0.5 * (ptExtMax - ptExtMin); ptPosition = ptTarget + vecViewDir; // create a transform from WCS to View space // this represents the transformation from WCS to the view space. (Actually not quite since // we are keeping the fixed point as the center of the box for convenience ) AcGeMatrix3d matView; matView = AcGeMatrix3d::alignCoordSys(ptTarget, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis, ptTarget, vecViewXDir, vecUpVector, vecViewDir).inverse(); AcDbExtents extWcsExtents(ptExtMin, ptExtMax); // now we have the view Extents AcDbExtents extViewExtents = extWcsExtents; // transforms the extents in WCS->view space extViewExtents.transformBy(matView); // get the extents of the AutoCAD view dFieldWidth = fabs(extViewExtents.maxPoint().x - extViewExtents.minPoint().x); dFieldHeight = fabs(extViewExtents.maxPoint().y - extViewExtents.minPoint().y); return TRUE; } void CGsPreviewCtrl::InitFromCurrentView2D(const AcDbExtents& exts,bool bRestTarget) { struct resbuf rb; acedGetVar(_T("CVPORT"), &rb); int iCurView = rb.resval.rint; acedGetVar(_T("TILEMODE"), &rb); int iTileMode = rb.resval.rint; #ifndef ZWCAD #if ARX < 20 AcGsView::RenderMode eShadeMode; if (iTileMode == 0 && iCurView == 1) eShadeMode = AcGsView::k2DOptimized; else eShadeMode = AcGsView::k2DOptimized; mpView->setMode(eShadeMode); #else AcGiVisualStyle style; if (iTileMode == 0 && iCurView == 1) style.setType(AcGiVisualStyle::k2DWireframe); else style.setType(AcGiVisualStyle::k2DWireframe); mpView->setVisualStyle(style); #endif #else #if defined(R24) AcGsView::RenderMode eShadeMode; if (iTileMode == 0 && iCurView == 1) eShadeMode = AcGsView::k2DOptimized; else eShadeMode = AcGsView::k2DOptimized; mpView->setMode(eShadeMode); #else AcGiVisualStyle style; if (iTileMode == 0 && iCurView == 1) style.setType(AcGiVisualStyle::k2DWireframe); else style.setType(AcGiVisualStyle::k2DWireframe); mpView->setVisualStyle(style); #endif #endif AcGeVector3d vecUpVector; AcGePoint3d ptPosition, ptTarget; double dFieldWidth, dFieldHeight; GetCurrentViewInfo(exts, ptPosition, ptTarget, vecUpVector, dFieldWidth, dFieldHeight); if (!vecUpVector.isParallelTo(AcGeVector3d::kYAxis)) { vecUpVector = AcGeVector3d::kYAxis;//???显示Y方向看 } if (bRestTarget) ptTarget.set(0,0,0); ptPosition.set(0,0,0); mpView->setView(ptPosition, ptTarget, vecUpVector, dFieldWidth, dFieldHeight); mpView->zoomExtents(exts.minPoint(),exts.maxPoint()); mpView->zoom(1.1); mpView->invalidate(); } void CGsPreviewCtrl::InitFromCurrentView3D(const AcDbExtents& exts, bool bRestTarget) { struct resbuf rb; acedGetVar(_T("CVPORT"), &rb); int iCurView = rb.resval.rint; acedGetVar(_T("TILEMODE"), &rb); int iTileMode = rb.resval.rint; #ifndef ZWCAD #if ARX < 20 mpView->setMode(AcGsView::kGouraudShaded); #else mpView->setVisualStyle(AcGiVisualStyle::kGouraud); #endif #else #if defined(R24) mpView->setMode(AcGsView::kGouraudShaded); #else mpView->setVisualStyle(AcGiVisualStyle::kGouraud); #endif #endif AcGePoint3d extMax(500, 500, 500);// = pDb->extmax(); AcGePoint3d extMin(-500, -500, -500);// = pDb->extmin(); //AcGePoint3d extMax = pDb->extmax(); //AcGePoint3d extMin = pDb->extmin(); // get the view port information - see parameter list ads_real height = 0.0, width = 0.0, viewTwist = 0.0; AcGePoint3d targetView; AcGeVector3d viewDir; GetActiveViewPortInfo(height, width, targetView, viewDir, viewTwist, true); viewDir.set(-1, -1, 1); viewDir = viewDir.normal(); AcGeVector3d viewXDir = viewDir.perpVector().normal(); viewXDir = viewXDir.rotateBy(viewTwist, -viewDir); AcGeVector3d viewYDir = viewDir.crossProduct(viewXDir); AcGePoint3d boxCenter = extMin + 0.5 * (extMax - extMin); AcGeMatrix3d viewMat = AcGeMatrix3d::alignCoordSys(boxCenter, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis, boxCenter, viewXDir, viewYDir, viewDir).inverse(); AcDbExtents wcsExtents(extMin, extMax); AcDbExtents viewExtents = wcsExtents; viewExtents.transformBy(viewMat); double xMax = fabs(viewExtents.maxPoint().x - viewExtents.minPoint().x); double yMax = fabs(viewExtents.maxPoint().y - viewExtents.minPoint().y); AcGePoint3d eye = boxCenter + viewDir; mpView->setView(eye, boxCenter, viewYDir, xMax, yMax); //if (mpView != NULL) //{ // mpView->invalidate(); // mpView->update(); //} } BOOL CGsPreviewCtrl::GetActiveViewPortInfo(double &dHeight, double &dWidth, AcGePoint3d &ptTarget, AcGeVector3d &vecViewDir, double &dViewTwist, BOOL bGetViewCenter) { // get the working db AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase(); // if not ok if (pDb == NULL) return FALSE; // lock document //AcApDocument* pDoc = acDocManager->curDocument(); //acDocManager->lockDocument(pDoc); // make sure the active view port is uptodate //acedVports2VportTableRecords(); // unlock document //acDocManager->unlockDocument(pDoc); // open the view port records AcDbViewportTable *pVTable = NULL; Acad::ErrorStatus es = pDb->getViewportTable(pVTable, AcDb::kForRead); // if we opened them ok if (es == Acad::eOk) { AcDbViewportTableRecord *pViewPortRec = NULL; es = pVTable->getAt(_T("*Active"), pViewPortRec, AcDb::kForRead); if (es == Acad::eOk) { // get the height of the view dHeight = pViewPortRec->height(); // get the width dWidth = pViewPortRec->width(); // if the user wants the center of the viewport used if (bGetViewCenter) { struct resbuf rb; memset(&rb, 0, sizeof(struct resbuf)); // get the system var VIEWCTR acedGetVar(_T("VIEWCTR"), &rb); // set that as the target ptTarget = AcGePoint3d(rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]); } else { // we want the viewports camera target setting // get the target of the view ptTarget = pViewPortRec->target(); } // get the view direction vecViewDir = pViewPortRec->viewDirection(); // get the view twist of the viewport dViewTwist = pViewPortRec->viewTwist(); } // close after use pVTable->close(); pViewPortRec->close(); } return TRUE; } BOOL CGsPreviewCtrl::GetCurrentViewInfo(AcGePoint3d & ptPosition, AcGePoint3d & ptTarget, AcGeVector3d& vecUpVector, double& dFieldWidth, double& dFieldHeight) { // get the view port information - see parameter list double dHeight = 0.0, dWidth = 0.0, dViewTwist = 0.0; AcGePoint3d ptTargetView; AcGeVector3d vecViewDir; GetActiveViewPortInfo(dHeight, dWidth, ptTargetView, vecViewDir, dViewTwist, TRUE); // we are only interested in the directions of the view, not the sizes, so we normalise. vecViewDir.normalize(); // Our view coordinate space consists of z direction // get a perp vector off the z direction // Make sure its normalised AcGeVector3d vecViewXDir = vecViewDir.perpVector().normal(); // correct the x angle by applying the twist vecViewXDir = vecViewXDir.rotateBy(dViewTwist, -vecViewDir); // now we can work out y, this is of course perp to the x and z directions. No need to normalise this, // as we know that x and z are of unit length, and perpendicular, so their cross product must be on unit length vecUpVector = vecViewDir.crossProduct(vecViewXDir); // the current editor drawing AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase(); // Calculate the extents in WCS AcGePoint3d ptExtMax = pDb->extmax(); AcGePoint3d ptExtMin = pDb->extmin(); // find a nice point around which to transform the view. We'll use the same point as the center of the view. ptTarget = ptExtMin + 0.5 * (ptExtMax - ptExtMin); ptPosition = ptTarget + vecViewDir; // create a transform from WCS to View space // this represents the transformation from WCS to the view space. (Actually not quite since // we are keeping the fixed point as the center of the box for convenience ) AcGeMatrix3d matView; matView = AcGeMatrix3d::alignCoordSys(ptTarget, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis, ptTarget, vecViewXDir, vecUpVector, vecViewDir).inverse(); AcDbExtents extWcsExtents(ptExtMin, ptExtMax); // now we have the view Extents AcDbExtents extViewExtents = extWcsExtents; // transforms the extents in WCS->view space extViewExtents.transformBy(matView); // get the extents of the AutoCAD view dFieldWidth = fabs(extViewExtents.maxPoint().x - extViewExtents.minPoint().x); dFieldHeight = fabs(extViewExtents.maxPoint().y - extViewExtents.minPoint().y); return TRUE; } void CGsPreviewCtrl::init(bool bCreateModel) { //Load our special cursors { CAcModuleResourceOverride vTemp; CWinApp *pApp = AfxGetApp(); mhPanCursor = pApp->LoadCursor(IDI_PAN); mhCrossCursor = pApp->LoadCursor(IDI_CROSS); mhOrbitCursor = pApp->LoadCursor(IDI_ORBIT); mhEditCursor = pApp->LoadCursor(IDC_CURSOREDIT); } //Instantiate view, a device and a model object CRect rect; if (!mpManager) { mpManager = acgsGetGsManager(); RXASSERT(mpManager); #if (ARX >= 20) AcGsKernelDescriptor desc; desc.addRequirement(AcGsKernelDescriptor::k3DDrawing); mpFactory = AcGsManager::acquireGraphicsKernel(desc); if (!mpFactory) return; #else mpFactory = mpManager->getGSClassFactory(); #endif RXASSERT(mpFactory); //a device with standard autocad color palette #if (ARX >= 20) //mpDevice = mpFactory->createOffScreenDevice(); mpDevice = mpManager->createAutoCADDevice(*mpFactory, m_hWnd); #else mpDevice = mpManager->createAutoCADDevice(m_hWnd); #endif RXASSERT(mpDevice); GetClientRect(&rect); mpDevice->onSize(rect.Width(), rect.Height()); //a simple view mpView = mpFactory->createView(); RXASSERT(mpView); if (bCreateModel) { RXASSERT(mpModel == NULL); //a model with open/close protocol #if (ARX >= 20) mpModel = mpManager->createAutoCADModel(*mpFactory); #else mpModel = mpManager->createAutoCADModel(); #endif RXASSERT(mpModel); mbModelCreated = true; } //another model without open/close for the orbit gadget mpGhostModel = mpFactory->createModel(AcGsModel::kDirect, 0, 0, 0); if (mOrbitFlag) { /* mpView->add(&mOrbitGadget,mpGhostModel); mOrbitGadget.setGsView(mpView); */ } mpDevice->add(mpView); mpView->setView(AcGePoint3d(0.0, 0.0, 1.0), AcGePoint3d(0.0, 0.0, 0.0), AcGeVector3d(0.0, 0.0, 1.0), 1.0, 1.0); } } BOOL CGsPreviewCtrl::Add(AcDbEntity* pEnt) { if (mpView != NULL) { mpView->add(pEnt, mpModel); mpView->invalidate(); } return TRUE; } void CGsPreviewCtrl::OnSize(UINT nType, int cx, int cy) { CRect rect; if (mpDevice) { GetClientRect(&rect); mpDevice->onSize(rect.Width(), rect.Height()); } } BOOL CGsPreviewCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { if (!(mOrbitFlag&OBF_ZOOM)) return CStatic::OnMouseWheel(nFlags, zDelta, pt); if (mpView) { if (mpView->isPerspective()) { AcGePoint3d ptTar = mpView->target(); AcGePoint3d ptCam = mpView->position(); AcGeVector3d vtView = ptTar - ptCam; vtView.normalize(); double nScale = mDistStep; if (zDelta < 0) nScale = -nScale; vtView *= nScale; ptCam += vtView; ptTar += vtView; mpView->setView(ptCam, ptTar, AcGeVector3d(0, 0, 1), mpView->fieldWidth(), mpView->fieldHeight(), AcGsView::kPerspective); //mpView->setTarget(ptTar); //mpView->setCamera(ptCam); } else { if (zDelta < 0) mpView->zoom(0.9); else mpView->zoom(1.1); } //Invalidate();//闪的利害 RedrawWindow(); } return TRUE; } void CGsPreviewCtrl::OnLButtonDown(UINT nFlags, CPoint point) { SetFocus(); if ((mOrbitFlag & OBF_COTE)) { CRect rc; GetClientRect(&rc); CPoint pt = point; AcGePoint3d ptGe1(pt.x, (rc.Height() - pt.y), 0.0); ptGe1.transformBy(mpView->worldToDeviceMatrix().inverse()); GetParent()->SendMessage(WM_VIEW_LBUTTONDOWN, 0, (LPARAM)&ptGe1); ::SetCursor(mhEditCursor); return; } if (!(mOrbitFlag & OBF_ORBIT)) { CStatic::OnLButtonDown(nFlags, point); return; } //start orbit mbOrbiting = true; SetCapture(); //set up the proper cursor //::SetClassLong(m_hWnd,GCL_HCURSOR,NULL); ::SetCursor(mhOrbitCursor); //store the start point mStartPt = point; ClientToScreen(&point); GetParent()->ScreenToClient(&point); GetParent()->SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y)); } void CGsPreviewCtrl::OnLButtonUp(UINT nFlags, CPoint point) { if ((mOrbitFlag & OBF_COTE)) { ::SetCursor(mhEditCursor); ReleaseCapture(); return; } if (!(mOrbitFlag&OBF_ORBIT)) { CStatic::OnLButtonUp(nFlags, point); return; } //end orbit mbOrbiting = false; //::SetClassLong(m_hWnd,GCL_HCURSOR,(long)mhCrossCursor); ::SetCursor(mhCrossCursor); ReleaseCapture(); } void CGsPreviewCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) { ClientToScreen(&point); GetParent()->ScreenToClient(&point); GetParent()->SendMessage(WM_LBUTTONDBLCLK,nFlags,MAKELPARAM(point.x,point.y)); GetParent()->SendMessage(WM_VIEWDBLCLKSEL,0,0); } void CGsPreviewCtrl::OnMButtonDown(UINT nFlags, CPoint point) { if (!(mOrbitFlag&OBF_PAN)) { CStatic::OnMButtonDown(nFlags, point); return; } //start pan mbPanning = true; SetCapture(); //set up the proper cursor //::SetClassLong(m_hWnd,GCL_HCURSOR,NULL); ::SetCursor(mhPanCursor); //store the start point mStartPt = point; } void CGsPreviewCtrl::OnMButtonUp(UINT nFlags, CPoint point) { if (!(mOrbitFlag&OBF_PAN)) { CStatic::OnMButtonUp(nFlags, point); return; } //end pan ReleaseCapture(); mbPanning = false; //::SetClassLong(m_hWnd,GCL_HCURSOR,(long)mhCrossCursor); ::SetCursor(mhCrossCursor); } void CGsPreviewCtrl::Invalidate(BOOL bErase) { #if(ARX<17) CStatic::Invalidate(bErase); #else { CWnd*pParent = GetParent(); if (pParent != NULL)//2008+vista发现刷新问题,暂用此方法解决 { CRect rect; GetWindowRect(rect); pParent->ScreenToClient(rect); pParent->InvalidateRect(rect, bErase); } else { CStatic::Invalidate(bErase); } } #endif } void CGsPreviewCtrl::OnMouseMove(UINT nFlags, CPoint point) { if (mpView && mbPanning && (mOrbitFlag&OBF_PAN)) { //transform the point from device coordinates to //world coordinates AcGeVector3d pan_vec(-(point.x - mStartPt.x), point.y - mStartPt.y, 0); pan_vec.transformBy(mpView->viewingMatrix() * mpView->worldToDeviceMatrix().inverse()); mpView->dolly(pan_vec); //Invalidate(); RedrawWindow(); mStartPt = point; } else if (mpView && mbOrbiting && (mOrbitFlag&OBF_ORBIT)) { AcGeVector3d vtMov(mStartPt.x - point.x, point.y - mStartPt.y, 0.0); AcGePoint3d ptCam = mpView->position(); AcGePoint3d ptTar = mpView->target(); AcGeVector3d vtUp = mpView->upVector(); vtUp = AcGeVector3d(0, 0, 1); CRect rect; GetClientRect(rect); double nRotX = -vtMov.y / rect.Height()*PI / 2; double nRotY = -vtMov.x / rect.Width()*PI / 2; AcGeVector3d vtZ = ptCam - ptTar; AcGePlane plan(ptCam, vtZ); AcGePoint3d ptUp = ptCam + vtUp*10000.0; AcGePoint3d ptUp1 = ptUp.orthoProject(plan); if (ptCam.distanceTo(ptUp1) < 0.1) return; AcGeVector3d vtY = ptUp1 - ptCam; AcGeVector3d vtX = vtY.crossProduct(vtZ); vtX.normalize(); vtY.normalize(); vtZ.normalize(); AcGeVector3d vtView = ptTar - ptCam; vtView.rotateBy(nRotX, vtX); vtY.rotateBy(nRotX, vtX); vtView.rotateBy(nRotY, vtY); ptTar = ptCam + vtView; mpView->setView(ptCam, ptTar, vtUp, mpView->fieldWidth(), mpView->fieldHeight(), mpView->isPerspective() ? AcGsView::kPerspective : AcGsView::kParallel); //Invalidate(); RedrawWindow(); mStartPt = point; } else { CStatic::OnMouseMove(nFlags, point); } } #if ARX<17 UINT CGsPreviewCtrl::OnNcHitTest(CPoint point) #else LRESULT CGsPreviewCtrl::OnNcHitTest(CPoint point) #endif { return HTCLIENT; } void CGsPreviewCtrl::OnSetFocus(CWnd* pOldWnd) { if (mOrbitFlag && mhCrossCursor) { ::SetCursor(mhCrossCursor); } } void CGsPreviewCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { BOOL bShift = IsKeyPressed(VK_SHIFT); BOOL bCtrl = IsKeyPressed(VK_CONTROL); if (!mpView) return; AcGePoint3d ptCam = mpView->position(); AcGePoint3d ptTar = mpView->target(); AcGeVector3d vtView = ptTar - ptCam; vtView.normalize(); AcGeVector3d vtUp(0, 0, 1); if (nChar == VK_LEFT || nChar == VK_RIGHT) { double nFactor = 1.0; if (nChar == VK_RIGHT) nFactor = -1.0; if (!bShift && !bCtrl) { //左右移 double nStepLen = mDistStep*nRepCnt; double longitude = GetLongitude(ptCam, ptTar); AcGeMatrix3d mat; AcGePoint3d ptTmp(nStepLen*cos(longitude + PI / 2.0*nFactor), nStepLen*sin(longitude + PI / 2.0*nFactor), 0.0); mat.setToTranslation(ptTmp.asVector()); ptCam.transformBy(mat); ptTar.transformBy(mat); } else if (bCtrl) { //左右转 PI/2 double val = GetLongitude(ptCam, ptTar) + PI / 2.0 * nFactor; double nElev = ptTar.z; ads_polar(asDblArray(ptCam), val, ptCam.distanceTo(ptTar), asDblArray(ptTar)); ptTar.z = nElev; } else if (bShift) { //左右转 double val = GetLongitude(ptCam, ptTar) + mAngStep*nRepCnt*nFactor; double nElev = ptTar.z; ads_polar(asDblArray(ptCam), val, ptCam.distanceTo(ptTar), asDblArray(ptTar)); ptTar.z = nElev; } } else if (nChar == VK_UP || nChar == VK_DOWN) { double nFactor = 1.0; if (nChar == VK_DOWN) nFactor = -1.0; if (!bShift && !bCtrl) { //前进或后退 AcGeMatrix3d mat; double nStepLen = mDistStep*nRepCnt*nFactor; double longitude = GetLongitude(ptCam, ptTar); AcGePoint3d ptT(nStepLen*cos(longitude), nStepLen*sin(longitude), 0); mat.setToTranslation(ptT.asVector()); ptCam.transformBy(mat); ptTar.transformBy(mat); } else if (bCtrl) { //上下移动 ptCam.z += mDistStep*nRepCnt*nFactor; ptTar.z += mDistStep*nRepCnt*nFactor; } else if (bShift) { //上下转动 double val = GetLatitude(ptCam, ptTar) + mAngStep*nRepCnt*nFactor; double nElevDiff = ptCam.distanceTo(ptTar)*tan(val); ptTar.z = ptCam.z + nElevDiff; } } else { CStatic::OnKeyDown(nChar, nRepCnt, nFlags); return; } mpView->setView(ptCam, ptTar, vtUp, mpView->fieldWidth(), mpView->fieldHeight(), mpView->isPerspective() ? AcGsView::kPerspective : AcGsView::kParallel); //Invalidate(); RedrawWindow(); } BOOL CGsPreviewCtrl::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if (pMsg->message == WM_KEYDOWN) { INT_PTR vk = pMsg->wParam; if (vk == VK_LEFT || vk == VK_RIGHT || vk == VK_DOWN || vk == VK_UP) { int nRepCnt = LOWORD(pMsg->lParam); OnKeyDown((UINT)vk, nRepCnt, 0); return TRUE; } } return CStatic::PreTranslateMessage(pMsg); } BOOL CGsPreviewCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if ((mOrbitFlag & OBF_COTE)) { SetCursor(mhEditCursor); return FALSE; } return CStatic::OnSetCursor(pWnd, nHitTest, message); } void CGsPreviewCtrl::RefreshView() { if (mpView != NULL) { mpView->invalidate(); mpView->update(); } } void CGsPreviewCtrl::OnZoomExtents(AcDbDatabase* pDb) { AcDbExtents viewExtents(pDb->extmin(), pDb->extmax()); AcGeMatrix3d viewMatrix; viewExtents.transformBy(viewMatrix); //mpView->zoomExtents(viewExtents.minPoint(),viewExtents.maxPoint()); RefreshView(); }