www.pudn.com > VC++-develop-GIS.rar > drawView.cpp
// DrawView.cpp : implementation of the CDrawView class // #include "stdafx.h" #include "Draw.h" #include#include #include "DrawDoc.h" #include "CntrItem.h" #include "DrawView.h" #include "TextWriteDlg.h" #include "mainfrm.h" #include "winresrc.h" #include #include "datalinkdlg.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif extern CGraphPara *p_GraphPara; //初试化一个公用的关于图形参数的实例 extern float xMinScreen,yMinScreen,xMaxScreen,yMaxScreen; ///////////////////////////////////////////////////////////////////////////// // CDrawView CDrawDoc* p_Doc; CDrawView *p_View; BOOL b_Draw; CWinThread *m_pDrawThread; IMPLEMENT_DYNCREATE(CDrawView, CView) BEGIN_MESSAGE_MAP(CDrawView, CView) //{{AFX_MSG_MAP(CDrawView) ON_WM_DESTROY() ON_WM_SETFOCUS() ON_WM_SIZE() //视图大小变化时调用,OnSize函数的映射 ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject) ON_COMMAND(ID_CANCEL_EDIT_CNTR, OnCancelEditCntr) ON_COMMAND(ID_DRAW_ARC, OnDrawArc) //开始圆弧绘制 ON_COMMAND(ID_DRAW_CIRCLE, OnDrawCircle) //开始圆绘制 ON_COMMAND(ID_DRAW_CIRCLE1, OnDrawCircle1) //开始填充圆绘制 ON_COMMAND(ID_DRAW_LINE, OnDrawLine) //开始直线绘制 ON_COMMAND(ID_DRAW_PLINE, OnDrawPline) //开始连续直线绘制 ON_COMMAND(ID_DRAW_RGN, OnDrawRgn) //开始连续多边形绘制 ON_COMMAND(ID_DRAW_TEXT, OnDrawText) //开始文字标注 ON_COMMAND(ID_TEXT_MESSAGE,DrawText) //标注文字时被调用在屏幕上写文字 ON_COMMAND(ID_TEXT_ONOK,DrawTextOnOk) //按‘确定'退出标注文字框时被调用 ON_COMMAND(ID_TEXT_ONCANCEL,DrawTextOnCancel)//按‘放弃'退出标注文字框时调用 ON_WM_LBUTTONDOWN() //按下鼠标左键,OnlButtonDown函数顶消息映射 ON_WM_MOUSEMOVE() //移动鼠标,OnMouseMove函数顶消息映射 ON_WM_RBUTTONDOWN() //按下鼠标右键,OnRButtonDown函数顶消息映射 ON_COMMAND(ID_GRAPH_REDRAW, OnGraphRedraw) //图形重画 ON_COMMAND(ID_GRAPH_ZOOM, OnGraphZoom) //图形放大 ON_COMMAND(ID_GRAPH_PAN, OnGraphPan) //图形摇动 ON_COMMAND(ID_GRAPH_UP, OnGraphUp) //重画上屏 ON_COMMAND(ID_GRAPH_FIRST, OnGraphFirst) //重画首屏 ON_COMMAND(ID_GRAPH_ALL, OnGraphAll) //重画全屏 ON_COMMAND(ID_SELECT_MOUSE, OnSelectMouse) //图形选中 ON_COMMAND(ID_SELECT_CLEAR, OnSelectClear) //放弃选中 ON_COMMAND(ID_SELECT_DELETE, OnSelectDelete)//删除选中图形 ON_COMMAND(ID_EDIT_CUT, OnEditCut) //裁剪选中图形进裁剪板 ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) //从剪裁板粘贴图形 ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) //逆向放弃操作 ON_COMMAND(ID_EDIT_COPY, OnEditCopy) //拷贝选中图形进裁剪板 ON_WM_HSCROLL() ON_WM_VSCROLL() ON_WM_KEYDOWN() ON_COMMAND(ID_BITMAP_CUT, OnBitmapCut) ON_COMMAND(ID_BITMAP_PASTE, OnBitmapPaste) ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) ON_COMMAND(ID_GRAPH_DRAW, OnGraphDraw) ON_EN_CHANGE(IDC_EDIT1, OnChangeDlgEdit) ON_LBN_SELCHANGE(IDC_COMBO1,OnChangeDlgCom) ON_WM_LBUTTONDBLCLK() ON_COMMAND(ID_DATA_SEACHER, OnDataSeacher) //}}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) END_MESSAGE_MAP() UINT DrawFunction(LPVOID PHWndView) { CClientDC ht(CWnd::FromHandle(*(HWND*)PHWndView)); p_Doc->Draw(&ht,0,0,1); return(0); } //视图类的构造函数 CDrawView::CDrawView() { m_pSelection = NULL; m_xStart=0; m_yStart=0; blc=1.0; m_bColor=0; //当前底色的序号 m_pColor=1; //设置笔色 m_brColor=1; //画刷色 m_LineWide=1; //设置线宽 m_LineType=0; //设置线型 m_Layer=1; //设置当前层 PointXyz=new PointStruct[3000];//存储连续直线点的数组 PushNumb=0; b_RunFirst=1; pTextDlg=NULL; //以下设置初始字体大小 m_FontHeight=20; m_FontWide=10; m_TextAngle=0; m_FontAngle=0; m_FontBetween=1; m_TextString.Empty(); m_Text1=new CText();//实际初始化一个标注类 m_bColor=7; //屏幕底色设置为0颜色号 nScrollMin=50; //滚动条的最小滚动范围是在屏幕上滚动50个像素 nXLine=1; //横向滚动一个滚动范围 nYLine=1; //纵向滚动一个滚动范围(按中滚动条的按键时的滚动 m_MapMode=1; // TODO: add construction code here } void CDrawView::DPtoVP(float x,float y,int *X,int *Y) { *X=(int)((x-m_xStart)/blc); if(m_MapMode==1) *Y=m_hScreen-(int)((y-m_yStart)/blc); else *Y=(int)((y-m_yStart)/blc)-m_hScreen; } void CDrawView::VPtoDP(int x,int y,float *X,float *Y) { *X=m_xStart+x*blc; if(m_MapMode==1) *Y=m_yStart+blc*(m_hScreen-y); else *Y=m_yStart+blc*(y+m_hScreen); } float CDrawView::VLtoDL(int l) { return blc*l; } int CDrawView::DLtoVL(float l) { return (int)(l/blc); } //视图类的析构函数 CDrawView::~CDrawView() { delete PointXyz; delete m_Text1; } //预定制窗口函数 BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs) { cs.style=cs.style|WS_HSCROLL|WS_VSCROLL; return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CDrawView drawing //视图类中的绘制函数,通过窗口激发完成视图的自动绘制 void CDrawView::OnDraw(CDC* pDC) { CRect rr; CDrawDoc* pDoc = GetDocument(); p_Doc=pDoc; ASSERT_VALID(pDoc); xMinScreen=m_xStart; yMinScreen=m_yStart; xMaxScreen=xMinScreen+blc*m_wScreen; yMaxScreen=yMinScreen+blc*m_hScreen; // DrawBack(pDC); //以底色填充整个屏幕 if(pDC->GetDeviceCaps(TECHNOLOGY)==DT_RASDISPLAY) { if(m_pDrawThread) { b_Draw=FALSE; m_pDrawThread->ResumeThread(); ::WaitForSingleObject(m_pDrawThread->m_hThread,INFINITE); delete m_pDrawThread; } b_Draw=TRUE; m_PDrawThread=AfxBeginThread(DrawFunction,&m_hWnd,THREAD_PRIORITY_BELOW_NORMAL,0,CREATE_SUSPENDED); m_PDrawThread->m_bAutoDelete=FALSE; m_PDrawThread->ResumeThread(); } else pDoc->Draw(pDC,0,0,m_bColor); POSITION pos=pDoc->GetStartPosition(); while(pos!=NULL) { CDrawCntrItem *pItem=(CDrawCntrItem *)pDoc->GetNextClientItem(pos); if(pItem!=m_pSelection) pItem->Draw(pDC); } if(m_pSelection!=NULL) { m_pSelection->Draw(pDC); CRectTracker tracker; PutTracker(m_pSelection,&tracker); tracker.Draw(pDC); } } //被函数OnDraw调用来以给定的屏幕底色填充屏幕 void CDrawView::DrawBack(CDC* pDC) { CBrush brush(p_GraphPara->GetColor(m_bColor)); //得到画刷 CBrush* pOldBrush=pDC->SelectObject(&brush); //选中画刷 pDC->PatBlt(0,0,m_wScreen,m_hScreen,PATCOPY); //填充屏幕 pDC->SelectObject(pOldBrush); } //函数Aarc::jsarc作用:计算通过屏幕的三个点的弧的图形要素 //参数:依次为三个点的屏幕坐标p1,p2,p3 //通过指针变量返回圆弧的特征参数 BOOL CDrawView::jsarc(CPoint p1,CPoint p2,CPoint p3,float *CircleX,float *CircleY, float *CircleR,float *Angle1,float *Angle2) { float an1,an2,an3; float x1,y1,x2,y2,x3,y3,xx1,xx2,yy1,yy2,xx,yy,rr; float k1,k2; //将三个点的坐标赋给浮点变量 x1=(float)p1.x;y1=(float)p1.y;x2=(float)p2.x; y2=(float)p2.y;x3=(float)p3.x;y3=(float)p3.y; if(x1==x2&&y1==y2||x1==x3&&y1==y3||x2==x3&&y2==y3) //如果有两个点是同一个点 return 0; //操作不成功,返回0 //得到顺三点方向的两条直线中点的坐标 xx1=(x1+x2)/2; yy1=(y1+y2)/2; xx2=(x2+x3)/2; yy2=(y2+y3)/2; if(fabs(y2-y1)>0.5) //如果第一条垂线不是垂直线 k1=-(x2-x1)/(y2-y1); //得到直线的垂线的斜率 //得到第二条直线垂线的斜率 if(fabs(y3-y2)>0.5) k2=-(x3-x2)/(y3-y2); if(k1==k2&&k1==0.0) return 0; if(fabs(y2-y1)<0.5) //如果第一条直线是平行线(即第一条垂线是垂直线) { xx=xx1; if(fabs(y3-y2)<0.5) //如果第二条直线也是平行线 { yy=y2+10000; //给定圆弧的半径为10000 rr=10000; } else // 如果第二条直线不是平行线(即第二条垂线不是垂直线) { yy=yy2+k2*(xx2-xx); //求得圆心的纵坐标 rr=yy-y2; if(rr<0)rr=-rr; //得到半径 } } else if(fabs(y2-y3)<0.5) //如果第二条直线是平行线,而第一条直线不是平行线 { xx=xx2; yy=yy1+k1*(xx1-xx); //解得圆心的y坐标 rr=yy-y2; if(rr<0)rr=-rr; //得到半径 } else //如果两条直线的垂线都不是垂直线 { if(k1==k2)//如果两条直线平行即三个点在一条直线上 { //假定这个圆弧半径为10000个像素,求得圆心坐标 xx=x2+(float)(10000/sqrt(1+k1*k1)); yy=y2+(float)(10000/sqrt((1+k1*k1)/(k1*k1))); rr=10000; } else //如果两条直线不平行 { //解得两条直线的垂线的交点,即圆心的坐标 xx=(yy2-yy1+k1*xx1-k2*xx2)/(k1-k2); yy=yy1+k1*(xx-xx1); rr=(float)sqrt((xx-x1)*(xx-x1)+(yy-y1)*(yy-y1)); //得到半径 } } //将交点变成实际坐标,并存入结构arc1中 VPtoDP((int)xx,(int)yy,CircleX,CircleY); *CircleR=VLtoDL((int)rr); //得到第一个点相对于圆心的弧度 an1=(float)acos((x1-xx)/rr); if(y1-yy>0) an1=(float)(pi*2-an1); //得到第二个点相对于圆心的弧度 an2=(float)acos((x2-xx)/rr); if(y2-yy>0) an2=(float)(pi*2-an2); //得到第三个点相对于圆心的弧度 an3=(float)acos((x3-xx)/rr); if(y3-yy>0) an3=(float)(pi*2-an3); if(an2>an1&&an2 m_linkdata1; } ///////////////////////////////////////////////////////////////////////////// // CDrawView printing BOOL CDrawView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CDrawView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo) { int mPageHeight,mPageWidth,nPage; m_MapMode=2; pDC->SetMapMode(m_MapMode); //整个图形左下角的坐标 xLeft=p_Screen[0].sx; yBottom=p_Screen[0].sy; //整个图形右上角的坐标为 xRight=xLeft+p_Screen[0].blc*m_wScreen; yTop=yBottom+p_Screen[0].blc*m_hScreen; //图形的横向和纵向的幅度为 xWide=xRight-xLeft; yHigh=yTop-yBottom; //point.y=pDC->GetDeviceCaps(VERTRES); //得到设备竖直方向的像素数 //point.x=pDC->GetDeviceCaps(HORZRES); //得到设备水平方向的像素数 //pDC->DPtoLP(&point); pDC->DPtoLP(&(pInfo->m_rectDraw)); mPageHeight=abs(pInfo->m_rectDraw.top-pInfo->m_rectDraw.bottom); mPageWidth=pInfo->m_rectDraw.right-pInfo->m_rectDraw.left; //每页的横向和纵向大小 xPage=blc*mPageWidth; //每页的实际宽度 yPage=blc*mPageHeight; //每页的实际高度 nPageX=(int)(xWide/xPage)+(xWide>xPage*(int)(xWide/xPage));//横向页数 nPageY=(int)(yHigh/yPage)+(yHigh>yPage*(int)(yHigh/yPage));//纵向页数 nPage=nPageX*nPageY; //总页数 pInfo->SetMinPage(1); //设置最小页号 pInfo->SetMaxPage(nPage); //设置最大页号 m_hScreen1=m_hScreen; m_wScreen1=m_wScreen; m_hScreen=mPageHeight; //显示窗口的高度 m_wScreen=mPageWidth; //显示窗口的宽度 // TODO: add extra initialization before printing } void CDrawView::OnEndPrinting(CDC* pDC, CPrintInfo* /*pInfo*/) { CDrawDoc *pDoc=(CDrawDoc *)GetDocument(); //恢复屏幕显示的参数 m_xStart=p_Screen[pDoc->m_CurrentScreen].sx; m_yStart=p_Screen[pDoc->m_CurrentScreen].sy; // TODO: add cleanup after printing m_hScreen=m_hScreen1; m_wScreen=m_wScreen1; m_MapMode=1; } void CDrawView::OnDestroy() { CView::OnDestroy(); COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this); if (pActiveItem != NULL && pActiveItem->GetActiveView() == this) { pActiveItem->Deactivate(); ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL); } } ///////////////////////////////////////////////////////////////////////////// // OLE Client support and commands BOOL CDrawView::IsSelected(const CObject* pDocItem) const { // The implementation below is adequate if your selection consists of // only CDrawCntrItem objects. To handle different selection // mechanisms, the implementation here should be replaced. // TODO: implement this function that tests for a selected OLE client item return pDocItem == m_pSelection; } void CDrawView::OnInsertObject() { m_DrawCurrent=50; //进行插入OLE对象操作 PushNumb=0; } // The following command handler provides the standard keyboard // user interface to cancel an in-place editing session. Here, // the container (not the server) causes the deactivation. void CDrawView::OnCancelEditCntr() { // Close any in-place active item on this view. COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this); if (pActiveItem != NULL) { pActiveItem->Close(); } ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL); } // Special handling of OnSetFocus and OnSize are required for a container // when an object is being edited in-place. void CDrawView::OnSetFocus(CWnd* pOldWnd) { COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this); if (pActiveItem != NULL && pActiveItem->GetItemState() == COleClientItem::activeUIState) { // need to set focus to this item if it is in the same view CWnd* pWnd = pActiveItem->GetInPlaceWindow(); if (pWnd != NULL) { pWnd->SetFocus(); // don't call the base class return; } } CView::OnSetFocus(pOldWnd); } //当视图的大小变化时被调用,cx,cy为变化后屏幕顶长、宽(像素) void CDrawView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); CDrawDoc *pDoc=(CDrawDoc *)GetDocument(); p_Screen=pDoc->m_Screen; m_wScreen=cx; m_hScreen=cy; nXPage=m_hScreen/nScrollMin; //横向一屏的滚动范围 nYPage=m_wScreen/nScrollMin; //纵向一屏的滚动范围 InitVScroll(); InitHScroll(); } ///////////////////////////////////////////////////////////////////////////// // CDrawView diagnostics #ifdef _DEBUG void CDrawView::AssertValid() const { CView::AssertValid(); } void CDrawView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CDrawDoc* CDrawView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDrawDoc))); return (CDrawDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CDrawView message handlers void CDrawView::InitVScroll() { //得到滚动条的最大范围 nVScrollMax=(int)(((float)m_hScreen*p_Screen[0].blc)/(blc*nScrollMin)); //得到当前的滚动条范围 nVScrollPos=nVScrollMax-(int)((m_yStart-p_Screen[0].sy)/(blc*nScrollMin)); //设置滚动条最大范围和当前位置 SetScrollRange(SB_VERT,0,nVScrollMax,TRUE); SetScrollPos(SB_VERT,nVScrollPos);//rrr.top=0; UpdateWindow(); } void CDrawView::InitHScroll() { //得到滚动条的最大范围 nHScrollMax=(int)(((float)m_hScreen*p_Screen[0].blc/blc)/nScrollMin); //得到当前的滚动条范围 nHScrollPos=(int)((m_xStart-p_Screen[0].sx)/blc/nScrollMin); //设置滚动条最大范围和当前位置 SetScrollRange(SB_HORZ,0,nHScrollMax,TRUE); SetScrollPos(SB_HORZ,nHScrollPos);//rrr.top=0; UpdateWindow(); } //选中菜单“绘制圆弧”时被调用 void CDrawView::OnDrawArc() { PushNumb=0; //鼠标左键按下次数 m_DrawCurrent=6; //标识进行圆弧绘制操作 } //选中菜单“绘制圆”时被调用 void CDrawView::OnDrawCircle() { PushNumb=0; //鼠标左键按下次数 m_DrawCurrent=4; //标识进行圆绘制操作 } //选中菜单“绘制圆形区域”时被调用 void CDrawView::OnDrawCircle1() { PushNumb=0; //鼠标左键按下次数 m_DrawCurrent=5; //标识进行圆形区域操作 } //选中菜单“绘制直线”时被调用 void CDrawView::OnDrawLine() { PushNumb=0; m_DrawCurrent=1; //标识进行直线绘制操作 } //选中菜单“绘制连续直线”时被调用 void CDrawView::OnDrawPline() { PushNumb=0; m_DrawCurrent=2; //标识进行连续直线绘制操作 } //选中菜单“绘制多边形区域”时被调用 void CDrawView::OnDrawRgn() { PushNumb=0; m_DrawCurrent=3; //标识进行多边形区域绘制操作 } //选中菜单“标注文字”时被调用 void CDrawView::OnDrawText() { PushNumb=0; m_DrawCurrent=7; //标识进行文字标注操作 } //在标注文字对话框中填入文字时被调用在屏幕上写文字 void CDrawView::DrawText() { CClientDC ht(this); //以下从标注文字对话框中得到字体参数 m_TextString=pTextDlg->m_Text; m_FontHeight=pTextDlg->m_FontHeight; m_FontWide=pTextDlg->m_FontWide; m_TextAngle=pTextDlg->m_Angle1; m_FontAngle=pTextDlg->m_Angle2; m_FontBetween=pTextDlg->m_FontBetween; //对一个字体类的参数重新进行辅值 m_Text1->Init(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,m_TextX,m_TextY ,m_TextAngle,m_FontAngle,m_FontHeight,m_FontWide,m_FontBetween,0,m_TextString); m_Text1->Draw(&ht,0,0,m_bColor);//绘制标注信息 } //按‘确定'退出标注文字对话框时被调用的函数,用来增加一个标注文字项 void CDrawView::DrawTextOnOk() { CDrawDoc* pDoc = GetDocument(); CClientDC ht(this); int TextLong; PushNumb=0; m_TextString=pTextDlg->m_Text; //得到标注的文字信息 TextLong=m_TextString.GetLength(); //标注文字的长度 if(TextLong>0) { //增加并重新绘制标注的文字 int id=pDoc->GetTextId(); pDoc->AddText(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id,m_TextX, m_TextY,m_TextAngle,m_FontAngle,m_FontHeight,m_FontWide, m_FontBetween,0,TextLong,m_TextString) ->Draw(&ht,0,0,m_bColor); pTextDlg->m_Text.Empty(); //清空标注文字对话框中编辑框中顶文字 pTextDlg->SendMessage(WM_INITDIALOG); //以下是记录增加标注信息这一操作,供逆操作时用 GraphUndo[0].Index=pDoc->GetMaxIndex(5);//此标注文字的位置 GraphUndo[0].Lb=5; //标注文字 pDoc->AddUndo(2,1,GraphUndo); ReleaseCapture(); //释放捕捉的鼠标 } } //按‘放弃'退出标注文字对话框时被调用的函数 void CDrawView::DrawTextOnCancel() { pTextDlg->m_Text.Empty(); ////清空标注文字对话框中编辑框中顶文字 pTextDlg->SendMessage(WM_INITDIALOG); } //按下鼠标左键时被调用,ON_WM_LBUTTONDOWN消息的映射函数 void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default float r; float xx1,yy1,xx2,yy2; int x1,x2,y1,y2,Lb,Index,pbh; BOOL m_Fill; CDrawDoc* pDoc = GetDocument(); //得到文档指针 CClientDC ht(this); if(m_DrawCurrent==1) //如果正在绘制直线 { if(PushNumb==0) //如果是第一次按下左鼠标键 { PushNumb++; //做标记表示按下鼠标左键一次 mPointOrign=point; //直线的第一点等于点中点 mPointOld=point; //记录本次点中点 SetCapture(); //捕捉鼠标输入 } else if(PushNumb==1) //第二次按下左鼠标键(即按下直线的结束点时) { //以下得到直线起终点的实际坐标 VPtoDP(mPointOrign.x,mPointOrign.y,&xx1,&yy1); VPtoDP(point.x,point.y,&xx2,&yy2); int id=pDoc->GetLineId(); //得到直线的唯一识别号 //增加一条直线并重新绘画此直线 pDoc->AddLine(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id, xx1,yy1,xx2,yy2) ->Draw(&ht,0,0,m_bColor); PushNumb=0; //鼠标按键次数为0,重新进行直线的绘制 //以下是记录增加直线这一操作,供逆操作时用 GraphUndo[0].Index=pDoc->GetMaxIndex(1);//得到此直线的序号 GraphUndo[0].Lb=1; //直线 pDoc->AddUndo(2,1,GraphUndo); ReleaseCapture(); } } else if(m_DrawCurrent==2||m_DrawCurrent==3)//正在绘制连续直线或者多边形区域 { //将点的坐标存入Pointxy中 PointXyz[PushNumb].x=m_xStart+blc*point.x; PointXyz[PushNumb].y=m_yStart+blc*(m_hScreen-point.y); if(PushNumb==0) //如果是第一次按下左鼠标键 { SetCapture(); //捕捉鼠标 mPointOrign=point;//原点等于点中点 mPointOld=point; //将前一个点设为点中点的坐标 } else //二次以上按下鼠标左键时 { mPointOrign=mPointOld; //将上一个点设为原点 mPointOld=point; //将点中点设为原点 } PushNumb++; //记录按下点的数目 } else if(m_DrawCurrent==4||m_DrawCurrent==5) //如果正在绘制普通圆或者填充圆 { if(PushNumb==0) //如果是第一次按下左鼠标键 { mPointOrign=point; //原点等于点中点 mPointOld=point; //上一个点也等于点中点 PushNumb++; SetCapture(); //捕捉鼠标 } else //二次以上按下鼠标左键时 { PushNumb=0; //鼠标按键次数为0,重新进行直线的绘制 //保存圆或填充圆 r=(float)sqrt(pow((float)(mPointOrign.x-mPointOld.x),2)+pow((float)(mPointOrign.y-mPointOld.y),2)); VPtoDP(mPointOrign.x,mPointOrign.y,&xx1,&yy1); if(m_DrawCurrent==4) //如果是绘制一般圆 m_Fill=0; else m_Fill=1; //保存圆并以覆盖模式重画圆 int id=pDoc->GetCircleId(); pDoc->AddCircle(m_pColor,m_brColor,m_LineWide,m_LineType, m_Layer,id,xx1,yy1,r,m_Fill) ->Draw(&ht,0,0,m_bColor); ReleaseCapture(); //释放捕捉的鼠标 //以下是记录增加圆这一操作,供逆操作时用 GraphUndo[0].Index=pDoc->GetMaxIndex(3); //此圆的序号 GraphUndo[0].Lb=3; //类别是圆 pDoc->AddUndo(2,1,GraphUndo); ReleaseCapture(); } } else if(m_DrawCurrent==6)//正在绘制圆弧 { if(PushNumb==0) //第一次按下鼠标左键 { SetCapture(); DrawArcYes=0; mPointOrign1=point; //记录圆弧第一点 mPointOld=point; PushNumb++; } else if(PushNumb==1) //第二次按下鼠标左键 { mPointOrign=point; //记录下圆弧的第二点 PushNumb++; ht.SetROP2(R2_NOT); //选择反色的绘画模式 ht.MoveTo(mPointOrign1); ht.LineTo(mPointOrign); } else //第三次按下鼠标键 { PushNumb=0; ////鼠标按键次数为0,重新进行圆弧的绘制 //计算圆弧的特征参数 jsarc(mPointOrign1,mPointOrign,point,&m_CircleX,&m_CircleY, &m_CircleR,&m_Angle1,&m_Angle2); //增加一个圆弧并重新绘制圆弧 int id=pDoc->GetArcId(); pDoc->AddArc(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id, m_CircleX,m_CircleY,m_CircleR,0,m_Angle1,m_Angle2) ->Draw(&ht,0,0,m_bColor); ReleaseCapture(); //释放捕捉的鼠标 //以下是记录增加圆弧这一操作,供逆操作时用 GraphUndo[0].Index=pDoc->GetMaxIndex(4); //此圆弧的序号 GraphUndo[0].Lb=4; //类别是圆弧 pDoc->AddUndo(2,1,GraphUndo); ReleaseCapture(); } } else if(m_DrawCurrent==7) //进行标注文字的操作 { VPtoDP(point.x,point.y,&m_TextX,&m_TextY); if(!pTextDlg) //如果标注文字对话框不存在,产生对话框 { //初始画形成一个标注文字对话框 pTextDlg=new TextWriteDlg(this,m_TextString,m_FontHeight,m_FontWide, m_TextAngle,m_FontAngle,m_FontBetween); ASSERT(pTextDlg); } if(!(pTextDlg->IsOpen())) //如果对话框没有打开 { pTextDlg->Create(ID_WRITE_TEXT,this); } if(!(pTextDlg->IsVisible()))//如果对话框当前不可见 { pTextDlg->ShowWindow(SW_SHOW); //使标注文字对话框可见 } } else if(m_DrawCurrent==11||m_DrawCurrent==12||m_DrawCurrent==50) //正在进行图形放大或图形移动 { if(PushNumb==0) //如果第一次按下鼠标左键 { mPointOrign=point; //原点等于点中点 mPointOld=point; //上一个点等于点中点 PushNumb++; //按键数增加1 SetCapture(); //捕捉鼠标 } else if(PushNumb==1)//第二次按下左键 { if(m_DrawCurrent==11) //图形放大 { //得到左下点和右上点 x1=min(mPointOrign.x,point.x); y1=max(mPointOrign.y,point.y); x2=max(mPointOrign.x,point.x); y2=min(mPointOrign.y,point.y); //改变原点的坐标 VPtoDP(x1,y1,&m_xStart,&m_yStart); //改变比例 float bl1=(float)m_wScreen/(float)(x2-x1); //横向放大比例 float bl2=(float)m_hScreen/(float)(y1-y2); //纵向放大比例 if(bl2 0) blc=blc/bl1; //改变显示比例 pDoc->AddScreen(m_xStart,m_yStart,blc); //保存本屏的参数 InitVScroll(); InitHScroll(); Invalidate(); //使图形重画 } else if(m_DrawCurrent==12) //图形移动操作 { //改变原点(左下角点)的实际坐标 m_xStart=m_xStart-blc*(point.x-mPointOrign.x); m_yStart=m_yStart+blc*(point.y-mPointOrign.y); pDoc->AddScreen(m_xStart,m_yStart,blc); //保存本屏的参数 InitVScroll(); InitHScroll(); Invalidate(); //使图形重画 } else if(m_DrawCurrent==50) //如果是插入OLE对象操作 { //得到左下点和右上点 x1=min(mPointOrign.x,point.x); y1=max(mPointOrign.y,point.y); x2=max(mPointOrign.x,point.x); y2=min(mPointOrign.y,point.y); COleInsertDialog dlg; if (dlg.DoModal() != IDOK) return; BeginWaitCursor(); CDrawCntrItem* pItem = NULL; TRY { pItem = new CDrawCntrItem(pDoc); ASSERT_VALID(pItem); if (!dlg.CreateItem(pItem)) AfxThrowMemoryException(); // any exception will do ASSERT_VALID(pItem); if (dlg.GetSelectionType()==COleInsertDialog::createNewItem) pItem->DoVerb(OLEIVERB_SHOW, this); ASSERT_VALID(pItem); m_pSelection = pItem; // set selection to last inserted item VPtoDP(x1,y1,&pItem->m_X1,&pItem->m_Y1); VPtoDP(x2,y2,&pItem->m_X2,&pItem->m_Y2); pDoc->UpdateAllViews(NULL); } CATCH(CException, e) { if (pItem != NULL) { ASSERT_VALID(pItem); pItem->Delete(); } AfxMessageBox(IDP_FAILED_TO_CREATE); } END_CATCH EndWaitCursor(); } PushNumb=0; //完成操作,左键按下数置0 m_DrawCurrent=0; //完成一次后,不继续运行此功能 ReleaseCapture(); //释放捕捉的鼠标 } } else if(m_DrawCurrent==30) //进行鼠标选择图形操作 { if(pDoc->n_GraphSelect==2000) //如果选中的图形元素数是2000则不再选中 { AfxMessageBox("最多只能选择2000个图形元素"); return; } xx1=m_xStart+blc*point.x; //点中点的实际x坐标 yy1=m_yStart+blc*(m_hScreen-point.y); //点中点的实际y坐标 float jl=blc*4; //点中范围(4个像素的实际距离) //以下对各种元素进行检查,计算是否点中(线,连续直线,圆和圆弧) BOOL pb=pDoc->PointSelect(xx1,yy1,jl,blc,&Lb,&Index,&pbh); if(pb) //如果选中了图形元素,记录下选中顶图形元素,特殊显示此图形元素 { BOOL pb1=pDoc->AddSelectList(Lb,Index,pbh); if(pb1) pDoc->DrawGraph(&ht,Lb,Index,0,1,m_bColor); } else { CDrawCntrItem* pItemHit=NULL; POSITION pos=pDoc->GetStartPosition(); while(pos!=NULL) { CDrawCntrItem* pItem=(CDrawCntrItem*)pDoc->GetNextItem(pos); if(pItem->IsPoint(point)) pItemHit=pItem; } if(pItemHit==NULL||m_pSelection!=pItemHit) { COleClientItem * pActiveItem=GetDocument()->GetInPlaceActiveItem(this); if(pActiveItem!=NULL&&pActiveItem!=pItemHit) pActiveItem->Close(); } Invalidate(); m_pSelection=pItemHit; if(pItemHit!=NULL) { pDoc->b_IsOleSelect=TRUE; pItemHit->b_Select=TRUE; CRectTracker tracker; PutTracker(pItemHit,&tracker); UpdateWindow(); if(tracker.Track(this,point)) { Invalidate(); VPtoDP(tracker.m_rect.left,tracker.m_rect.bottom,&pItemHit->m_X1,&pItemHit->m_Y1); VPtoDP(tracker.m_rect.right,tracker.m_rect.top,&pItemHit->m_X2,&pItemHit->m_Y2); GetDocument()->SetModifiedFlag(); } } } } else if(m_DrawCurrent==31) //进行鼠标选择图形操作 { CString m_str; char p1[9]; xx1=m_xStart+blc*point.x; //点中点的实际x坐标 yy1=m_yStart+blc*(m_hScreen-point.y); //点中点的实际y坐标 float jl=blc*4; //点中范围(4个像素的实际距离) BOOL pb=pDoc->PointSelect(xx1,yy1,jl,blc,&Lb,&Index,&pbh); if(pb) { if(m_pLinkSet->IsOpen()) m_pLinkSet->Close(); m_str="(graph_id="; sprintf(p1,"%d",Lb); m_str+=p1; m_str+=") AND (element_id="; sprintf(p1,"%d",pbh); m_str+=p1; m_str+=")"; m_pLinkSet->m_strFilter=m_str; m_pLinkSet->Open(); if(m_pLinkSet->IsBOF()) { m_pLinkSet->Close(); return; } CDataLinkDlg pDg1(pDoc,m_pLinkSet); pDg1.DoModal(); } } else if(m_DrawCurrent==20) //进行图形粘贴操作 { OnSelectClear(); xx1=m_xStart+blc*point.x; //点中点的实际x坐标 yy1=m_yStart+blc*(m_hScreen-point.y); //点中点的实际y坐标 if(pDoc->ReadClipBoard(xx1,yy1)) { // for(int i=0;i n_GraphSelect;i++) //删除图形 // Delete(&ht,pDoc->GraphSelect[i].Lb,pDoc->GraphSelect[i].Index); //以下是记录删除图形这一操作,供逆操作时用 pDoc->AddUndo(2,pDoc->n_GraphSelect,pDoc->GraphSelect); pDoc->n_GraphSelect=0; //选中的图形元素为0 Invalidate(); } } CView::OnLButtonDown(nFlags, point); } //鼠标移动时被调用,ON_WM_MOUSEMOVE消息的映射函数 void CDrawView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDrawDoc* pDoc = GetDocument(); //得到文档的指针 CClientDC ddd(this); CPen pen(0,0,RGB(0,0,0)); CPen* pOldPen=ddd.SelectObject(&pen); ddd.SetROP2(R2_NOT); //选择反色的绘画模式 int r; BOOL pb; float x1,y1; char p1[20]; CMainFrame* pFrame=(CMainFrame*)(AfxGetApp()->m_pMainWnd); VPtoDP(point.x,point.y,&x1,&y1); sprintf(p1,"%f",x1); //将横坐标变为字符串 pFrame->m_wndStatusBar.SetPaneText(2,p1,TRUE);//在状态条的第3个指示器写入 sprintf(p1,"%f",y1); //将总坐标转为字符串 pFrame->m_wndStatusBar.SetPaneText(3,p1,TRUE);//在状态条的第4个指示器写入 if(m_DrawCurrent==1&&PushNumb==1)//如果是绘制直线并且已经按下第一点 { if(mPointOld!=point)//如果鼠标的现在移动点与上一个点不相同 //将起点到上一个移动点的直线擦除,绘制从起点到现在移动点的直线 { ddd.MoveTo(mPointOrign); ddd.LineTo(mPointOld); //擦除上一条线 ddd.MoveTo(mPointOrign); ddd.LineTo(point); //画到鼠标移动点的直线 mPointOld=point; } } else if((m_DrawCurrent==2||m_DrawCurrent==3)&&PushNumb>=1) //如果是绘制连续直线或封闭多边形,并且已经按下第一点 { if(mPointOld!=point)//如果鼠标的现在移动点与上一个点不相同 //将上一个顶点到上一个移动点的直线擦除,绘制从上一个顶点到移动点的直线 { ddd.MoveTo(mPointOrign); ddd.LineTo(mPointOld); //擦除原来的直线 ddd.MoveTo(mPointOrign); ddd.LineTo(point); //重画移动到点的直线 mPointOld=point; } } else if((m_DrawCurrent==4||m_DrawCurrent==5)&&PushNumb>=1) //如果是绘制圆或圆形区域,并且已经按下第一点 { if(mPointOld!=point)//如果鼠标的现在移动点与上一个点不相同 //将原来的圆擦掉,重新绘制圆 { if(m_DrawCurrent==4) ddd.SelectStockObject(NULL_BRUSH); //如果是普通圆,设置不填充状态 //上一个圆的半径 r=(int)sqrt(pow((float)(mPointOrign.x-mPointOld.x),2)+pow((float)(mPointOrign.y-mPointOld.y),2)); //擦除上一个圆 ddd.Ellipse(mPointOrign.x-r,mPointOrign.y-r,mPointOrign.x+r,mPointOrign.y+r); //移动点所在圆的半径 r=(int)sqrt(pow((long)(mPointOrign.x-point.x),2)+pow((float)(mPointOrign.y-point.y),2)); //绘制一个新圆 ddd.Ellipse(mPointOrign.x-r,mPointOrign.y-r,mPointOrign.x+r,mPointOrign.y+r); mPointOld=point; } } else if(m_DrawCurrent==6) //在绘制圆弧操作 { if(PushNumb==2&&mPointOld!=point) //按下第二个点后 { if(DrawArcYes>0) //如果不是第一次画弧 m_Arc1.Draw(&ddd,1,0,m_bColor); //擦掉原来的圆弧 pb=jsarc(mPointOrign1,mPointOrign,point,&m_CircleX,&m_CircleY, &m_CircleR,&m_Angle1,&m_Angle2); //计算目前圆弧的参数 if(pb) //如果三点能够形成圆弧,则以反色模式重新绘制实际是擦除圆弧 { m_Arc1.Init(m_pColor,m_brColor,m_LineWide,m_LineType, m_Layer,m_CircleX,m_CircleY,m_CircleR,0,m_Angle1,m_Angle2); m_Arc1.Draw(&ddd,1,0,m_bColor); } DrawArcYes=pb; //判断下一次绘制弧时要先删除弧 mPointOld=point; // int id=pDoc->GetArcId(); // if (DrawArcYes>0) // { // pb=jsarc(mPointOrign1,mPointOrign,mPointOld,&m_CircleX,&m_CircleY, // &m_CircleR,&m_Angle1,&m_Angle2); //计算目前圆弧的参数 // pDoc->AddArc(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id, // m_CircleX,m_CircleY,m_CircleR,0,m_Angle1,m_Angle2) // ->Draw(&ddd,0,0,m_bColor); // PushNumb=0; ////鼠标按键次数为0,重新进行圆弧的绘制 // // //ddd.AngleArc(m_CircleX,m_CircleY,m_CircleR,m_Angle1,m_Angle2); // pb=jsarc(mPointOrign1,mPointOrign,point,&m_CircleX,&m_CircleY, // &m_CircleR,&m_Angle1,&m_Angle2); //计算目前圆弧的参数 // pDoc->AddArc(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id, // m_CircleX,m_CircleY,m_CircleR,0,m_Angle1,m_Angle2) // ->Draw(&ddd,0,0,m_bColor); DrawArcYes=pb; //判断下一次绘制弧时要先删除弧 // mPointOld=point; // } // else // { // pb=jsarc(mPointOrign1,mPointOrign,point,&m_CircleX,&m_CircleY, // &m_CircleR,&m_Angle1,&m_Angle2); //计算目前圆弧的参数 // pDoc->AddArc(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id, // m_CircleX,m_CircleY,m_CircleR,0,m_Angle1,m_Angle2) // ->Draw(&ddd,0,0,m_bColor); // } } else if (PushNumb==1) { ddd.MoveTo(mPointOrign1); ddd.LineTo(mPointOld); //擦除原来的直线 ddd.MoveTo(mPointOrign1); ddd.LineTo(point); //重画移动到点的直线 mPointOld=point; } } else if((m_DrawCurrent==11||m_DrawCurrent==12||m_DrawCurrent==50)&&PushNumb==1) //如果是图形放大或移动并且按下了第一点 { if(point!=mPointOld) //如果鼠标移动了 { if(m_DrawCurrent==11||m_DrawCurrent==50) //如果是图形放大操作 { ddd.SelectStockObject(NULL_BRUSH); //设置不填充状态 //擦除原来的矩形 ddd.Rectangle(mPointOrign.x,mPointOrign.y,mPointOld.x,mPointOld.y); //画新的矩形 ddd.Rectangle(mPointOrign.x,mPointOrign.y,point.x,point.y); } else //如果是图形移动操作 { //擦除原来的橡皮线 ddd.MoveTo(mPointOrign); ddd.LineTo(mPointOld); //画新的橡皮线 ddd.MoveTo(mPointOrign); ddd.LineTo(point); } mPointOld=point; //将本次移动点作为下次移动的上一点 } } ddd.SelectObject(pOldPen); //选出画笔 CView::OnMouseMove(nFlags, point); } //按下鼠标右键时被调用,ON_WM_RBUTTONDOWN消息的映射函数 void CDrawView::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default int r; CDrawDoc* pDoc = GetDocument(); CClientDC ddd(this); CPen pen(0,0,RGB(0,0,0)); //定义一个画笔 CPen* pOldPen=ddd.SelectObject(&pen); //选择一个画笔 ddd.SetROP2(R2_NOT); //设置反色的绘画模式 if(m_DrawCurrent==1&&PushNumb==1) //如果正在绘制直线并且已经按下了起点 { //将直线从屏幕上擦除并使绘制处于起始状态 ddd.MoveTo(mPointOrign); ddd.LineTo(mPointOld); //擦除屏幕上的拖动线 PushNumb=0; //结束绘制 ReleaseCapture(); //释放捕捉的鼠标 } else if((m_DrawCurrent==2||m_DrawCurrent==3)&&PushNumb>0) { //如果正在绘制连续直线或多边形区域并且已经按下了一次以上鼠标左键 //擦除最后一段直线 ddd.MoveTo(mPointOrign); ddd.LineTo(mPointOld); if(m_DrawCurrent==2&&PushNumb>1) //如果顶点数大于1并在绘制直线 { //保存连续直线并重新绘制连续直线 int id=pDoc->GetPLineId(); pDoc->AddPLine(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id, PushNumb,PointXyz,0) ->Draw(&ddd,0,0,m_bColor); //以下是记录增加连续直线这一操作,供逆操作时用 GraphUndo[0].Index=pDoc->GetMaxIndex(2); GraphUndo[0].Lb=2; pDoc->AddUndo(2,1,GraphUndo); ReleaseCapture(); } else if(m_DrawCurrent==3&&PushNumb>2)//如果顶点数大于1并在绘制多边形区域 { //保存封闭多边形并重新绘制封闭多边形 int id=pDoc->GetPLineId(); pDoc->AddPLine(m_pColor,m_brColor,m_LineWide,m_LineType,m_Layer,id,PushNumb,PointXyz,1) ->Draw(&ddd,0,0,m_bColor); //以下是记录增加多边形区域这一操作,供逆操作时用 GraphUndo[0].Index=pDoc->GetMaxIndex(2); GraphUndo[0].Lb=2; pDoc->AddUndo(2,1,GraphUndo); ReleaseCapture(); } PushNumb=0; ReleaseCapture(); //释放捕捉的鼠标 } else if((m_DrawCurrent==4||m_DrawCurrent==5)&&PushNumb>0) //如果是绘制圆或圆形区域,并且已经按下第一点 { if(m_DrawCurrent==4) ddd.SelectStockObject(NULL_BRUSH); //如果是普通圆,设置不填充状态 //得到上一个圆的半径 r=(int)sqrt(pow((float)(mPointOrign.x-mPointOld.x),2)+pow((float)(mPointOrign.y-mPointOld.y),2)); //重画以擦除圆 ddd.Ellipse(mPointOrign.x-r,mPointOrign.y-r,mPointOrign.x+r,mPointOrign.y+r); ReleaseCapture(); //释放捕捉的鼠标 PushNumb=0; } else if(m_DrawCurrent==6&&PushNumb>0)//正在绘制弧并且按下了第一点 { if(PushNumb==2)//已经按下两个点正在拖动弧 m_Arc1.Draw(&ddd,1,0,m_bColor); //擦掉原来的弧 PushNumb=0; //没有按中键 ReleaseCapture(); } else if((m_DrawCurrent==11||m_DrawCurrent==12||m_DrawCurrent==50)&&PushNumb==1) //如果在进行图形放大或图形移动并且按下了一次鼠标左键 { ddd.SelectStockObject(NULL_BRUSH); //设置不填充状态 if(m_DrawCurrent==11||m_DrawCurrent==50) //如果是在“图形放大”,擦除矩形框 ddd.Rectangle(mPointOrign.x,mPointOrign.y,point.x,point.y); else //如果是在“图形移动”,擦除橡皮线 { ddd.MoveTo(mPointOrign); ddd.LineTo(point); } ReleaseCapture(); //释放捕捉的鼠标 PushNumb=0; //放弃操作,使左键按下数置0 } ddd.SelectObject(pOldPen); CView::OnRButtonDown(nFlags, point); } //“图形重画”菜单项的映射函数 void CDrawView::OnGraphRedraw() { CDrawDoc* pDoc = GetDocument(); //得到文档的指针 Invalidate(); pDoc->UpdateAllViews(this); } //“图形放大”菜单项的映射函数 void CDrawView::OnGraphZoom() { m_DrawCurrent=11; //标识进行图形放大操作 PushNumb=0; } //“图形移动”菜单项的对应函数 void CDrawView::OnGraphPan() { m_DrawCurrent=12; //标识进行图形移动操作 PushNumb=0; } //“重画上屏”菜单项的对应函数 void CDrawView::OnGraphUp() { CDrawDoc *pDoc=(CDrawDoc *)GetDocument(); if(pDoc->m_CurrentScreen>0) //如果不是第一屏 pDoc->m_CurrentScreen--; //得到上一屏的图形参数并重画 m_xStart=p_Screen[pDoc->m_CurrentScreen].sx; m_yStart=p_Screen[pDoc->m_CurrentScreen].sy; blc=p_Screen[pDoc->m_CurrentScreen].blc; InitVScroll(); InitHScroll(); Invalidate(); } //“重画首屏”菜单项的对应函数 void CDrawView::OnGraphFirst() { CDrawDoc *pDoc=(CDrawDoc *)GetDocument(); if(pDoc->m_CurrentScreen==0) return; m_xStart=p_Screen[0].sx; m_yStart=p_Screen[0].sy; blc=p_Screen[0].blc; pDoc->AddScreen(m_xStart,m_yStart,blc); InitVScroll(); InitHScroll(); Invalidate(); } //“重画全屏”菜单项的对应函数 void CDrawView::OnGraphAll() { float minx,miny,maxx,maxy,bl1; CDrawDoc* pDoc = GetDocument(); //捕捉光标,并使光标成沙漏等待光标 //把最小值给非常大,把最大值给非常小,为了对变量进行初试化 minx=(float)1E20;miny=(float)1E20;maxx=-(float)1E20;maxy=-(float)1E20; SetCapture(); SetCursor(LoadCursor(NULL,IDC_WAIT)); BOOL pb=pDoc->GetRect(&minx,&miny,&maxx,&maxy); //将光标变为箭头形,放弃捕捉的光标 SetCursor(LoadCursor(NULL,IDC_ARROW)); ReleaseCapture(); if(!pb) //没有图形元素,程序返回 return; bl1=(maxx-minx)/(m_wScreen-20);//横向的比例 blc=(maxy-miny)/(m_hScreen-20);//实际纵向比例 if(bl1>blc)blc=bl1; //取较大的一个作为比例尺 /*以下确定屏幕左下角的实际坐标,即在左侧和下侧都留了10点阵的区域 (minx,miny)在屏幕的左下角向右10点阵同时向上10点阵处。*/ m_xStart=minx-10*blc; m_yStart=miny-10*blc; //将全图的显示比例放在首屏,并把屏幕设为首屏 p_Screen[0].sx=m_xStart; p_Screen[0].sy=m_yStart; p_Screen[0].blc=blc; pDoc->m_CurrentScreen=0; InitVScroll(); InitHScroll(); Invalidate(); } //“鼠标选中”菜单项的对应函数 void CDrawView::OnSelectMouse() { m_DrawCurrent=30; //标识进行图形选中操作 PushNumb=0; } //“放弃选中”菜单项的对应函数,用来放弃所作的选择 void CDrawView::OnSelectClear() { CDrawDoc* pDoc = GetDocument(); CClientDC ht(this); for(int i=0;i n_GraphSelect;i++) //将选中的图形元素原样进行绘制 pDoc->DrawGraph(&ht,pDoc->GraphSelect[i].Lb,pDoc->GraphSelect[i].Index,0,0,m_bColor); pDoc->n_GraphSelect=0; if(pDoc->b_IsOleSelect) { POSITION pos=pDoc->GetStartPosition(); while(pos!=NULL) { CDrawCntrItem *pItem=(CDrawCntrItem *)pDoc->GetNextClientItem(pos); if(pItem!=NULL) pItem->b_Select=FALSE; } pDoc->b_IsOleSelect=0; Invalidate(); } } //用来删除一个图形元素的函授数 //Lb-删除图形的类别 Index-删除图形顶序列号 void CDrawView::Delete(CDC* pDC,int Lb,int Index) { float x1,y1,x2,y2; CDrawDoc* pDoc = GetDocument(); if(Lb==1) //如果是直线,得到直线指针并以屏幕底色重画达到删除的效果 { CLine* p_Line=pDoc->GetLine(Index); p_Line->Draw(pDC,0,2,m_bColor); p_Line->Delete(1); //做删除标识 } else if(Lb==2) //如果是连续直线或多边形 { CPline* p_PLine=pDoc->GetPLine(Index); //得到连续直线(多边形)的指针 if(p_PLine->IsPLine()) //如果是连续直线,以屏幕底色重画达到删除的效果 p_PLine->Draw(pDC,0,2,m_bColor); else //如果是多边形区域 { p_PLine->GetRect(&x1,&y1,&x2,&y2); //得到多边形区域的边界矩形 ReDrawRect(x1,y1,x2,y2); //重画多边形区域所在顶区域 } p_PLine->Delete(1); //做删除标识 } else if(Lb==3) //如果是圆或圆形区域 { CCircle* p_Circle=pDoc->GetCircle(Index);//得到圆(圆形区域)的指针 if(p_Circle->IsCircle()) //如果是圆,则以屏幕底色进行重画 p_Circle->Draw(pDC,0,2,m_bColor); else //如果是圆形区域,则得到其边界矩形并重画这个区域 { p_Circle->GetRect(&x1,&y1,&x2,&y2); ReDrawRect(x1,y1,x2,y2); } p_Circle->Delete(1); //做删除标识 } else if(Lb==4) //如果是圆弧,则以屏幕底色进行重画 { CArc* p_Arc=pDoc->GetArc(Index); //得到圆弧的指针 p_Arc->Draw(pDC,0,2,m_bColor); p_Arc->Delete(1); //做删除标识 } else if(Lb==5) //如果是标注文字,则得到其边界矩形并重画这个区域 { CText* p_Text=pDoc->GetText(Index); //得到标注文字的指针 p_Text->GetRect(&x1,&y1,&x2,&y2); p_Text->Delete(1); //做删除标识 ReDrawRect(x1,y1,x2,y2);//重画屏幕区域 } } //此函数用来重画由点(X1,Y1)和点(X2,Y2)确定的区域 void CDrawView::ReDrawRect(float X1, float Y1, float X2, float Y2) { float xx1,xx2,yy1,yy2; CRect r1; xx1=m_xStart; xx2=m_xStart+blc*m_wScreen; yy1=m_yStart; yy2=m_yStart+blc*m_hScreen; //得到区域与视图区域相交的矩形 BOOL IsCross=RectCross(&xx1,&yy1,&xx2,&yy2,X1,Y1,X2,Y2); if(IsCross) //如果相交,则重画这一区域 { //以下得到这个区域顶像素坐标 r1.left=(int)((xx1-m_xStart)/blc)-1; r1.right=(int)((xx2-m_xStart)/blc)+1; r1.top=m_hScreen-(int)((yy2-m_yStart)/blc)-1; r1.bottom=m_hScreen-(int)((yy1-m_yStart)/blc)+1; InvalidateRect(r1); } } //此函数用来计算由(*x1,*y1),(*x2,*y2)和(xx1,yy1),(xx2,yy2)决定的两个区域的相交区域 //返回:TURE,两区域相交,相交区域由(*x1,*y1),(*x2,*y2)决定 BOOL CDrawView::RectCross(float* x1,float* y1,float* x2,float* y2,float xx1, float yy1,float xx2,float yy2) { float m_X1,m_Y1,m_X2,m_Y2; m_X1=*x1; m_Y1=*y1; m_X2=*x2 ;m_Y2=*y2; if(m_X1>xx2||m_X2 yy2||m_Y2 n_GraphSelect;i++) //删除选中的图形 Delete(&ht,pDoc->GraphSelect[i].Lb,pDoc->GraphSelect[i].Index); //以下是记录删除图形这一操作,供逆操作时用 pDoc->AddUndo(3,pDoc->n_GraphSelect,pDoc->GraphSelect); ReleaseCapture(); pDoc->n_GraphSelect=0; //选中的图形元素为0 if(pDoc->b_IsOleSelect) { POSITION pos=pDoc->GetStartPosition(); while(pos!=NULL) { CDrawCntrItem *pItem=(CDrawCntrItem *)pDoc->GetNextClientItem(pos); if(pItem!=NULL) { if(pItem->b_Select) { pDoc->RemoveItem(pItem); delete pItem; m_pSelection =NULL; // set selection to last inserted item } } } pDoc->UpdateAllViews(this); } } //“Cut"菜单项的对应函数,用来删除鼠标选中的图形并将删除的图形放在剪裁板 void CDrawView::OnEditCut() { CClientDC ht(this); CDrawDoc* pDoc = GetDocument(); if(pDoc->WriteClipBoard()) { for(int i=0;i n_GraphSelect;i++) //删除图形 Delete(&ht,pDoc->GraphSelect[i].Lb,pDoc->GraphSelect[i].Index); //以下是记录删除图形这一操作,供逆操作时用 pDoc->AddUndo(3,pDoc->n_GraphSelect,pDoc->GraphSelect); pDoc->n_GraphSelect=0; //选中的图形元素为0 } } void CDrawView::OnEditPaste() { m_DrawCurrent=20; PushNumb=0; } //“Copy"菜单项的对应函数,用来将选中的图形放在剪裁板 void CDrawView::OnEditCopy() { CDrawDoc* pDoc = GetDocument(); pDoc->WriteClipBoard(); //将图形写入剪裁板 } //“Undo"菜单项的对应函数,用来实现完全的逆操作 void CDrawView::OnEditUndo() { CDrawDoc* pDoc = GetDocument(); CClientDC ht(this); pDoc->OnEditUndo(); //进行一步逆操作 pDoc->UpdateAllViews(this); //重画所有视图 } void CDrawView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { short nScrollInc; int nNewPos; CRect r1; switch(nSBCode) { case SB_TOP: nScrollInc=-nHScrollPos; break; case SB_BOTTOM: nScrollInc=nHScrollMax-nHScrollPos; break; case SB_LINEUP: nScrollInc=-nXLine; break; case SB_LINEDOWN: nScrollInc=nXLine; break; case SB_PAGEUP: nScrollInc=-nXPage; break; case SB_PAGEDOWN: nScrollInc=nXPage; break; case SB_THUMBPOSITION: nScrollInc=nPos-nHScrollPos; break; default: nScrollInc=0; } nNewPos=max(0,min(nHScrollPos+nScrollInc,nHScrollMax)); nScrollInc=nNewPos-nHScrollPos; if(nScrollInc) //如果产生了滚动 { nHScrollPos=nNewPos; //设定新的滚动位置 SetScrollPos(SB_HORZ,nHScrollPos); UpdateWindow();//使滚动条的位置改动在屏幕上实现 m_xStart=m_xStart+blc*nScrollInc*nScrollMin;//调整纵坐标使图形产生滚动 GetClientRect(&r1); //得到客户区的矩形边界 if(abs(nScrollInc)*nScrollMin 0) //如果是图形向上滚动 r1.left=nScrollInc*nScrollMin; //得到滚动屏幕上重叠区域的矩形 else //如果图形向下滚动 r1.right=r1.right-nScrollInc*nScrollMin; //得到重叠区域的矩形 ScrollWindow(-nScrollInc*nScrollMin,0,r1); //滚动重叠的区域 if(nScrollInc>0) //如果是向上滚动 r1.left=r1.right-nScrollInc*nScrollMin; //得到需要重画的区域 else //如果是向下滚动 r1.right=-nScrollInc*nScrollMin; //得到需要重画的区域 InvalidateRect(r1,0); //对图形进行局部重画 } else //如果滚动后的区域与滚动前的区域没有重叠,则全屏重画 Invalidate(); //恢复矩形rr原来的坐标 // r.left=0; // r.right=ScreenWide; } /* if(nScrollInc) { nHScrollPos=nNewPos; SetScrollPos(SB_HORZ,nHScrollPos); UpdateWindow(); startx=startx+blc*nScrollInc*nScrollMin; Screenxy[numb][0]=startx; Invalidate(); r.top=0; r.bottom=ScreenHigh; }*/ CView::OnHScroll(nSBCode, nPos, pScrollBar); } void CDrawView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { short nScrollInc; int nNewPos; CRect r1; switch(nSBCode) //判断按键位置 { case SB_TOP: //如果将滚动条滚动到顶部 nScrollInc=-nVScrollPos; //得到相对滚动范围 break; case SB_BOTTOM: //如果将滚动条滚动到底部 nScrollInc=nVScrollMax-nVScrollPos; //得到相对的滚动范围 break; case SB_LINEUP: //如果按了滚动条中的向上的按键 nScrollInc=-nYLine; //得到相对滚动位置 break; case SB_LINEDOWN: //如果按中了向下的按键 nScrollInc=nYLine; //得到相对的滚动位置 break; case SB_PAGEUP: //如果按中了中间活动按钮的上部区域 nScrollInc=-nYPage; //得到相对的滚动位置 break; case SB_PAGEDOWN: //如果按中了中间活动钮的下部位置 nScrollInc=nYPage; //得到相对的滚动位置 break; case SB_THUMBPOSITION: //如果用鼠标拖动中间活动钮到一个位置 nScrollInc=nPos-nVScrollPos; //通过信息处理函数得到的按钮位置得到相对移动位置 break; default: nScrollInc=0; } //进行滚动边界检查,得到实际的滚动位置(不能超出滚动条的滚动范围) nNewPos=max(0,min(nVScrollPos+nScrollInc,nVScrollMax)); //得到实际的相对滚动范围 nScrollInc=nNewPos-nVScrollPos; if(nScrollInc) //如果产生了滚动 { nVScrollPos=nNewPos; //设定新的滚动位置 SetScrollPos(SB_VERT,nVScrollPos); UpdateWindow();//使滚动条的位置改动在屏幕上实现 m_yStart=m_yStart-blc*nScrollInc*nScrollMin;//调整纵坐标使图形产生滚动 GetClientRect(&r1); //得到客户区的矩形边界 if(abs(nScrollInc)*nScrollMin 0) //如果是图形向上滚动 r1.top=nScrollInc*nScrollMin; //得到滚动屏幕上重叠区域的矩形 else //如果图形向下滚动 r1.bottom=r1.bottom+nScrollInc*nScrollMin; //得到重叠区域的矩形 ScrollWindow(0,-nScrollInc*nScrollMin,r1); //滚动重叠的区域 if(nScrollInc>0) //如果是向上滚动 r1.top=r1.bottom-nScrollInc*nScrollMin; //得到需要重画的区域 else //如果是向下滚动 r1.bottom=-nScrollInc*nScrollMin; //得到需要重画的区域 InvalidateRect(r1,0); //对图形进行局部重画 //pbdy=1; } else //如果滚动后的区域与滚动前的区域没有重叠,则全屏重画 Invalidate(); } CView::OnVScroll(nSBCode, nPos, pScrollBar); } void CDrawView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch(nChar) { case VK_HOME: OnHScroll(SB_PAGEUP,0,NULL); break; case VK_END: OnHScroll(SB_PAGEDOWN,0,NULL); break; case VK_PRIOR: OnVScroll(SB_PAGEUP,0,NULL); break; case VK_NEXT: OnVScroll(SB_PAGEDOWN,0,NULL); break; case VK_UP: OnVScroll(SB_LINEUP,0,NULL); break; case VK_DOWN: OnVScroll(SB_LINEDOWN,0,NULL); break; case VK_LEFT: OnHScroll(SB_LINEUP,0,NULL); break; case VK_RIGHT: OnHScroll(SB_LINEDOWN,0,NULL); break; } CView::OnKeyDown(nChar, nRepCnt, nFlags); } void CDrawView::OnChangeDlgEdit() { char p1[7]; CMainFrame* p_Wnd=(CMainFrame *)(AfxGetApp()->m_pMainWnd); p_Wnd->m_wndDlgBar.GetDlgItemText(IDC_EDIT1,p1,6); m_LineWide=(unsigned char)atoi(p1); } void CDrawView::OnChangeDlgCom() { CMainFrame* p_Wnd=(CMainFrame *)(AfxGetApp()->m_pMainWnd); CComboBox* plist=(CComboBox*)(p_Wnd->m_wndDlgBar.GetDlgItem(IDC_COMBO1)); m_LineType=(unsigned char)plist->GetCurSel(); } void CDrawView::OnBitmapCut() { CBitmap Bitmap; CClientDC ht(this); CDC MemDC; RECT r1; GetClientRect(&r1); Bitmap.CreateCompatibleBitmap(&ht,r1.right-r1.left,r1.bottom-r1.top); MemDC.CreateCompatibleDC(&ht); MemDC.SelectObject(&Bitmap); MemDC.BitBlt(0,0,r1.right-r1.left,r1.bottom-r1.top,&ht,0,0,SRCCOPY); ht.BitBlt(0,0,r1.right-r1.left,r1.bottom-r1.top,&MemDC,100,100,SRCCOPY); if(!OpenClipboard()) return; EmptyClipboard(); ::SetClipboardData(CF_BITMAP,Bitmap.m_hObject); Bitmap.Detach(); CloseClipboard(); } void CDrawView::OnBitmapPaste() { CClientDC ht(this); CBitmap Bitmap; BITMAP BitmapInfo; HANDLE HBitmap; CDC MemDC; if(!OpenClipboard()) return; HBitmap=::GetClipboardData(CF_BITMAP); if(HBitmap==NULL) { CloseClipboard(); return; } Bitmap.Attach(HBitmap); Bitmap.GetObject(sizeof(BITMAP),&BitmapInfo); MemDC.CreateCompatibleDC(&ht); MemDC.SelectObject(&Bitmap); ht.BitBlt(0,0,BitmapInfo.bmWidth,BitmapInfo.bmHeight,&MemDC,0,0,SRCCOPY); Bitmap.Detach(); ::CloseClipboard(); } void CDrawView::OnUpdateEditPaste(CCmdUI* pCmdUI) { } void CDrawView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { char p1[6]; p_View=this; CDrawDoc *pDoc=(CDrawDoc *)GetDocument(); p_Screen=pDoc->m_Screen; CMainFrame* p_Wnd=(CMainFrame *)(AfxGetApp()->m_pMainWnd); CComboBox* plist=(CComboBox*)(p_Wnd->m_wndDlgBar.GetDlgItem(IDC_COMBO1)); plist->SetCurSel(m_LineType); sprintf(p1,"%d",(int)m_LineWide); p_Wnd->m_wndDlgBar.SetDlgItemText(IDC_EDIT1,p1); CView::OnActivateView(bActivate, pActivateView, pDeactiveView); } void CDrawView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) { if(pInfo==NULL) //如果是屏幕显示 return; //当前打印页所在的行 pDC->SetMapMode(m_MapMode); int nRow=pInfo->m_nCurPage/nPageX+(pInfo->m_nCurPage%nPageX); //当前打印页所在的列 int nCol=(pInfo->m_nCurPage-1)%nPageX+1; m_xStart=xLeft+(nCol-1)*xPage; //当前页输出的图形左下角的实际横坐标 m_yStart=yTop-nRow*yPage; //当前页输出的图形左下角的实际纵坐标 pDC->SetWindowOrg(0,0); CView::OnPrepareDC(pDC, pInfo); } void CDrawView::OnPrint(CDC* pDC, CPrintInfo* pInfo) { char p1[4]; CString strHeader=GetDocument()->GetTitle(); sprintf(p1,"%d",pInfo->m_nCurPage); strHeader+=" 第"; strHeader+=p1; strHeader+="页"; POINT point; m_MapMode=pDC->GetMapMode(); point.x=0;point.y=25; pDC->DPtoLP(&point); pDC->SetTextAlign(TA_LEFT); pDC->TextOut(0,point.y,strHeader); TEXTMETRIC textMetric; pDC->GetTextMetrics(&textMetric); int y; if(m_MapMode==1) y=point.y+textMetric.tmHeight; else y=point.y-textMetric.tmHeight; pDC->MoveTo(0,y); pDC->LineTo(pInfo->m_rectDraw.right,y); OnDraw(pDC); } void CDrawView::DrawBmp1(CDC* pDC,int x,int y,int wide,int high,UINT idCBitmap,int DrawMode) { int wide1,high1; int w_CBitmap,h_CBitmap; CBitmap Bitmap; BITMAP BM; //定义一个BITMAP型的结构 CDC pDC1; //定义一个绘图设备对象 //将资源文件中定义的位图资源选入位图对象 Bitmap.LoadBitmap(idCBitmap); Bitmap.GetObject(sizeof(BM),&BM); //得到位图对象的信息 w_CBitmap=BM.bmWidth; //得到位图的宽度(像素) h_CBitmap=BM.bmHeight; //得到位图的高度(像素) if(DrawMode==1) //原样大小显示 { wide1=w_CBitmap; high1=h_CBitmap; } else if(DrawMode==2)//按参数给定的区域显示,纵横伸缩比例一样 { float bl1=(float)wide/w_CBitmap; float bl2=(float)high/h_CBitmap; if(bl1>bl2) { high1=high; wide1=(int)(bl2*wide); } else { wide1=wide; high1=(int)(bl1*high); } } else if(DrawMode==3) //严格按参数给定的区域显示 { wide1=wide; high1=high; } //创建一个与绘图设备兼容的内存设备描述对象 pDC1.CreateCompatibleDC(pDC); pDC1.SelectObject(&Bitmap); //将位图选入内存设备描述对象 //将内存设备描述对象的位图拷贝到屏幕上 pDC->StretchBlt(x,y,wide1,high1,&pDC1,0,0,w_CBitmap,h_CBitmap,SRCCOPY); Bitmap.DeleteObject(); //删除位图对象 } void CDrawView::DrawBmp2(CDC* pDC,int x,int y,int wide,int high,char *fName,int DrawMode) { char p1[80]; BITMAPFILEHEADER fileh; //定义一个文件标题结构 LPBITMAPINFOHEADER fileh1; //定义一个信息标题结构 CFile FileBmp; CBitmap* pOldMap; CDC pDC1; //定义一个设备描述表 int i,wide1,high1,maxread; short int bytes_per_line; unsigned char *BmpChar; long bmpsize; maxread=64*512; BOOL YN=FileBmp.Open(fName,CFile::typeBinary|CFile::modeRead); if(YN==0) //如果文件打开错误,给出出错信息 { strcpy(p1,"位图文件"); strcpy(p1,fName); strcat(p1,"不存在"); AfxMessageBox(p1); return; } //以下读入位图的文件标题 FileBmp.Read((unsigned char *)&fileh,sizeof(fileh)); if(fileh.bfType!=19778) //判断是否是一个位图文件,19778是"BM"的数值 { //如果不是一个位图文件,加入提示信息,关闭文件退出 FileBmp.Close(); strcpy(p1,"文件"); strcat(p1,fName); strcat(p1,"不是一个位图文件"); AfxMessageBox(p1); return; } bmpsize=fileh.bfSize-sizeof(BITMAPFILEHEADER); bmpdata=GlobalAllocPtr(GHND,bmpsize); if(bmpdata==0) return; BmpChar=new unsigned char[maxread]; if(BmpChar==NULL) { GlobalFreePtr(bmpdata); return; } unsigned char *data=(unsigned char *)bmpdata; int chunksize; while(bmpsize) { if(bmpsize>maxread) chunksize=maxread; else chunksize=bmpsize; FileBmp.Read(BmpChar,chunksize); for(i=0;i biWidth*(long)fileh1->biBitCount+31L)/32*4; if(fileh1->biSize==12) return; if(fileh1->biClrUsed!=0) nPalate=fileh1->biClrUsed; else { switch(fileh1->biBitCount) { case 1: nPalate=2; break; case 4: nPalate=16; break; case 8: nPalate=256; break; case 24: nPalate=0; break; default: nPalate=2; break; } } bhm_ddb=0; if(fileh1!=NULL) { if(hpal==0&&nPalate>0)//如果调色板颜色数量大于0 { make_palette(); } if(bhm_ddb==0) DIBtoDDB(pDC->GetSafeHdc()); } if(DrawMode==1) //原样大小显示 { wide1=fileh1->biWidth; high1=fileh1->biHeight; } else if(DrawMode==2)//按参数给定的区域显示,纵横伸缩比例一样 { float bl1=(float)wide/fileh1->biWidth; float bl2=(float)high/fileh1->biHeight; if(bl1>bl2) { high1=high; wide1=(int)(bl2*wide); } else { wide1=wide; high1=(int)(bl1*high); } } else if(DrawMode==3) //严格按参数给定的区域显示 { wide1=wide; high1=high; } if(bhm_ddb!=0) { pDC1.CreateCompatibleDC(pDC); pOldMap=pDC1.SelectObject(CBitmap::FromHandle(bhm_ddb)); //将内存设备描述对象中的图像映射到在屏幕中的显示区域 pDC->StretchBlt(x,y,wide1,high1,&pDC1,0,0,fileh1->biWidth,fileh1->biHeight,SRCCOPY); pDC1.SelectObject(pOldMap); } delete BmpChar; //释放字符串空间 FileBmp.Close(); //关闭文件 return ; } void CDrawView::DIBtoDDB(HDC hdc) { LPBITMAPINFOHEADER p_bminfo=(LPBITMAPINFOHEADER)(bmpdata); if(p_bminfo==0) return; if(bhm_ddb!=0) DeleteBitmap(bhm_ddb); LPSTR p_image=(LPSTR)p_bminfo+sizeof(BITMAPINFOHEADER)+nPalate*sizeof(RGBQUAD); HPALETTE hpalold=NULL; if(hpal) { hpalold=SelectPalette(hdc,hpal,FALSE); RealizePalette(hdc); } bhm_ddb=CreateDIBitmap(hdc,p_bminfo,CBM_INIT,p_image,(LPBITMAPINFO)p_bminfo,DIB_RGB_COLORS); if(hpalold) SelectPalette(hdc,hpalold,FALSE); } void CDrawView::make_palette() { LPBITMAPINFOHEADER p_bminfo=(LPBITMAPINFOHEADER)bmpdata; if(hpal!=0)DeletePalette(hpal); if(nPalate>0) { LPLOGPALETTE cp=(LPLOGPALETTE)GlobalAllocPtr(GHND,sizeof(LOGPALETTE)+nPalate*sizeof(PALETTEENTRY)); if(cp!=NULL) { cp->palVersion=0x0300; cp->palNumEntries=nPalate; //设置调色板入口 LPBITMAPINFO p_bi=(LPBITMAPINFO)p_bminfo; for(int i=0;i palPalEntry[i].peRed=p_bi->bmiColors[i].rgbRed; cp->palPalEntry[i].peGreen=p_bi->bmiColors[i].rgbGreen; cp->palPalEntry[i].peBlue=p_bi->bmiColors[i].rgbBlue; } hpal=CreatePalette(cp); //创建逻辑调色板 GlobalFreePtr(cp); } } } void CDrawView::DrawBmp3(CDC* pDC,int x,int y,int wide,int high,char *fName,int DrawMode) { char p1[80]; CRect r; BITMAPFILEHEADER fileh; //定义一个文件标题结构 BITMAPINFOHEADER fileh1; //定义一个信息标题结构 CBitmap Bitmap,*pOldMap; //定义一个位图对象 CDC pDC1; //定义一个设备描述表 unsigned char *BmpChar; int minx,miny,maxx,maxy,BmpStartX,BmpStartY,BmpEndX,BmpEndY; int i,j,xh,i1,j1,c1,c2,c3,nPalate; int IsCompress,bicount,bytes_per_line,wide1,high1; long filecd,boff,boxmfile1; float pbX,pbY; CPalette palatte,*pOldPalatte; //定义一个调色板结构 LOGPALETTE* cp; //定义一个逻辑调色板结构 RGBQUAD bmicolors[256]; // CFile FileBmp; BOOL YN=FileBmp.Open(fName,CFile::typeBinary|CFile::modeRead); if(YN==0) //如果文件打开错误,给出出错信息 { strcpy(p1,"位图文件"); strcpy(p1,fName); strcat(p1,"不存在"); AfxMessageBox(p1); return; } //以下读入位图的文件标题 FileBmp.Read((unsigned char *)&fileh,sizeof(fileh)); if(fileh.bfType!=19778) //判断是否是一个位图文件,19778是"BM"的数值 { FileBmp.Close(); strcpy(p1,"文件"); strcat(p1,fName); strcat(p1,"不是一个位图文件"); AfxMessageBox(p1); return; } boff=fileh.bfOffBits; //文件头的长度,文件从开始到实际位图起点的字节偏移量 filecd=fileh.bfSize; //位图文件的大小 FileBmp.Read((unsigned char *)&fileh1,sizeof(fileh1));//读入信息标题 GetClientRect(&r); if(DrawMode==1) //原样大小显示 { wide1=fileh1.biWidth; high1=fileh1.biHeight; } else if(DrawMode==2)//按参数给定的区域显示,纵横伸缩比例一样 { float pbX=(float)wide/fileh1.biWidth; float pbY=(float)high/fileh1.biHeight; if(pbX>pbY) { high1=high; wide1=(int)(pbY*wide); } else { wide1=wide; high1=(int)(pbX*high); } } else if(DrawMode==3) //严格按参数给定的区域显示 { wide1=wide; high1=high; } bicount=fileh1.biBitCount; //位图的位面数 IsCompress=fileh1.biCompression; //是否进行压缩 filecd=fileh1.biSizeImage; //图像尺寸大小 bytes_per_line=((long)fileh1.biWidth*bicount+31L)/32*4; if(fileh1.biClrUsed==0) //如果颜色索引数等于0 { if(bicount!=24) //如果不是24位位图 nPalate=(int)(pow(2,bicount)); //得到调色板颜色数 else nPalate=0; //如果是24位位图,调色板颜色数为0 } else //如果颜色索引数不等于0 { if(bicount!=24) nPalate=fileh1.biClrUsed;//直接得到调色版数量 else nPalate=0; } if(nPalate>0)//如果调色板颜色数量大于0 { for(i=0;i palNumEntries=nPalate; //设置调色板入口 cp->palVersion=0x0300; for(i=0;i palPalEntry[i].peRed=bmicolors[i].rgbRed; cp->palPalEntry[i].peGreen=bmicolors[i].rgbGreen; cp->palPalEntry[i].peBlue=bmicolors[i].rgbBlue; } palatte.CreatePalette(cp); //创建逻辑调色板 pOldPalatte=pDC1.SelectPalette(&palatte,FALSE); pDC1.RealizePalette();//从当前的调色板影射入口到系统调色板 } //分配一个用来读入位图一行位图数据的字符串 BmpChar=new unsigned char[bytes_per_line]; if(IsCompress!=0) { //如果位图是采用压缩方式的,我们不进行处理退出 strcpy(p1,"不处理压缩格式的位图文件"); AfxMessageBox(p1); FileBmp.Close(); delete BmpChar; return ; } //GetClientRect(&rr); //得到客户区的矩形边界 //如果两个图像绘制区域完全不在客户区内。 if(y+high1 r.bottom||x+wide1 r.right) { FileBmp.Close(); delete BmpChar; return ; } //得到在客户区上实际图像绘制区域的大小 minx=max(x,r.left); //右上角横坐标 maxx=min(x+wide1,r.right); miny=max(y,r.top); maxy=min(y+high1,r.bottom);//右下角纵坐标 //以下得到能够显示到屏幕部分的图像在图像文件中的具体位置 BmpStartX=(int)((float)fileh1.biWidth*(float)(minx-x)/(float)wide1); //每行起点 BmpEndX=fileh1.biWidth-1-(int)((float)fileh1.biWidth*(float)(x+wide1-maxx)/(float)wide1);//终点 BmpEndY=fileh1.biHeight-1-(int)(((float)fileh1.biHeight*(y+high1-maxy)/(float)high1));//起始行 BmpStartY=(int)((float)fileh1.biHeight*(miny-y)/(float)high1); //终止行 pbX=(float)fileh1.biWidth/wide1; //得到水平方向图像像素与要显示像素的比例 pbY=(float)fileh1.biHeight/high1; //竖直方向 if(pbX>1.5) //如果比例较大 { BmpStartX=minx; //将屏幕上图像显示区的起点作为起点 BmpEndX=maxx-1; //终点作为终点 } if(pbY>1.5) //如果竖直方向比例较大 { BmpStartY=miny; //起始行 BmpEndY=maxy-1; //结束行 } //建立一个空白位图 Bitmap.CreateCompatibleBitmap(pDC,BmpEndX-BmpStartX+1,BmpEndY-BmpStartY+1); pDC1.CreateCompatibleDC(pDC);//建立一个与当前设备兼容的内存设备描述对象 pOldMap=pDC1.SelectObject(&Bitmap); //将空白位图选入内存设备描述对象 //对所有行进行循环,将图像的实际内容装入空白位图 for(i=BmpEndY;i>=BmpStartY;i--) { if(pbY>1.5) //如果图像纵向压缩比例较大 i1=(int)(pbY*(i-y)); //得到图像文件中实际起始行 else i1=i; //以下得到实际起始行在文件中的位置,将这一行信息读入BmpChar中 boxmfile1=boff+(long)bytes_per_line*(fileh1.biHeight-1-i1); FileBmp.Seek(boxmfile1,0); FileBmp.Read((unsigned char *)BmpChar,bytes_per_line); for(j=BmpStartX;j<=BmpEndX;j++) //对一行中所有要显示的像素循环 { if(pbX>1.5) //如果横向压缩较大,得到像素点在一行中的实际位置 i1=(int)(pbX*(j-x)); else //否则,j的位置就是像素点在一行中的实际位置 i1=j; if(bicount==1) //如果是1位面位图 { //以下得到像素点的实际值,并在内存设备描述对象中写入点 j1=i1/8; xh=*(BmpChar+j1); j1=(int)(fmod(j,8)); j1=(int)(pow(2,7-j1)); //在内存描述对象中写入点 if(xh&j1) pDC1.SetPixel(j-BmpStartX,i-BmpStartY,RGB(bmicolors[1].rgbRed, bmicolors[1].rgbGreen,bmicolors[1].rgbBlue)); else pDC1.SetPixel(j-BmpStartX,i-BmpStartY,RGB(bmicolors[0].rgbRed, bmicolors[0].rgbGreen,bmicolors[0].rgbBlue)); } else if(bicount==4)//如果是4位面位图 { //以下得到像素的实际值 j1=i1/2; xh=*(BmpChar+j1); if(j1*2!=j) j1=xh-xh/16*16; else j1=xh/16; pDC1.SetPixel(j-BmpStartX,i-BmpStartY,RGB(bmicolors[j1].rgbRed, bmicolors[j1].rgbGreen,bmicolors[j1].rgbBlue)); } else if(bicount==8) //如果是8位面位图 { j1=*(BmpChar+i1); pDC1.SetPixel(j-BmpStartX,i-BmpStartY,RGB(bmicolors[j1].rgbRed, bmicolors[j1].rgbGreen,bmicolors[j1].rgbBlue)); } else if(bicount==24) { c1=*(BmpChar+3*(int)i1); c2=*(BmpChar+3*(int)i1+1); c3=*(BmpChar+3*(int)i1+2); pDC1.SetPixel(j-BmpStartX,i-BmpStartY,RGB(c3,c2,c1)); } } } //将内存设备描述对象中的图像映射到在屏幕中的显示区域 pDC->StretchBlt(minx,miny,maxx-minx,maxy-miny, &pDC1,0,0,BmpEndX-BmpStartX+1,BmpEndY-BmpStartY+1,SRCCOPY); pDC1.SelectObject(pOldMap); Bitmap.DeleteObject(); //删除位图 delete BmpChar; //释放字符串空间 FileBmp.Close(); //关闭文件 if(nPalate>0) //如果调色板颜色数量大于0 { free(cp); pDC1.SelectPalette(pOldPalatte,0); } return ; } void CDrawView::OnGraphDraw() { // TODO: Add your command handler code here CClientDC ht(this); DrawBmp3(&ht,100,100,300,200,"d:\\scan\\sharp\\cjc1.bmp",1); } void CDrawView::PutTracker(CDrawCntrItem *pItem,CRectTracker *pTracker) { int x1,y1,x2,y2; DPtoVP(pItem->m_X1,pItem->m_Y1,&x1,&y1); DPtoVP(pItem->m_X2,pItem->m_Y2,&x2,&y2); pTracker->m_rect.SetRect(x1-5,y2-5,x2+5,y1+5); if(pItem==m_pSelection) pTracker->m_nStyle|=CRectTracker::resizeInside; if(pItem->GetType()==OT_LINK) pTracker->m_nStyle|=CRectTracker::dottedLine; else pTracker->m_nStyle|=CRectTracker::solidLine; if(pItem->GetItemState()==COleClientItem::openState|| pItem->GetItemState()==COleClientItem::activeUIState) { pTracker->m_nStyle|=CRectTracker::hatchInside; } } void CDrawView::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_DrawCurrent=30; OnLButtonDown(nFlags,point); if(m_pSelection!=NULL) { m_pSelection->DoVerb(GetKeyState(VK_CONTROL)<0?OLEIVERB_OPEN:OLEIVERB_PRIMARY,this); } CView::OnLButtonDblClk(nFlags, point); } void CDrawView::OnDataSeacher() { m_DrawCurrent=31; //标识进行图形连接的查询操作 PushNumb=0; }