www.pudn.com > VCad3.0.zip > VCadView.cpp
// VCadView.cpp : implementation of the CVCadView class // #include "stdafx.h" #include "VCad.h" #include#include "VCadDoc.h" #include "VCadView.h" #include "Base.h" #include "Command.h" #include "CreateCmd.h" #include "ModifyCmd.h" #include "Entity.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CVCadView IMPLEMENT_DYNCREATE(CVCadView, CView) BEGIN_MESSAGE_MAP(CVCadView, CView) //{{AFX_MSG_MAP(CVCadView) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_RBUTTONDOWN() ON_COMMAND(ID_PICK, OnPick) ON_UPDATE_COMMAND_UI(ID_PICK, OnUpdatePick) ON_COMMAND(ID_REDRAW, OnRedraw) ON_WM_KEYDOWN() //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) ON_COMMAND_RANGE(ID_CREATE_LINE, ID_CREATE_ARC, OnCreateEntity) ON_UPDATE_COMMAND_UI_RANGE(ID_CREATE_LINE, ID_CREATE_ARC, OnUpdateCreateCommand) ON_COMMAND_RANGE(ID_MODIFY_MOVE, ID_MODIFY_ERASE, OnModifyEntity) ON_UPDATE_COMMAND_UI_RANGE(ID_MODIFY_MOVE, ID_MODIFY_ERASE, OnUpdateModifyCommand) ON_COMMAND_RANGE(ID_VIEW_PAN, ID_VIEW_ZOOMRGN, OnDispStyle) ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_PAN, ID_VIEW_ZOOMRGN, OnUpdateDispStyleCommand) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CVCadView construction/destruction CVCadView::CVCadView() { // TODO: add construction code here g_pView = this; m_pCmd = NULL; // 初始化世界坐标与屏幕坐标的关系 m_dOrgX = m_dOrgY = 0.; scale = 1.; } CVCadView::~CVCadView() { if( m_pCmd ) delete m_pCmd ; } BOOL CVCadView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CVCadView drawing void CVCadView::OnDraw(CDC* pDC) { g_nRefresh ++; // 每次视窗被重新绘制时,刷新次数加 1 CVCadDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here pDoc->Draw(pDC); } ///////////////////////////////////////////////////////////////////////////// // CVCadView diagnostics #ifdef _DEBUG void CVCadView::AssertValid() const { CView::AssertValid(); } void CVCadView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CVCadDoc* CVCadView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CVCadDoc))); return (CVCadDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CVCadView message handlers void CVCadView::OnCreateEntity(int m_nID) { // 如果当前状态存在命令,那么 // 1. 取消该命令的操作 // 2. 删除该命令对象 // 3. 将命令指针设为空 if( m_pCmd ){ m_pCmd->Cancel(); delete m_pCmd ; m_pCmd = NULL; } // 下面根据不同的菜单命令创建不同的命令对象 switch(m_nID) { case ID_CREATE_LINE: // 直线 { m_pCmd = new CCreateLine(); break; } case ID_CREATE_RECTANGLE: // 矩形 { m_pCmd = new CCreateRect(); break; } case ID_CREATE_CIRCLE: // 圆 { m_pCmd = new CCreateCircle(); break; } case ID_CREATE_ARC: // 圆弧 { m_pCmd = new CCreateArc(); break; } } } void CVCadView::OnUpdateCreateCommand(CCmdUI* pCmdUI) { int flag = 0 ; switch(pCmdUI->m_nID) { case ID_CREATE_LINE: { if( (m_pCmd != NULL && m_pCmd->GetType() == ctCreateLine) ) flag = 1; break; } case ID_CREATE_RECTANGLE: { if( (m_pCmd != NULL && m_pCmd->GetType() == ctCreateRectangle) ) flag = 1; break; } case ID_CREATE_CIRCLE: { if( (m_pCmd != NULL && m_pCmd->GetType() == ctCreateCircle) ) flag = 1; break; } case ID_CREATE_ARC: { if( (m_pCmd != NULL && m_pCmd->GetType() == ctCreateArc) ) flag = 1; break; } default: break; } pCmdUI->SetCheck(flag); } void CVCadView::OnModifyEntity(int m_nID) { CVCadDoc* pDoc = GetDocument(); ASSERT(pDoc) ; // 如果当前状态存在命令,那么 // 1. 取消该命令的操作 // 2. 删除该命令对象 // 3. 将命令指针设为空 if( m_pCmd ){ m_pCmd->Cancel(); delete m_pCmd ; m_pCmd = NULL; } // 判断是否有实体图元被选中 if(pDoc->m_selectArray.GetSize() == 0) { CString strError = _T("请首先选取图元"); AfxMessageBox(strError); return; } // 下面根据不同的菜单命令创建不同的命令对象 switch(m_nID) { case ID_MODIFY_MOVE: // 平移 { m_pCmd = new CMove(); break; } case ID_MODIFY_ROTATE: // 旋转 { m_pCmd = new CRotate(); break; } case ID_MODIFY_MIRROR: // 镜像 { m_pCmd = new CMirror(); break; } case ID_MODIFY_ERASE: DeleteSel(); break; default: break; } } void CVCadView::OnUpdateModifyCommand(CCmdUI* pCmdUI) { CVCadDoc* pDoc = GetDocument(); ASSERT(pDoc) ; // 判断是否有实体图元被选中 if(pDoc->m_selectArray.GetSize() == 0) { pCmdUI->Enable(FALSE); return; } int flag = 0 ; switch(pCmdUI->m_nID) { case ID_MODIFY_MOVE: { if( (m_pCmd != NULL && m_pCmd->GetType() == ctMove) ) flag = 1; break; } case ID_MODIFY_ROTATE: { if( (m_pCmd != NULL && m_pCmd->GetType() == ctRotate) ) flag = 1; break; } case ID_MODIFY_MIRROR: { if( (m_pCmd != NULL && m_pCmd->GetType() == ctMirror) ) flag = 1; break; } case ID_MODIFY_ERASE: break; default: break; } pCmdUI->SetCheck(flag); } void CVCadView::OnDispStyle(int m_nID) { CVCadDoc* pDoc = GetDocument(); ASSERT(pDoc) ; // 如果当前状态存在命令,那么 // 1. 取消该命令的操作 // 2. 删除该命令对象 // 3. 将命令指针设为空 if( m_pCmd ){ m_pCmd->Cancel(); delete m_pCmd ; m_pCmd = NULL; } switch(m_nID) { case ID_VIEW_PAN: // 平移 { m_pCmd = new CViewPanCmd(); break; } case ID_VIEW_ZOOMIN: { SendMessage(WM_KEYDOWN,VK_NEXT) ; break; } case ID_VIEW_ZOOMOUT: { SendMessage(WM_KEYDOWN,VK_PRIOR) ; break; } case ID_VIEW_ZOOMALL: { ZoomAll() ; break; } case ID_VIEW_ZOOMRGN: { m_pCmd = new CZoomRgnCmd() ; break; } default: //erase the objects ; break; } } void CVCadView::OnUpdateDispStyleCommand(CCmdUI* pCmdUI) { } void CVCadView::WorldtoScreen(const Position& pos, CPoint& screenPt) { // 获取当前客户区的大小 CRect rect ; GetClientRect(&rect) ; // 将屏幕原点设置为客户区的中心 int nSOrgX = (rect.left + rect.right) / 2 ; int nSOrgY = -(rect.top + rect.bottom) / 2 ; // 计算屏幕坐标值 screenPt.x = (int)((pos.x - m_dOrgX) / scale + nSOrgX) ; screenPt.y = (int)((pos.y - m_dOrgY) / scale + nSOrgY) ; } void CVCadView::ScreentoWorld(const CPoint& pt, Position& pos) { CPoint screenPt = pt; CDC* pDC = GetDC(); pDC->SetMapMode(MM_LOENGLISH); pDC->DPtoLP(&screenPt); ReleaseDC(pDC); // 获取当前客户区的大小 CRect rect ; GetClientRect(&rect) ; // 将屏幕原点设置为客户区的中心 int nSOrgX = (rect.left + rect.right) / 2 ; int nSOrgY = -(rect.top + rect.bottom) / 2 ; // 计算世界坐标值 pos.x = (screenPt.x - nSOrgX) * scale + m_dOrgX; pos.y = (screenPt.y - nSOrgY ) * scale + m_dOrgY; } double CVCadView::GetScale() { return scale; } double CVCadView::GetOrgX() { return m_dOrgX ; } double CVCadView::GetOrgY() { return m_dOrgY ; } void CVCadView::SetOrgX(double dx) { m_dOrgX = dx ; } void CVCadView::SetOrgY(double dy) { m_dOrgY = dy ; } void CVCadView::SetScale(double sal) { scale = sal ; } void CVCadView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CVCadDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); Position pos; ScreentoWorld(point, pos); // 将设备坐标转换为世界坐标 if(m_pCmd) m_pCmd->OnLButtonDown(nFlags, pos); else pDoc->OnLButtonDown(nFlags, pos); CView::OnLButtonDown(nFlags, point); } void CVCadView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CVCadDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); Position pos; ScreentoWorld(point, pos);// 将设备坐标转换为世界坐标 //获得状态条的指针 CStatusBar* pStatus=(CStatusBar*) AfxGetApp()->m_pMainWnd->GetDescendantWindow(ID_VIEW_STATUS_BAR); if(pStatus) { char tbuf[40]; sprintf(tbuf,"(%8.3f,%8.3f)",pos.x, pos.y); //在状态条的第二个窗格中输出当前鼠标的位置 pStatus->SetPaneText(1,tbuf); } if(m_pCmd) m_pCmd->OnMouseMove(nFlags, pos); else pDoc->OnMouseMove(nFlags, pos); CView::OnMouseMove(nFlags, point); } void CVCadView::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default Position pos; ScreentoWorld(point, pos);// 将设备坐标转换为世界坐标 if(m_pCmd) m_pCmd->OnRButtonDown(nFlags, pos); CView::OnRButtonDown(nFlags, point); } void CVCadView::OnPick() { // TODO: Add your command handler code here if(m_pCmd){ delete m_pCmd; m_pCmd = NULL; } } void CVCadView::OnUpdatePick(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->SetCheck(m_pCmd == NULL ? 1 : 0) ; } ///////////////////////////////////////////////////////////////////////////// // CVCadView printing BOOL CVCadView::OnPreparePrinting(CPrintInfo* pInfo) { // 将绘图板设置为2个标准页大小 pInfo->SetMaxPage(2); return DoPreparePrinting(pInfo); } void CVCadView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo) { // TODO: add extra initialization before printing // 获得可打印区域(毫米值) int nHorzSize = pDC->GetDeviceCaps(HORZSIZE); int nVertSize = pDC->GetDeviceCaps(VERTSIZE); // 计算页面的高度和宽度(逻辑单位) m_nPageWidth = (int)((double)nHorzSize / 25.4 * 100.0); m_nPageHeight = (int)((double)nVertSize / 25.4 * 100.0); } void CVCadView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } void CVCadView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) { pDC->SetMapMode(MM_LOENGLISH); if(pDC->IsPrinting()) { int nPages = pInfo->m_nCurPage - 1; int x = (nPages & 1) * m_nPageWidth; int y = (nPages / 2) * m_nPageHeight; pDC->SetWindowOrg(x,y); } CView::OnPrepareDC(pDC, pInfo); } void CVCadView::OnPrint(CDC* pDC, CPrintInfo* pInfo) { ASSERT_VALID(pDC); pDC->SetWindowOrg(pInfo->m_rectDraw.left, -pInfo->m_rectDraw.top); // 打印页眉 PrintPageHeader(pDC,pInfo); // 打印图形 CView::OnPrint(pDC, pInfo); // 打印页脚 PrintPageFooter(pDC,pInfo); } void CVCadView::PrintPageHeader(CDC *pDC, CPrintInfo *pInfo) { // 获取设备描述表中缺省的字体 TEXTMETRIC tm; pDC->GetTextMetrics(&tm); // 创建新字体并将其选入设备描述表 CFont newFont; newFont.CreateFont(-tm.tmHeight, 0,0,0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_MODERN, "Courier New"); CFont* pOldFont = (CFont*)pDC->SelectObject(&newFont); // 页眉中的文本右对齐 pDC->SetTextAlign(TA_RIGHT); // 打印页眉文本 pDC->TextOut(pInfo->m_rectDraw.right, -25, "VCad 绘图系统"); // 打印页眉中的水平直线 int y = - 35 - tm.tmHeight; pDC->MoveTo(0,y); pDC->LineTo(pInfo->m_rectDraw.right,y); // 根据页眉占用的空间来调整可打印图形区域 y -= 25; pInfo->m_rectDraw.top += y; // 恢复以前的字体 pDC->SelectObject(pOldFont); } // 打印页脚 void CVCadView::PrintPageFooter(CDC *pDC, CPrintInfo *pInfo) { CVCadDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // 由文档保存的位置或者标题和当前的页码构成页脚的文本 // 如果文档没有被保存,则打印文档的标题名称;反之,则打印文档保存的位置 CString strFooter = pDoc->GetPathName(); CString strTitle = pDoc->GetTitle(); if(strTitle == "Untitled" || strTitle == "无标题") strFooter = strTitle; // 文本左对齐 pDC->SetTextAlign(TA_LEFT); // 打印文本 pDC->TextOut(pInfo->m_rectDraw.left, pInfo->m_rectDraw.bottom + 100, strFooter); // 在页脚中添加页码信息 CString strPage; strPage.Format("%s%d%s", "第", pInfo->m_nCurPage, "页"); // 获取页码的宽度 CSize size = pDC->GetTextExtent(strFooter); // 页码右对齐 pDC->TextOut(pInfo->m_rectDraw.right - size.cx, pInfo->m_rectDraw.bottom + 100, strPage); // 绘制页脚的水平上划线 TEXTMETRIC tm; pDC->GetTextMetrics(&tm); int y = pInfo->m_rectDraw.bottom + 90 + tm.tmHeight; pDC->MoveTo(0, y); pDC->LineTo(pInfo->m_rectDraw.right, y); } void CVCadView::OnRedraw() { // TODO: Add your command handler code here Invalidate(FALSE) ; } void CVCadView::ZoomAll() { //得到屏幕矩形 CRect rc ; GetClientRect(&rc); //通过比较每个图元的包围盒,得到一个最大包围盒 double MinX, MaxX, MinY, MaxY ; MinX = rc.right ; MinY = rc.bottom ; MaxX = -rc.right ; MaxY = -rc.bottom ; BOX2D pBox ; POSITION pos ; pos = g_pDoc->m_EntityList.GetHeadPosition() ; CEntity* pEntity = NULL ; while(pos!=NULL) { pEntity = (CEntity*)(g_pDoc->m_EntityList.GetNext(pos)) ; pEntity->GetBox(&pBox) ; if(MinX>pBox.min[0])MinX = pBox.min[0] ; if(MinY>pBox.min[1])MinY = pBox.min[1] ; if(MaxX UpdateAllViews(NULL) ; } void CVCadView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch(nChar) { case VK_NEXT: scale *= 0.618 ; if(scale <1e-8) scale =1 ; g_pDoc->UpdateAllViews(NULL) ; break; case VK_PRIOR: scale /= 0.618 ; if(1/scale <1e-8) scale =1 ; g_pDoc->UpdateAllViews(NULL) ; break; default:; } CView::OnKeyDown(nChar, nRepCnt, nFlags); } void CVCadView::DeleteSel() { CEntity* pEntity = NULL; POSITION pos = g_pDoc->m_EntityList.GetHeadPosition(); POSITION pos1 ; while((pos1 = pos )!=NULL) { pEntity = (CEntity *) g_pDoc->m_EntityList.GetNext(pos); if(g_pDoc->IsSelected(pEntity)) { g_pDoc->m_EntityList.RemoveAt(pos1) ; delete pEntity ; } } g_pDoc->m_selectArray.RemoveAll() ; g_pDoc->UpdateAllViews(NULL) ; }