drawview.cpp

来自「VC做的矢量画图程序!」· C++ 代码 · 共 2,000 行 · 第 1/5 页

CPP
2,000
字号
// DrawView.cpp : implementation of the CDrawView class
//

#include "stdafx.h"
#include "Draw.h"
#include <float.h>
#include <math.h>
#include "DrawDoc.h"
#include "CntrItem.h"
#include "DrawView.h"
#include "TextWDlg.h"
#include "mainfrm.h"
#include "browseDlg.h"
//#include "winresrc.h"
#include <afxwin.h>
#include "tag.h"
#include <windowsx.h>
#include "Tree.h"
#include "graphpa.h"
#include "bmapdlg.h"
#include "mmsystem.h"
#include "linedlg.h"
#include "LengthDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif 
extern CBrowseDlg * pBrowseDlg;
extern CTree * pTree;
extern CPline* m_pPline;
extern CArc* m_pArc;
extern CGraphPara *p_GraphPara;	//初试化一个公用的关于图形参数的实例
extern float xMinScreen,yMinScreen,xMaxScreen,yMaxScreen;
static MCI_GENERIC_PARMS MciGenParm;
WORD wDeviceID;
/////////////////////////////////////////////////////////////////////////////
// CDrawView
CStdioFile dxfFile;
int	nCharHeight,nCharWidth;
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_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_ZOOMOUT, OnGraphZoomOut)//图形放大
	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_COMMAND(ID_EDIT_MOVE, OnEditMove)
	ON_WM_HSCROLL()								//横向滚动条的消息映射
	ON_WM_VSCROLL()								//纵向滚动条的消息映射
	ON_WM_KEYDOWN()								//按下键盘的消息映射
	ON_COMMAND(ID_BITMAP_CUT, OnBitmapCut)		//图象剪裁
	ON_COMMAND(ID_BITMAP_PASTE, OnBitmapPaste)	//图象粘贴
	ON_EN_CHANGE(IDC_EDIT1, OnChangeDlgEdit)	//改变对话条的编辑框的消息映射
	ON_LBN_SELCHANGE(IDC_COMBO1,OnChangeDlgCom)	//改变对话条的列表框的消息映射
	ON_WM_LBUTTONDBLCLK()						//双击鼠标左键的消息映射
	ON_COMMAND(ID_GRAPHPARA_SET, OnGraphParaSET)//图形参数设置	
	ON_COMMAND(ID_LAYER_SET, OnLayerManage)		//图层管理
	ON_COMMAND(ID_BLOCK_ADD, OnBlockAdd)		//选中的图形元素形成一个图形块
	ON_COMMAND(ID_DRAW_TAG, OnDrawTag)			//开始绘制图例
	ON_COMMAND(ID_BLOCK_NEW, OnBlockNew)		//新建一个图形块
	ON_COMMAND(ID_BLOCK_OK, OnEditBlockOk)		//保存编辑的图形块退出图形块编辑状态
	ON_COMMAND(ID_BLOCK_CANCEL, OnEditBlockCancel)	//放弃编辑的图形块退出图形块编辑状态
	ON_COMMAND(ID_BLOCK_INSERT, OnBlockInsert)	//绘制图形块的插入点
	ON_COMMAND(ID_BLOCK_GL, OnBlockDialog)		//图形块管理的消息映射
	ON_COMMAND(ID_BASEMAP_MANAGE, OnBasemapManage)
	ON_WM_SETCURSOR()
	ON_COMMAND(ID_GRAPH_MODIFY, OnGreaphModify)
	ON_COMMAND(ID_GRAPH_DATA, OnGraphData)
	ON_COMMAND(ID_DXF_READ, OnDxfRead)
	ON_COMMAND(ID_DXF_WRITE, OnDxfWrite)
	ON_COMMAND(ID_SELECT_WINDOW_IN, OnSelectWindowIn)
	ON_COMMAND(ID_SELECT_WINDOW_CROSS, OnSelectWindowCross)
	ON_COMMAND(ID_SELECT_WINDOW_ALL, OnSelectWindowAll)
	ON_COMMAND(ID_SELECT_CIRCLE_IN, OnSelectCircleIn)
	ON_COMMAND(ID_SELECT_CIRCLE_CROSS, OnSelectCircleCross)
	ON_COMMAND(ID_SELECT_CIRCLE_ALL, OnSelectCircleAll)
	ON_COMMAND(ID_SELECT_PLINE_IN, OnSelectPlineIn)
	ON_COMMAND(ID_SELECT_PLINE_CROSS, OnSelectPlineCross)
	ON_COMMAND(ID_SELECT_PLINE_ALL, OnSelectPlineAll)
	ON_COMMAND(ID_GRAPH_ZOOMIN, OnGraphZoomIn)
	ON_WM_LBUTTONUP()
	ON_WM_CREATE()
	ON_WM_ERASEBKGND()
	ON_COMMAND(ID_EDIT_PLENGTH, OnEditPlength)
	//}}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=51508;	
	m_yStart=92800;
	blc=1;
	m_bColor=0;		//当前底色的序号	
	m_pColor=1;		//设置笔色
	m_brColor=1;	//画刷色	
	m_beColor=0;
	m_LineWide=1;	//设置线宽
	m_LineType=0;	//设置线型
	m_Layer=0;		//设置当前层
	PointXyz=new PointStruct[3000];//存储连续直线点的数组
	PointPL=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();//实际初始化一个标注类	
    nScrollMin=50;  //滚动条的最小滚动范围是在屏幕上滚动50个像素
    nXLine=1;       //横向滚动一个滚动范围
    nYLine=1;     //纵向滚动一个滚动范围(按中滚动条的按键时的滚动
	m_MapMode=1;
}

