(工具:VS2010)
• 掌握VC++.net 坐标系和各项设置方法
• 掌握GDI绘图方法
• 理解交互式图形程序设计
下列数据为一变形监测点的24期位移监测结果(分别为X,Y,H),编制程序绘制出该点的变形曲线图,每个方向一个位移序列图。要求程序具有通用性,坐标刻度及格网绘制应根据读入数据本身自动标绘。
3.3.1文件:<Data.h>
/***************************************************************************
* 文件名: *
* *
* 描述:用来储存数据 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月1日 创建 张 *
* *
* 外部过程: *
* *
/**************************************************************************/
#pragma once
class CData
{
public:
int iID;//时间点 1-24
int iSum;//仅记录多少点
double dX;
double dY;
double dH;
CData(void);
~CData(void);
};
3.3.2文件:<Data.cpp>
#include "StdAfx.h"
#include "Data.h"
CData::CData(void)
{
}
CData::~CData(void)
{
}
3.3.3文件:<CSupport.h>
/***************************************************************************
* 文件名: *
* *
* 描述:封装主要函数的类 ,并用了类CData *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月1日 创建 张 *
* *
* 外部过程: *
* *
/**************************************************************************/
#pragma once
#include "math.h"
#include "Data.h"
//#include "RS_110_zhang_SY6View.h"
#include <locale.h>
class CSupport
{
public:
CSupport(void);
~CSupport(void);
CData * read();
void Draw(CData *a,CDC *pDC,CRect rect,int B);
private:
CString * SplitString(CString str, char split, int& iSubStrs);
CData *a;
};
3.3.4文件:<CSupport.cpp>
#include "StdAfx.h"
#include "Support.h"
CSupport::CSupport(void)
{
}
CSupport::~CSupport(void)
{
delete [] a;//删除 动态数组
}
/***************************************************************************
* 名字:CString * CSupport::SplitString(CString str, char split, int& iSubStrs)*
* *
* 描述:字符串分割函数2 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年4月30日 引用该函数 张 *
* 参数: 1.CString str *
* 2.char split *
* 3.int& iSubStrs *
* 返回值:返回指针 指针带有动态数组的内容 *
* *
* 注: *
/**************************************************************************/
CString * CSupport::SplitString(CString str, char split, int& iSubStrs)
{
int iPos = 0; //分割符位置
int iNums = 0; //分割符的总数
CString strTemp = str;
CString strRight;
//先计算子字符串的数量
while (iPos != -1)
{
iPos = strTemp.Find(split);
if (iPos == -1)
{
break;
}
strRight = strTemp.Mid(iPos + 1, str.GetLength());
strTemp = strRight;
iNums++;
}
if (iNums == 0) //没有找到分割符
{
//子字符串数就是字符串本身
iSubStrs = 1;
return NULL;
}
//子字符串数组
iSubStrs = iNums + 1; //子串的数量 = 分割符数量 + 1
CString* pStrSplit;
pStrSplit = new CString[iSubStrs];
strTemp = str;
CString strLeft;
for (int i = 0; i < iNums; i++)
{
iPos = strTemp.Find(split);
//左子串
strLeft = strTemp.Left(iPos);
//右子串
strRight = strTemp.Mid(iPos + 1, strTemp.GetLength());
strTemp = strRight;
pStrSplit[i] = strLeft;
}
pStrSplit[iNums] = strTemp;
return pStrSplit;
}
/***************************************************************************
* 名字:CData * CSupport::read() *
* *
* 描述:读取函数 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年4月1日 引用该函数 张 *
* 参数: 无 *
* 返回值:返回指针 指针带有动态数组的内容 *
* *
* 注: *
/**************************************************************************/
CData * CSupport::read()
{
CFileDialog dlgFile(TRUE,_T("txt"),NULL,
OFN_ALLOWMULTISELECT|OFN_EXPLORER,
//_T("(文本文件)|*.txt"));
_T(""));
if(dlgFile.DoModal()==IDCANCEL) return NULL;
CString strName=dlgFile.GetPathName();//获取打开文件文件名(路径)
setlocale(LC_ALL,"");
CStdioFile sf;
if(! sf.Open(strName,CFile::modeRead)) return NULL;
CString strLine;
CString strContent;//接受内容字符串
strContent.Empty();
BOOL bEOF =sf.ReadString (strLine);
if(!bEOF)
{
AfxMessageBox(_T("数据有误,请检查数据文件!"));
return NULL;
}
int iPointCount;
iPointCount=_ttoi(strLine);//读取点数
a=new CData [iPointCount];//创建动态数组
a[0].iSum=iPointCount;
int i=0 ;
int n=0;//为下文读取做铺垫
while (bEOF)
{
//strContent+=strLine;
bEOF=sf.ReadString(strLine);
CString *pstrData =SplitString(strLine,',',n);
if(pstrData==NULL) continue;
a[i].iID = ++n;
a[i].dX =_tstof(pstrData[0]);
a[i].dY =_tstof(pstrData[1]);
a[i].dH =_tstof(pstrData[2]);
i++;
delete [] pstrData;
pstrData=NULL;
}
sf.Close();
AfxMessageBox(_T("成功读取数据!"));
return a;
}
/***************************************************************************
* 名字:void CSupport::Draw(CData *a,CDC *pDC,CRect rect,int B) *
* *
* 描述:画图函数 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年4月1日 引用该函数 张 *
* 参数: 1.CData *a //承载着数据 *
* 2.CDC *pDC //画图用的指针 *
* 3.CRect rect //用来获取窗口大小元素 *
* 4.int B //用B 的数值大小0 1 2来表示X Y Z *
* 返回值:无 *
* *
* 注: *
/**************************************************************************/
void CSupport::Draw(CData *a,CDC *pDC,CRect rect,int B)
{
double *Data=new double [a[0].iSum];
for(int i=0;i<a[0].iSum;i++)
{
if (B==0) Data[i]=a[i].dX;
if (B==1) Data[i]=a[i].dY;
if (B==2) Data[i]=a[i].dH;
}
//绘制坐标轴
CPen pen(PS_SOLID,1,RGB(0,0,0));
pDC->Rectangle(rect);
double X0=rect.left+100;
double Y0=rect.bottom-100;
double X1=rect.right-50;
double Y1=rect.top+50;
//绘制X轴
pDC->MoveTo(X0,Y0);
pDC->LineTo(X1,Y0);
pDC->MoveTo(X1,Y0);
pDC->LineTo(X1-10,Y0+10);
pDC->MoveTo(X1,Y0);
pDC->LineTo(X1-10,Y0-10);
CString X;
X="X";
pDC->TextOut(X1,Y0+20,X,1);
//绘制Y轴
pDC->MoveTo(X0,Y0);
pDC->LineTo(X0,Y1);
pDC->MoveTo(X0,Y1);
pDC->LineTo(X0-10,Y1+10);
pDC->MoveTo(X0,Y1);
pDC->LineTo(X0+10,Y1+10);
CString Y;
X="Y";
pDC->TextOut(X0-20,Y1,X,1);
//绘制X轴平行线
double ddy=(fabs(Y1-Y0)-100)/10;
double temp;
temp=ddy;
for(int t=0;t<12;t++)
{
pDC->MoveTo(X0,Y0-temp);
pDC->LineTo(X1-100+(fabs(X1-X0)-100)/a[0].iSum,Y0-temp);
temp+=ddy;
}
//绘制Y轴平行线
double ddx=(fabs(X1-X0)-100)/a[0].iSum;
double _temp;
_temp=ddx;
for(int t=0;t<a[0].iSum+1;t++)
{
//pDC->MoveTo(X0+_temp,Y0);
//pDC->LineTo(X0+_temp,Y1+100-ddy*2);
pDC->MoveTo(X0+_temp,Y0);
pDC->LineTo(X0+_temp,Y0-10);
_temp+=ddx;
}
//返回最大值最小值
double max=Data[0];
double min=Data[0];
for (int i = 0; i <a[0].iSum; i++)
{
if(Data[i]>max)
{
max=Data[i];
}
if(Data[i]<min)
{
min=Data[i];
}
}
//加刻度
double ddd=(max-min)*0.1;
for(int t=0;t<13;t++)
{
CString str;
str.Format(_T("%.4f"),(min+ddd*(t-1)));
int n;
if(B==0) n=7;
if(B==1) n=8;
if(B==2) n=6;
pDC->TextOut(X0-88,Y0-ddy*t-0.2*ddy,str,n);
}
for(int t=0;t<a[0].iSum+2;t++)
{
CString str;
str.Format(_T("%d"),t);
if(t<=9)
{
pDC->TextOut(X0+ddx*t,Y0+20,str,1);
}
else
{
pDC->TextOut(X0+ddx*t,Y0+20,str,2);
}
}
//加文字
CString name;
CFont newFont;
CFont *oldFont;
newFont.CreateFont( 22, // 字体的高度
13, // 字体的宽度
0, // nEscapement
0, // nOrientation
FW_NORMAL, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
_T("楷体"));
oldFont=pDC->SelectObject(&newFont);//选择新字体
pDC->SetTextColor(RGB(0,255,0));//设置字体颜色
/*
pDC->TextOut(10, 10, pDc->text); //输出
pDC->SelectObject(oldFont);//选择回老字体
newFont.DeleteObject();//删除新字体*/
if(B==0) name="沿X方向图 ----张";
if(B==1) name="沿Y方向图 ----张";
if(B==2) name="沿H方向图 ----张";
pDC->TextOut((X0+X1)/2-50,Y1-20,name,23);
//绘制图像
//CPen pen(PS_SOLID,2,RGB(0,1,0));
pen.Detach();
if(B==0) pen.CreatePen(0,2,RGB(200,0,0));
if(B==1) pen.CreatePen(0,2,RGB(100,0,200));
if(B==2) pen.CreatePen(0,2,RGB(100,200,50));
pDC->SelectObject(&pen);
for(int i=0;i<a[0].iSum-1;i++)
{
pDC->MoveTo(X0+ddx*(i+1),Y0-ddy-(Data[i]-min)*10*ddy/(max-min));
pDC->LineTo(X0+ddx*(i+2),Y0-ddy-(Data[i+1]-min)*10*ddy/(max-min));
}
pen.DeleteObject();
delete [] Data;
}
3.3.5文件: <RS_110_zhang_SY6View.cpp > (只摘取部分)
/***************************************************************************
* 文件名: *
* *
* 描述:单文档 *
* *
* 历史:**日期** **理由** **签名** *
* 2019年5月1日 创建 张 *
* *
* 外部过程: *
* *
/**************************************************************************/
//全局
CSupport k;
CData *p;
void CRS_110_zhang_SY6View::OnFileOpen()
{
// TODO: 在此添加命令处理程序代码
p=k.read();//读取
}
void CRS_110_zhang_SY6View::On32771X()
{
// TODO: 在此添加命令处理程序代码
RedrawWindow(); //重绘窗口先
CRect rect;//声明客户区矩形
GetClientRect(rect);//获得客户区坐标
k.Draw(p,GetDC(), rect,0);
}
void CRS_110_zhang_SY6View::On32772Y()
{
// TODO: 在此添加命令处理程序代码
RedrawWindow(); //重绘窗口先
CRect rect;//声明客户区矩形
GetClientRect(rect);//获得客户区坐标
k.Draw(p,GetDC(), rect,1);
}
void CRS_110_zhang_SY6View::On32773H()
{
// TODO: 在此添加命令处理程序代码
RedrawWindow(); //重绘窗口先
CRect rect;//声明客户区矩形
GetClientRect(rect);//获得客户区坐标
k.Draw(p,GetDC(), rect,2);
}
创建多个类,层次分明。
使用指针动态开辟数组,较为方便
使用文件操作
使用单文档