⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drawview.cpp

📁 陈建春<用VC++开发GIS系统>源码.适合于GIS学习者,以及学习图形图象编程的朋友.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 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 "TextWriteDlg.h"
#include "mainfrm.h"
#include "winresrc.h"
#include <afxwin.h>
#include "datalinkdlg.h"
#include <windowsx.h>
#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<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;
	m_pLinkSet=&pDoc->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;
}

⌨️ 快捷键说明

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