vc可视化实验4.docx
《vc可视化实验4.docx》由会员分享,可在线阅读,更多相关《vc可视化实验4.docx(18页珍藏版)》请在冰点文库上搜索。
![vc可视化实验4.docx](https://file1.bingdoc.com/fileroot1/2023-5/6/c928e54a-20e2-42a9-9746-1e6e9622d680/c928e54a-20e2-42a9-9746-1e6e9622d6801.gif)
vc可视化实验4
实验四:
基于文档/视图结构的应用
学号:
2011329700214姓名:
周咪咪班级:
11数媒
(2)班
一、实验目的
1.掌握MFC中文档/视图框架体系的编程方法
二、实验内容
1.用户在视图窗口绘制温度曲线
2.重绘时曲线能够保持
3.应用程序图标为用户自定义位图
三、实验步骤及源代码
1.创建MFC应用程序框架
打开VS2005,使用MFCAppWizard[exe]向导创建MFC应用程序Sy4框架,选择单文档应用程序,其它默认。
2.在视图类的头文件sy4View.h中声明有关的成员变量。
protected:
//在视图类头文件sy4View.h中声明有关的成员变量
CPointm_pOld;//绘图标识
HCURSORm_Hcursor;//拖拽状态时鼠标的样式
boolm_bDraw;//记录鼠标位置
3.在视图类sy4View的构造函数中对拖拽标记和鼠标样式进行初始化。
CSy4View:
:
CSy4View()//在视图类构造函数中对成员变量进行初始化
{
//TODO:
addconstructioncodehere
m_bDraw=FALSE;//初始化为false
m_Hcursor=AfxGetApp()->LoadStandardCursor(IDC_CROSS);//载入“十字”光标}
4.使用类向导为视图类添加按下鼠标左键,移动鼠标,释放鼠标左键等消息处理函数。
(1)为视图类sy4View添加消息WM_LBUTTONDOWN,定义消息响应函数,实现按下鼠标左键的相关绘图操作。
再为消息函数中添加代码。
voidCSy4View:
:
OnLButtonDown(UINTnFlags,CPointpoint)//按下鼠标左键
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
SetCursor(m_Hcursor);//使用新光标
m_bDraw=TRUE;//进入绘图状态
m_pOld=point;
SetCapture();//捕捉鼠标
CRectrect;
GetClientRect(&rect);//获取客户窗口矩形区域
ClientToScreen(&rect);//转换为屏幕坐标
ClipCursor(rect);//限定鼠标不能移出客户窗口
CView:
:
OnLButtonDown(nFlags,point);
}
(2)为视图T类添加消息WM_MOUSEMOVE和LBUTTONUP,并定义消息响应函数,实现移动和释放鼠标左键的相关绘图操作。
为消息函数添加代码。
voidCSy4View:
:
OnMouseMove(UINTnFlags,CPointpoint)//移动鼠标
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
if(m_bDraw)
{
CClientDCdc(this);//获取客户窗口DC
dc.MoveTo(m_pOld);//绘图
dc.LineTo(point);
m_pOld=point;
}
CView:
:
OnMouseMove(nFlags,point);
}
voidCSy4View:
:
OnLButtonUp(UINTnFlags,CPointpoint)//释放鼠标左键
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
m_bDraw=FALSE;//取消绘图状态
ReleaseCapture();//释放鼠标捕捉
ClipCursor(NULL);//取消鼠标区域的限制
CView:
:
OnLButtonUp(nFlags,point);
}
4.运行结果:
当调整窗口大小或者被覆盖时,绘制的图形将消失,无法实现重绘时曲线保持
其原因:
此时调用的是视图类的刷新函数OnDraw(),而在该函数中并没有实现图形绘制功能,为了解决此缺陷必须在OnDraw()函数中重新绘制以前用鼠标所绘制的线段,在利用鼠标绘制时必须将线段的坐标数据保存起来。
二功能的修补
为线段定义一个CLine的类,线段的起点和终点坐标作为类的成员变量,并定义相应的成员函数。
在文档类中为线段选择一个合适的动态数据结构,用于保存大量的且数目不确定的直线图形对象。
在CLine.h中定义:
private:
CPointm_pt1;//两个私有数据成员分别表示一条线段的起点和终点。
CPointm_pt2;
public:
CLine(CPointpt1,CPointpt2);//自定义构造函数
voidDrawLine(CDC*pDC);//声明绘制线段的成员函数。
在CLine.cpp中:
CLine:
:
CLine(CPointpt1,CPointpt2)//使用自定义构造函数初始化起点和终点
{
m_pt1=pt1;
m_pt2=pt2;
}
voidCLine:
:
DrawLine(CDC*pDC)//绘制线段
{
pDC->MoveTo(m_pt1);
pDC->LineTo(m_pt2);
}
2文档类主要是用来保存数据的,那么在文档类CMyDrawDoc文档类中定义
#include"Line.h"//包含CLine类头文件
#include//使用模板来需要包含此头文件
protected:
//createfromserializationonly
CMyDrawDoc();
DECLARE_DYNCREATE(CMyDrawDoc)
CTypedPtrArraym_LineArray;//存放线段对象指针的动态数组
//Attributes
public:
CLine*GetLine(intnIndex);//获取指定序号线段对象的指针
voidAddLine(CPointpt1,CPointpt2);//向动态数组中添加新的线段对象的指针
intGetNumLines();//获取线段的向量
成员函数的实现:
voidCMyDrawDoc:
:
AddLine(CPointpt1,CPointpt2)
{
CLine*pLine=newCLine(pt1,pt2);
m_LineArray.Add(pLine);
}
CLine*CMyDrawDoc:
:
GetLine(intnIndex)
{
if(nIndex<0||nIndex>m_LineArray.GetUpperBound())
returnNULL;
returnm_LineArray.GetAt(nIndex);
}
intCMyDrawDoc:
:
GetNumLines()
{
returnm_LineArray.GetSize();
}
3.当移动鼠标时,除了绘制,还要保存当前线段的起点和终点坐标,代码如下:
voidCMyDrawView:
:
OnMouseMove(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CView:
:
OnMouseMove(nFlags,point);
if(m_bDragging)
{
CMyDrawDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
pDoc->AddLine(m_ptOrigin,point);//加入线段到指针数组
CClientDCdc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOrigin=point;
}
}
4.在改变程序窗口大小或重新打开窗口时显示这些窗口中的原有图形,必须在OnDraw()函数中重新绘制前面利用鼠标所绘制的线段,这些线段的坐标为CLine类的成员变量,所有的CLine对象的指针已保存在动态数组m_LineArray中。
voidCMyDrawView:
:
OnDraw(CDC*pDC)
{
CMyDrawDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
intnIndex=pDoc->GetNumLines();
TRACE("nIndex=%d\n",nIndex);
while(nIndex--)
{
TRACE("nIndex=%d\n",nIndex);
pDoc->GetLine(nIndex)->DrawLine(pDC);
}
}
至此程序完整了。
在第一阶段的时候,由于视图的OnDraw()函数里面没有实现绘图的函数,在改变窗口大小后,程序刷新重画窗口,也就什么东东都没有了。
修补程序后,OnDraw()函数取得线段的数量nIndex,然后用一个while循环,GetLine(nIndex)取得指定序号线段对象的指针,它是一个CLine类型的对象。
然后调用CLine类的DrawLine()绘制已保存的所有线段。
5、由于此实验太难,所以先了解了一些基础的创建过程,再通过网上查找代码和询问同学略有一点了解。
(1)创建MFC应用程序框架
打开VS2005,使用MFCAppWizard[exe]向导创建MFC应用程序Sy4框架,选择单文档应用程序,其它默认。
(2)添加菜单项
在菜单栏添加“温度湿度测试”菜单。
(3)创建工具栏
为应用程序增加的工具栏,并使工具栏上的各按钮与菜单栏中的菜单项相对应,如下截图中所示:
(4)添加代码
添加成员变量和成员函数,选择项目工作区中的类视图,右击CSy5View,光标移至添加,分别添加成员变量及成员函数,
m_col,k,voiddrawaxis(CDC*pDC)
添加成员函数代码
建立消息映射
分别为菜单项【温度曲线绘制】、工具栏添加COMMAND及UPDATE_COMMAND_UI消息处理函数
向以下voidOnWendu(),voidOnTimer(UINT_PTRnIDEvent),voidOnColb(),voidOnColr(),voidOnExit()函数中添加代码。
//Graph2View.cpp:
implementationoftheCGraph2Viewclass
//
#include"stdafx.h"
#include"Graph2.h"
#include"Graph2Doc.h"
#include"Graph2View.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CGraph2View
IMPLEMENT_DYNCREATE(CGraph2View,CView)
BEGIN_MESSAGE_MAP(CGraph2View,CView)
//{{AFX_MSG_MAP(CGraph2View)
ON_COMMAND(ID_WENDU,OnWendu)
ON_WM_TIMER()
//}}AFX_MSG_MAP
//Standardprintingcommands
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()
/////////////////////////////////////////////////////////////////////////////
//CGraph2Viewconstruction/destruction
CGraph2View:
:
CGraph2View()
{
//TODO:
addconstructioncodehere
k=0;
}
CGraph2View:
:
~CGraph2View()
{
}
BOOLCGraph2View:
:
PreCreateWindow(CREATESTRUCT&cs)
{
//TODO:
ModifytheWindowclassorstylesherebymodifying
//theCREATESTRUCTcs
returnCView:
:
PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
//CGraph2Viewdrawing
voidCGraph2View:
:
OnDraw(CDC*pDC)
{
CGraph2Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
//画坐标
pDC->MoveTo(200,300);
pDC->LineTo(460,300);
pDC->MoveTo(200,300);
pDC->LineTo(200,40);
CStringstr1="时间/Hours";
CStringstr2="湿度(%)/温度(℃)";
pDC->TextOut(463,300,str1);
pDC->TextOut(153,30,str2);
//画箭头
pDC->MoveTo(445,295);
pDC->LineTo(445,305);
pDC->LineTo(460,300);
pDC->LineTo(445,295);
pDC->MoveTo(195,55);
pDC->LineTo(205,55);
pDC->LineTo(200,45);
pDC->LineTo(195,55);
//坐标标识
CStringstr;
for(inti=0;i<13;i++){
str.Format("%d",i);
pDC->TextOut(196+i*20,308,str);
}
for(inti=0;i<13;i++){
str.Format("%d",40-i*3);
pDC->TextOut(175,50+i*20,str);
}
//画网格
CPen*pPenBlue=newCPen;//创建画笔对象
pPenBlue->CreatePen(PS_DOT,1,RGB(0,0,255));//蓝色画笔
CPen*pPenGreen=newCPen;//创建画笔对象
pPenGreen->CreatePen(PS_SOLID,1,RGB(0,255,0));//绿色画笔
CPen*pPenRed=newCPen;//创建画笔对象
pPenRed->CreatePen(PS_SOLID,1,RGB(255,0,0));//红色画笔
CGdiObject*pOldPen=pDC->SelectObject(pPenBlue);
for(inti=1;i<=240;i+=20)
{
pDC->MoveTo(200,60+i);
pDC->LineTo(440,60+i);
pDC->MoveTo(i+220,60);
pDC->LineTo(i+220,300);
}
CStringstr3="湿度(%)";
CStringstr4="温度(℃)";
pDC->SelectObject(pPenRed);
pDC->MoveTo(480,40);
pDC->LineTo(540,40);
pDC->TextOut(545,40,str3);
pDC->SelectObject(pPenGreen);
pDC->MoveTo(480,70);
pDC->LineTo(540,70);
pDC->TextOut(545,70,str4);
pDC->SelectObject(pOldPen);
deletepPenBlue;
deletepPenRed;
deletepPenGreen;
}
/////////////////////////////////////////////////////////////////////////////
//CGraph2Viewprinting
BOOLCGraph2View:
:
OnPreparePrinting(CPrintInfo*pInfo)
{
//defaultpreparation
returnDoPreparePrinting(pInfo);
}
voidCGraph2View:
:
OnBeginPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{
//TODO:
addextrainitializationbeforeprinting
}
voidCGraph2View:
:
OnEndPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{
//TODO:
addcleanupafterprinting
}
/////////////////////////////////////////////////////////////////////////////
//CGraph2Viewdiagnostics
#ifdef_DEBUG
voidCGraph2View:
:
AssertValid()const
{
CView:
:
AssertValid();
}
voidCGraph2View:
:
Dump(CDumpContext&dc)const
{
CView:
:
Dump(dc);
}
CGraph2Doc*CGraph2View:
:
GetDocument()//non-debugversionisinline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGraph2Doc)));
return(CGraph2Doc*)m_pDocument;
}
#endif//_DEBUG
/////////////////////////////////////////////////////////////////////////////
//CGraph2Viewmessagehandlers
voidCGraph2View:
:
OnWendu()
{
//TODO:
Addyourcommandhandlercodehere
SetTimer(1,1000,NULL);
}
voidCGraph2View:
:
OnTimer(UINTnIDEvent)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
//画曲线
inta[13]={111,100,120,145,150,140,180,200,190,212,191,200,180};
intb[13]={210,234,209,218,180,200,191,151,125,111,139,161,170};
CClientDCdc(this);
CPen*pPenGreen=newCPen;//创建画笔对象
pPenGreen->CreatePen(PS_SOLID,1,RGB(0,255,0));//绿色画笔
CPen*pPenRed=newCPen;//创建画笔对象
pPenRed->CreatePen(PS_SOLID,1,RGB(255,0,0));//红色画笔
CGdiObject*pOldPen=dc.SelectObject(pPenRed);
//画温度曲线
dc.SelectObject(pPenRed);
intx,y,s,t;
x=200+k*20;
y=a[k];
s=x+20;
t=a[k+1];
dc.MoveTo(x,y);
dc.LineTo(s,t);
//画湿度曲线
dc.SelectObject(pPenGreen);
x=200+k*20;
y=b[k];
s=x+20;
t=b[k+1];
dc.MoveTo(x,y);
dc.LineTo(s,t);
k++;
if(k>=12)
{
//system("cls");
k=0;
}
dc.SelectObject(pOldPen);
deletepPenRed;
deletepPenGreen;
CView:
:
OnTimer(nIDEvent);
}
6、用户自定义位图
选择Icon中的IDR_MAINFRAME,就可以看到图标编辑器,与工具条编辑器十分相似,在这里修改图标的尺寸和图案。
单击NewDeviceImage按钮,在弹出的NewIconIamge对话框中选择图标的尺寸。
对光标资源进行修改,编译程序后可看到执行文件的图标改变。
根据书上所说,但是无法实现图标的改变。
四、运行结果及分析
改变窗口大小:
分析:
(1)程序运行后开始执行voidOnDraw(pDC)函数绘制坐标轴,设置坐标轴的各项属性,单击“湿度温度测试”菜单项或者工具栏上的折线图标开始绘制曲线,
(2)通过消息响应机制完成上述功能。
(3)要实现单击对话框中某个控件产生某种效果必须为该控件建立消息映射,添加相应的消息响应函数,并编写实现代码;
(4)实