//将实际坐标(x,y)转成逻辑坐标(*X,*Y)
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;
}

//将逻辑坐标(x,y)转成实际坐标(*X,*Y)
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);
}

//将实际距离转成逻辑距离返回
//参数:l-距离(逻辑单位)
float CDrawView::VLtoDL(int l)
{
	return blc*l;
}

//将逻辑距离转成实际距离返回
//参数:l-距离(实际单位)
int CDrawView::DLtoVL(float l)
{
	return (int)(l/blc);
}

//视图类的析构函数
CDrawView::~CDrawView()	
{
//	delete m_Screen;
	delete PointXyz;
	delete m_Text1;
	delete PointPL;
}

//预定制窗口函数
BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs)
{	m_hcurHand = (HCURSOR)::LoadImage(cs.hInstance,
		MAKEINTRESOURCE(IDC_CURSOR_HAND), IMAGE_CURSOR,
		32, 32, LR_DEFAULTCOLOR);

	m_hcurZoomIn = (HCURSOR)::LoadImage(cs.hInstance,
		MAKEINTRESOURCE(IDC_CURSOR_ZOOMIN), IMAGE_CURSOR,
		32, 32, LR_DEFAULTCOLOR);

	m_hcurZoomOut = (HCURSOR)::LoadImage(cs.hInstance,
		MAKEINTRESOURCE(IDC_CURSOR_ZOOMOUT), IMAGE_CURSOR,
		32, 32, LR_DEFAULTCOLOR);

	//获得光标资源的另一种方法
	m_hcurArrow = AfxGetApp()->LoadCursor(IDC_CURSOR_ARROW);
	m_hcurCross = AfxGetApp()->LoadCursor(IDC_CURSOR_CROSS);

    return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CDrawView drawing

//视图类中的绘制函数,通过窗口激发完成视图的自动绘制
void CDrawView::OnDraw(CDC* pDC)
{
	CRect rr;
	TEXTMETRIC tm;
	CDrawDoc* pDoc = GetDocument();
	p_GraphPara=&pDoc->m_GraphPara;	//将公用的GraphPara类的指针指向当前文档的GraphPara对象
	p_Doc=pDoc;
	p_View=this;
	ASSERT_VALID(pDoc);
	xMinScreen=m_xStart;
	yMinScreen=m_yStart;
	xMaxScreen=xMinScreen+blc*m_wScreen;
	yMaxScreen=yMinScreen+blc*m_hScreen;
	pDC->GetTextMetrics(&tm);
	nCharHeight=tm.tmHeight+tm.tmExternalLeading;//-nCharHeightVal;
	nCharWidth=tm.tmAveCharWidth;
	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
	{*/
		b_Draw=TRUE;
	    for(int i=0;i<pDoc->m_BasemapNumb;i++)
 		  pDoc->m_Basemap[i].Draw(this,pDC);
		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<an1+pi||an2<an1&&an2+pi<an1) //如果弧是逆时针方向画的
	{
		*Angle1=an1;*Angle2=an3;	//得到起终弧度
	}
	else    //如果弧是顺时针画的
	{
		*Angle1=an3;*Angle2=an1;	//得到起终弧度
	}
	return 1;  //操作成功
}

//视图类的初始化函数
void CDrawView::OnInitialUpdate()
{
	CView::OnInitialUpdate();
	CDrawDoc* pDoc=GetDocument();
	m_pSelection = NULL;    // initialize selection
	p_View=this;
}

/////////////////////////////////////////////////////////////////////////////
// CDrawView printing

BOOL CDrawView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?