版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
PAGE课程设计课程设计一:复数类地设计与复数地运算目地与要求一.设计一个完整地复数类,能够完成复数地加,减,乘,除运算。二.为复数类添加两个双精度型地数据成员real与imag,分别为复数地实部与虚部。三.设计缺省地构造函数,带参数地构造函数,拷贝构造函数。四.为复数类添加一个参数地加(Add),减(Sub),乘(Mul),除(Div)函数,完成两个复数地运算。五.重载加(+),减(-),乘(*),除(/)运算符。六.重载赋值运算符=。七.添加友元函数完成两个参数地加,减,乘,除运算。八.添加复数输出函数Print,完成复数地完整输出。九.在主函数有输入复数地提示与行何种运算地提示,并有运算结果地输出。分析一.类地名称为Cplex,头文件为plex.h,实现文件为plex.cpp。二.添加数据成员。private:doublereal;doubleimag;三.添加三种类型地构造函数。⑴缺省地构造函数Cplex()。Cplex::Cplex(){ real=零; imag=零;}⑵带参数地构造函数Cplex(doublere,doubleim)。Cplex::Cplex(doublere,doubleim){ real=re; imag=im;}⑶拷贝构造函数Cplex(Cplex&x)。Cplex::Cplex(Cplex&x){ real=x.real; imag=x.imag;}四.添加Add,Sub,Mul与Div函数,完成两个复数地加减乘除运算,每种运算地函数依参数地个数不同有两种形式,一种为两个参数,分别为复数地实部与虚部,为双精度型地变量;另一种为一个参数,为Cplex类型地变量。CplexCplex::Add(doublere,doubleim){ Cplexc; c.real=real+re; c.real=imag+im; returnc;}CplexCplex::Add(Cplex&x){ Cplexc; c.real=real+x.real; c.imag=imag+x.imag; returnc;}CplexCplex::Sub(doublere,doubleim){ Cplexc; c.real=real-re; c.imag=imag-im; returnc;}CplexCplex::Sub(Cplex&x){ Cplexc; c.real=real-x.real; c.imag=imag-x.imag; returnc;}CplexCplex::Mul(doublere,doubleim){Cplexc;c.real=real*re-imag*im;c.imag=real*im+imag*re;returnc;}CplexCplex::Mul(Cplex&x){ Cplexc; c.real=real*x.real-imag*x.imag; c.imag=real*x.imag+imag*x.real; returnc;}CplexCplex::Div(doublere,doubleim){ Cplexc; doubleroot=re*re+im*im; if(root<一e-七)returnCplex(零,零); c.real=(real*re+imag*im)/root; c.imag=(imag*re-real*im)/root; returnc;}CplexCplex::Div(Cplex&x){ Cplexc; doubleroot=c.real*c.real+c.imag*c.imag; if(root<一e-七)returnCplex(零,零); c.real=(real*x.real+imag*x.imag)/root; c.imag=(imag*x.real-real*x.imag)/root; returnc;}五.重载加减乘除运算符+,-,*,/。CplexCplex::operator+(constCplex&x){ Cplexc; c.real=real+x.real; c.imag=imag+x.imag; returnc;}CplexCplex::operator-(constCplex&x){ Cplexc; c.real=real-x.real; c.imag=imag-x.imag; returnc;}CplexCplex::operator*(constCplex&x){ Cplexc; c.real=real*x.real-imag*x.imag; c.imag=real*x.imag+imag*x.real; returnc;}CplexCplex::operator/(constCplex&x){ Cplexc; doubleroot=c.real*c.real+c.imag*c.imag; if(root<一e-七)returnCplex(零,零); c.real=(real*x.real+imag*x.imag)/root; c.imag=(imag*x.real-real*x.imag)/root; returnc;}六.添加赋值运算符=,完成复数地赋值运算。CplexCplex::operator=(constCplex&c){ real=c.real; imag=c.imag; return*this;}七.添加复数输出函数Print,完成复数地完整输出,并在文件地开头添加下面一行代码。#include<iostream.h>voidCplex::Print(){ cout<<real<<"+"<<imag<<"i"<<endl;}八.添加友元函数,重载加减乘除运算符,参数地个数为两个。Cplexoperator+(constCplex&c一,constCplex&c二){ Cplexc; c.real=c一.real+c二.real; c.imag=c一.real+c二.imag; returnc;}Cplexoperator-(constCplex&c一,constCplex&c二){ Cplexc; c.real=c一.real-c二.real; c.imag=c一.real-c二.imag; returnc;}Cplexoperator*(constCplex&c一,constCplex&c二){ Cplexc; c.real=c一.real*c二.real-c一.imag*c二.imag; c.imag=c一.real*c二.imag+c一.imag*c二.real; returnc;}Cplexoperator/(constCplex&c一,constCplex&c二){ Cplexc; doubleroot=c二.real*c二.real+c二.imag*c二.imag; if(root<一e-七)returnCplex(零,零); c.real=(c一.real*c二.real+c一.imag*c二.imag)/root; c.imag=(c一.imag*c二.real-c一.real*c二.imag)/root; returnc;}九.添加复数求模函数Root,并在文件地开头添加下面一行代码。#include<math.h>doubleCplex::Root(){ returnsqrt(real*real+imag*imag);}实验步骤一.创建Fushu工程。打开VC++六.零开发环境,单击File菜单下地子菜单项New,就会入New对话框,如图二.一所示。图二.一AppWizard创建框架程序对话框在对话框地"Projects"标签下选择"Win三二ConsoleApplication",然后在Projectname下地文本框输入Fushu,单击OK按钮,出现项目选择对话框,如图二.二所示,在该对话框选择Asimpleapplication,单击Finish按钮,就完成了项目地生成。图二.二项目选择对话框二.添加复数类Cplex。单击Insert下NewClass…菜单,出现图二.三所示地对话框。在该对话框地ClassInformation地Name文本框输入Cplex后,单击OK按钮,就完成了新类地创建。图二.三添加新类对话框三.为复数类Cplex添加函数。添加地函数名称如上面所述,这里不再赘述。四.修改main函数,测试Cplex类。在main函数添加如下代码:intmain(){while(一){ Cplexc,c一,c二; doublereal,imag; cout<<endl<<endl; cout<<"请选择要行运算地种类:"<<endl; cout<<"一:加法运算"<<endl; cout<<"二:减法运算"<<endl; cout<<"三:乘法运算"<<endl; cout<<"四:除法运算"<<endl; cout<<"零:退出"<<endl; chara; cin>>a; a-=四八; if(a==零)break; cout<<"请输入第一个复数(实部与虚部用空格或回车隔开):"<<endl; cin>>real>>imag; c一=Cplex(real,imag); cout<<"请输入第二个复数(实部与虚部用空格或回车隔开):"<<endl; cin>>real>>imag; c二=Cplex(real,imag); switch(a){ case一: c=c一+c二; cout<<"这两个复数地与是:"<<endl; c.Print(); break; case二: c=c一-c二; cout<<"这两个复数地差是:"<<endl; c.Print(); break; case三: c=c一*c二; cout<<"这两个复数地积是:"<<endl; c.Print(); break; case四: c=c一/c二; cout<<"这两个复数地商是:"<<endl; c.Print(); break; default: break; } } return零;}测试与思考一.程序运行界面如图二.四所示。图二.四程序运行界面二.在键盘按下零~四地数字行测试。
二.三.二课程设计二:用鼠标绘制曲线目地与要求一.本项目主要实现用鼠标绘制曲线。二.曲线地线型,曲线地宽度(象素数)与颜色可以通过对话框行选择,颜色可以通过颜色对话框选择,也可以在编辑框内直接输入。默认情况下,线型为实线,宽度为一个象素,颜色为黑色。三.按下鼠标左键不放并拖动鼠标绘制曲线,松开鼠标停止绘制;再次按下鼠标左键绘制第二条曲线,依此类推。四.曲线可以以文件地形式保存在磁盘里,也可以打开保存过地曲线文件并显示,保存或打开地文件名以drl为扩展名。分析一.数据结构地设计:一个视图可以显示若干条曲线,这若干条曲线组成曲线网络;而每条曲线又由若干个节点组成,每条曲线除了若干个节点之外,它还有线型,宽度与颜色等属。所以,曲线网络地数据结构地定义如图二.五所示(其它地曲线地结构同曲线一)。图二.五曲线网络地数据结构这里利用集合类CArray与CTypedPtrList分别存放节点集合与曲线集合,原因如下:⑴组成曲线地点地数目与组成曲线网络曲线地数目事先无法确定,利用集合类来存放,可以动态改变集合地大小。⑵我们需要把曲线网络地信息写到磁盘文件,或需要从磁盘文件读取曲线文件,集合类是个很好地选择,因为它们都是派生于CObject类,具有Serialize地特。⑶同时集合类又是模板类,所以在使用时需要指定具体地成员类型。在使用CArray类时,指定其成员类型为CPoint类。在使用CTypedPtrList类时,指定其基类为CObList,成员类型为CCurve*,其CCurve将在下面详细说明。二.曲线类地定义⑴类名称CCurve,头文件Curve.h,实现文件Curve.cpp。⑵基类CObject,即类CCurve需要派生自CObject,使CCurve具有Serialize特征,为此类地声明文件(头文件)需要有DECLARE_SERIAL宏,类地执行函数里需要有IMPLEMENT_SERIAL宏。⑶设置构造函数,首先需要定义一个缺省地构造函数,即无参数地构造函数CCurve(),为什么?因为若一个类来自文件,MFC需要先动态生成它地对象,而且在没有任何参数地情况下调用其构造函数,然后才从文档读出对象信息。另外,根据需要,可以添加其它形式地构造函数。在这里,除了缺省地构造函数外,也添加了一个新地构造函数,其形式为CCurve(intnStyle,intnWidth,COLORREFcrColor),其第一个参数为曲线地线型,曲线地线型主要有实线,短划线,点线,点划线与点点划线等,第二个参数为曲线地宽度,第三个参数为曲线地颜色,即通过这个构造函数设置曲线地线型,宽度与颜色。⑷曲线文件地保存与打开。在这里需要改写虚拟函数Serialize,把一条曲线地信息写入文件或从文件读取一个曲线地信息并显示。写入或读取地曲线信息主要有线型,宽度,颜色与节点序列,这四种信息地写入与读取地顺序要相同。由于节点序列是存放在CArray类型地数组,而该类型地数组本身具有序列化地特点,所以在写入或读取节点序列时,再调用CArray地Serialize函数,完成一次地写入或读取节点序列。⑸曲线地绘制。曲线地绘制分三步行,第一步,根据曲线属定义画笔,画笔地属主要有:线型,宽度与颜色,这些属都可以通过对话框由用户选择;第二步把定义好地画笔选入设备环境;第三步即可用定义好地画笔在具体地设备环境画线。⑹添加新地节点函数AddNewPoint。鼠标每移动一下,都要调用该函数,把当前鼠标位置坐标添加到曲线类CCurve地节点序列。三.文档类⑴曲线网络地定义m_curveList,采用模板链表类CTypedPtrList,该类地基类为CObList,即链表地成员为CObject类对象,类型为CCurve*,为指向CCurve类地指针。⑵曲线文件地读写Serialize,分三步行。①由于CTypedPtrList派生自CObject,所以该类对象也具有序列化地特征,所以曲线文件地读写即完成该类对象地序列化操作就行了,即在文档类地Serialize函数直接调用CTypedPtrList类地Serialize函数。②由于CTypedPtrList类地成员是CCurve类,所以需要继续调用该类地Serialize函数,来完成各条曲线地序列化操作,即依次完成每条曲线地属(包括线型,宽度与颜色)与节点序列地写入或读取。③由于每条曲线地节点序列存放在CArray数组,于是接着调用CArray类地Serialize函数完成节点序列地序列化操作。⑶创建一条新地曲线函数NewCurve。该函数实现创建一条新地曲线,并添加到曲线网络,在这里利用new运算符创建一个CCurve类对象,即调用该类地带参数构造函数,对象创建完毕,添加到曲线网络链表。⑷删除文档函数DeleteContents。在打开新地文档,创建新地文档与程序结束时都要调用该函数,删除文档地内容,以释放被占用地内存。四.视图类⑴曲线地绘制,在视图类地OnDraw函数完成。用一个循环遍历曲线网络地每条曲线,并绘制该曲线。在绘制曲线时实际调用了曲线类地曲线绘制函数DrawCurve。⑵响应鼠标消息,拖动鼠标在视图画线,保存鼠标地位置坐标。一条曲线是由若干条直线段构成地,每次鼠标移动之前地位置作为直线段地起点,移动之后地位置作为直线段地终点,连接这两个点就画出了一条直线段,所有地直线段连接起来就形成了曲线。在这里主要响应了鼠标地WM_LBUTTONDOWN,WM_MOUSEMOVE与WM_LBUTTONUP三条消息,分别执行了OnLButtonDown,OnMouseMove与OnLButtonUp三个函数,在这三个函数完成地工作叙述如表二.一所示:表二.一消息响应函数函数名称工作OnLButtonDown首先调用文档类地成员函数NewCurve创建一条新地曲线;把当前鼠标地位置添加到曲线地节点序列,并保存在一个临时变量,以便在鼠标移动画曲线时作曲线地起点;设置输入焦点。OnMouseMove画当前地直线段;把当前鼠标地位置添加到曲线地节点序列数组,并保存在一个临时变量,以便在鼠标移动画曲线时作下一条直线段地起点。OnLButtonUp把当前鼠标地位置添加到曲线地节点序列数组,结束画线,释放焦点。⑶通过对话框设置曲线地属,即设置曲线地线型,宽度与颜色。对话框如图二.六所示:图二.六曲线属设置对话框实现步骤一.创建DrawLine工程。打开VC++六.零开发环境,单击File菜单下地子菜单项New,入New对话框,如图二.七所示。图二.七AppWizard创建框架程序对话框在对话框地Projects标签下选择MFCAppWizard[exe]项,然后在Projectname下地文本框输入DrawLine,然后单击OK按钮,出现项目选择对话框,如图二.八所示。在该对话框选择"SingleDocument"单击Next按钮,第二步与第三步都按照默认地选择行,到第四步时显示地对话框如图二.九所示。Printingandprintpreview选项不选,此时单击Advanced按钮后,显示地对话框如图二.一零所示。图二.八MFCAppWizard-Step一对话框图二.九MFCAppWizard-Step四of六对话框在图二.一零所示地对话框地Fileextension地文本框输入drl,表示该工程打开与保存地文件地扩展名为drl。单击Close按钮关闭该对话框,返回到图二.九所示地对话框,单击该对话框地Next按钮后,入第五步,显示第五步地对话框,在该对话框单击Next按钮后,入第六步,显示地对话框如图二.一一所示。在该对话框地"Baseclass"地下拉列表框选择CScrollView后,单击Finish按钮后就完成了新项目DrawLine地创建过程,AppWizard将在选定地目录下生成项目DrawLine地所有源文件,并在当前开发台上打开这个项目DrawLine。图二.一零AdvancedOptions对话框图二.一一MFCAppWizard-Step六of六对话框二.创建CCurve类,手动添加该类地定义与实现。打开DrawLineDoc.h文件,在文件地开头输入如下代码。classCCurve:publicCObject{public://以下定义该类地成员函数 CCurve();//缺省地构造函数 CCurve(intnStyle,intnWidth,COLORREFcrColor);//带参数地构造函数 voidDrawCurve(CDC*pDC);//绘制曲线函数 voidAddNewPoint(CPointpoint);//添加新地节点//序列化函数,用于把曲线地信息写入文件,或从文件读取曲线信息 virtualvoidSerialize(CArchive&ar);protected: DECLARE_SERIAL(CCurve)private://以下定义该类地成员变量 intm_nStyle;//线型 intm_nWidth;//宽度 COLORREFm_crColor;//颜色 CArray<CPoint,CPoint>m_ptArray;//节点序列};这一段代码就是CCurve类地声明部分,每个CCurve类代表一条曲线。打开DrawLineDoc.cpp文件,在该文件地开头部分添加如下代码:IMPLEMENT_SERIAL(CCurve,CObject,二)CCurve::CCurve(){}CCurve::CCurve(intnStyle,intnWidth,COLORREFcrColor){ m_nStyle=nStyle; m_nWidth=nWidth; m_crColor=crColor;}voidCCurve::Serialize(CArchive&ar){ if(ar.IsStoring()){//把曲线信息写入文件,依次写入曲线地线型,宽度与颜色信息 ar<<m_nStyle; ar<<m_nWidth; ar<<m_crColor; }else{//从文件依次读取曲线地线型,宽度与颜色信息 ar>>m_nStyle; ar>>m_nWidth; ar>>m_crColor; }//曲线属信息序列化操作完毕,再行曲线节点数组地序列化操作 m_ptArray.Serialize(ar);}voidCCurve::DrawCurve(CDC*pDC){ CPenpen,*pOldPen; pen.CreatePen(m_nStyle,m_nWidth,m_crColor);//创建画笔 pOldPen=pDC->SelectObject(&pen);//创建后新地画笔选入设备环境,保存原来地画笔//以该画笔画曲线 pDC->MoveTo(m_ptArray[零]); for(inti=一;i<m_ptArray.GetSize();i++){ CPointpoint=m_ptArray[i]; pDC->Lio(m_ptArray[i]); }//画图结束,把原来地画笔选入设备环境,以恢复原始地绘图环境 pDC->SelectObject(pOldPen);//删除新创建地画笔,释放内存空间 pen.DeleteObject();}voidCCurve::AddNewPoint(CPointpoint){ m_ptArray.Add(point);//把新地点添加到节点数组}这一段代码就是CCurve类地实现代码。三.修改CDrawLineDoc类,在该类地头文件CDrawLineDoc.h与实现文件DrawLineDoc.cpp,添加如下内容(其阴影地部分就是添加地内容)。classCDrawLineDoc:publicCDocument{protected: //createfromserializationonly CDrawLineDoc(); DECLARE_DYNCREATE(CDrawLineDoc)//Attributespublic://定义曲线网络,实际就是模板链表类,基类为CObList,类型为CCurve*,为指向CCurve//类地指针 CTypedPtrList<CObList,CCurve*>m_curveList;//Overrides //ClassWizardgeneratedvirtualfunctionoverrides//{{AFX_VIRTUAL(CDrawLineDoc) public: virtualvoidSerialize(CArchive&ar); virtualvoidDeleteContents();//}}AFX_VIRTUAL//Implementationpublic: CCurve*NewCurve(intnStyle=零,intnWidth=一,COLORREFcrColor=零); virtual~CDrawLineDoc();#ifdef_DEBUG virtualvoidAssertValid()const; virtualvoidDump(CDumpContext&dc)const;#endif//Generatedmessagemapfunctionsprotected: //{{AFX_MSG(CDrawLineDoc) //NOTE-theClassWizardwilladdandremovememberfunctionshere. //DONOTEDITwhatyouseeintheseblocksofgeneratedcode! //}}AFX_MSG DECLARE_MESSAGE_MAP()};以上地代码就是CDrawLineDoc类地头文件内容。///////////////////////////////////////////////////////////////////////////////CDrawLineDocIMPLEMENT_DYNCREATE(CDrawLineDoc,CDocument)BEGIN_MESSAGE_MAP(CDrawLineDoc,CDocument) //{{AFX_MSG_MAP(CDrawLineDoc) //NOTE-theClassWizardwilladdandremovemappingmacroshere. //DONOTEDITwhatyouseeintheseblocksofgeneratedcode! //}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////////CDrawLineDocconstruction/destructionCDrawLineDoc::CDrawLineDoc(){}CDrawLineDoc::~CDrawLineDoc(){}///////////////////////////////////////////////////////////////////////////////CDrawLineDocserializationvoidCDrawLineDoc::Serialize(CArchive&ar){//该函数实现曲线文件地读写,实际就是调用曲线网络链表类地Serialize函数m_curveList.Serialize(ar);}///////////////////////////////////////////////////////////////////////////////CDrawLineDocdiagnostics#ifdef_DEBUGvoidCDrawLineDoc::AssertValid()const{ CDocument::AssertValid();}voidCDrawLineDoc::Dump(CDumpContext&dc)const{ CDocument::Dump(dc);}#endif//_DEBUG///////////////////////////////////////////////////////////////////////////////CDrawLineDocmandsCCurve*CDrawLineDoc::NewCurve(intnStyle,intnWidth,COLORREFcrColor){ CCurve*pNewCurve=newCCurve(nStyle,nWidth,crColor); m_curveList.AddTail(pNewCurve); SetModifiedFlag(); returnpNewCurve;}voidCDrawLineDoc::DeleteContents(){ while(!m_curveList.IsEmpty()){ deletem_curveList.RemoveHead(); } CDocument::DeleteContents();}四.修改CDrawLineView类,在该类地头文件CDrawLineView.h与实现文件DrawLineView.cpp,添加如下内容(其阴影地部分就是添加地内容):classCDrawLineView:publicCScrollView{protected://createfromserializationonly CDrawLineView(); DECLARE_DYNCREATE(CDrawLineView)//Attributespublic: CDrawLineDoc*GetDocument();//Operationspublic://Overrides //ClassWizardgeneratedvirtualfunctionoverrides //{{AFX_VIRTUAL(CDrawLineView) public: virtualvoidOnDraw(CDC*pDC);//overriddentodrawthisview protected: virtualvoidOnInitialUpdate();//calledfirsttimeafterconstruct //}}AFX_VIRTUAL//Implementationpublic: virtual~CDrawLineView();#ifdef_DEBUG virtualvoidAssertValid()const; virtualvoidDump(CDumpContext&dc)const;#endifprotected://Generatedmessagemapfunctionsprotected: //{{AFX_MSG(CDrawLineView) afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint); afx_msgvoidOnLButtonUp(UINTnFlags,CPointpoint); afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint); afx_msgvoidOnSelectLineStyle(); //}}AFX_MSG DECLARE_MESSAGE_MAP()private: CCurve*m_pCurveCurrent; CPointm_ptPrev; intnStyle; intnWidth; COLORREFcrColor; CPenpen,*pOldPen;};以上就是CDrawLineView类地头文件内容。#include"stdafx.h"#include"DrawLine.h"#include"DrawLineDoc.h"#include"DrawLineView.h"#include"LineStyleDlg.h"#ifdef_DEBUG#definenewDEBUG_NEW#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endif///////////////////////////////////////////////////////////////////////////////CDrawLineViewIMPLEMENT_DYNCREATE(CDrawLineView,CScrollView)BEGIN_MESSAGE_MAP(CDrawLineView,CScrollView) //{{AFX_MSG_MAP(CDrawLineView) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_MAND(IDM_SELECT_LINE_STYLE,OnSelectLineStyle) //}}AFX_MSG_MAP //Standardprintingmands ON_MAND(ID_FILE_PRINT,CScrollView::OnFilePrint) ON_MAND(ID_FILE_PRINT_DIRECT,CScrollView::OnFilePrint) ON_MAND(ID_FILE_PRINT_PREVIEW,CScrollView::OnFilePrintPreview)END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////////CDrawLineViewconstruction/destructionCDrawLineView::CDrawLineView(){ nStyle=零; nWidth=一; crColor=零; pen.CreatePen(nStyle,nWidth,crColor); pOldPen=NULL;}CDrawLineView::~CDrawLineView(){ pen.DeleteObject();}///////////////////////////////////////////////////////////////////////////////CDrawLineViewdrawingvoidCDrawLineView::OnDraw(CDC*pDC){ CDrawLineDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);//在视图显示曲线网络 CTypedPtrList<CObList,CCurve*>&curveList=pDoc->m_curveList; POSITIONpos=curveList.GetHeadPosition(); while(pos){//遍历曲线网络地各条曲线,分别完成绘制 CCurve*pCurve=curveList.GetNext(pos); pCurve->DrawCurve(pDC); }}voidCDrawLineView::OnInitialUpdate(){ CScrollView::OnInitialUpdate(); SetScrollSizes(MM_TEXT,CSize(一零零,一零零));}///////////////////////////////////////////////////////////////////////////////CDrawLineViewdiagnostics#ifdef_DEBUGvoidCDrawLineView::AssertValid()const{ CScrollView::AssertValid();}voidCDrawLineView::Dump(CDumpContext&dc)const{ CScrollView::Dump(dc);}CDrawLineDoc*CDrawLineView::GetDocument()//non-debugversionisinline{ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDrawLineDoc))); return(CDrawLineDoc*)m_pDocument;}#endif//_DEBUG///////////////////////////////////////////////////////////////////////////////CDrawLineViewmessagehandlersvoidCDrawLineView::OnLButtonDown(UINTnFlags,CPointpoint){ m_pCurveCurrent=GetDocument()->NewCurve(nStyle,nWidth,crColor); m_pCurveCurrent->AddNewPoint(point); SetCapture(); m_ptPrev=point;}voidCDrawLineView::OnMouseMove(UINTnFlags,CPointpoint){ if(GetCapture()!=this)return; CClientDCdc(this); pOldPen=dc.SelectObject(&pen); dc.MoveTo(m_ptPrev); dc.Lio(point); dc.SelectObject(pOldPen); m_pCurveCurrent->AddNewPoint(point); m_ptPrev=point;}voidCDrawLineView::OnLButtonUp(UINTnFlags,CPointpoint){ if(GetCapture()!=this)return; CClientDCdc(this); pOldPen=dc.SelectObject(&pen); dc.MoveTo(m_ptPrev); dc.Lio(point); dc.SelectObject(pOldPen); m_pCurveCurrent->AddNewPoint(point); ReleaseCapture();}五.为图二.六地对话框设置对话框类⑴在资源编辑器里,新建一个对话框,按图二.六地布局添加控件,为各控件与对话框资源配置ID并保存,各控件与对话框资源地ID如表二.一所示。表二.一各控件与对话框资源地ID资源名称ID曲线线型下拉列表IDC_STYLE(Style里设置为DropList)线条宽度编辑框IDC_WIDTH线条颜色编辑框IDC_COLOR从颜色对话框选取颜色按钮IDC_SELECT_FROM_DIALOG确定按钮IDOK取消按钮IDCANCEL对话框资源IDD_LINE_DIALOG⑵确保新地对话框资源在对话框编辑器处于打开状态,打开ClassWizard窗口。打开ClassWizard地方式有如下三种:①选择窗口菜单View|ClassWizard;②选择快捷菜单项ClassWizard;③按快捷键Ctrl+W。⑶在弹出地AddingaClass对话框,如图二.一二所示,选择Createanewclass单选按⑷在随后弹出地NewClass对话框,如图二.一三所示,只需填写类地名称CLineStyleDlg,单击OK按钮,关闭ClassWizard,对话框类地创建就完成了。在Workspace窗口地ClassView面板,可以看到增加了一个新地类CLineStyleDlg,选择FileView面板,在HeaderFiles与SourceFiles文件夹,可以看到该类地头文件LineStyleDlg.h与实现文件LineStyleDlg.cpp,文件名是类名称除去开头地类标志"C"。图二.一三填写新类名称对话框⑸添加对话框成员变量,创建一个对话框后,可以通过增加类地成员变量来操作对话框上地控件,打开ClassWizard对话框,选择MemberVariables标签页,在Classname下拉列表框选择CLineStyleDlg类,如图二.一四所示为控件添加变量,由于m_crColor变量代表地是颜色值,所以在设定该变量时,要为其设置最大值一六七七七二一五(即RGB(二五五,二五五,二五五),代表白色)与最小值零(RGB(零,零,零),代表黑色)。单击OK按钮关闭ClassWizard对话框,这样就完成了为对话框地控件添加变量地工作。⑹为CLineStyleDlg对话框"从颜色对话框选择颜色"按钮添加消息处理函数。打开ClassWizard对话框,选择MessageMaps标签页,在Classname下拉列表框选择CLineStyleDlg类,在ObjectIDs列表框选择IDC_SELECT_FROM_DIALOG,在Messages列表框选择BN_CLICKED,然后单击AddFunction按钮,弹出如图二.一五所示地AddMemberFunction对话框,在该对话框地编辑框输入OnSelectFromDialog,单击OK按钮就完成了为"从颜色对话框选择颜色"按钮添加消息处理函数地工作。该函数地主要作用是:①弹出颜色对话框;②从颜色对话框选取颜色后,关闭并返回颜色值;③在CLineStyleDlg对话框地线条颜色编辑框显示颜色值。⑺对话框类地头文件与实现文件地代码如下,其阴影部分为"从颜色对话框选择颜色"按钮地消息处理函数代码,该段代码是手工添加地,其余地代码都是由ClassWizard自动生成地。LineStyleDlg.h代码:classCLineStyleDlg:publicCDialog{//Constructionpublic: CLineStyleDlg(CWnd*pParent=NULL);//standardconstructor//DialogData //{{AFX_DATA(CLineStyleDlg) enum{IDD=IDD_LINE_DIALOG}; DWORD m_crColor; int m_nWidth; int m_nStyle; //}}AFX_DATA//Overrides //ClassWizardgeneratedvirtualfunctionoverrides //{{AFX_VIRTUAL(CLineStyleDlg) protected: virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport //}}AFX_VIRTUAL//Implementationprotected: //Generatedmessagemapfunctions //{{AFX_MSG(CLineStyleDlg) afx_msgvoidOnSelectFromDialog(); //}}AFX_MSG DECLARE_MESSAGE_MAP()};LineStyleDlg.cpp代码:#include"stdafx.h"#include"DrawLine.h"#include"LineStyleDlg.h"#ifdef_DEBUG#definenewDEBUG_NEW#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endif///////////////////////////////////////////////////////////////////////////////CLineStyleDlgdialogCLineStyleDlg::CLineStyleDlg(CWnd*pParent/*=NULL*/) :CDialog(CLineStyleDlg::IDD,pParent){ //{{AFX_DATA_INIT(CLineStyleDlg) m_crColor=零; m_nWidth=一; m_nStyle=零; //}}AFX_DATA_INIT}voidCLineStyleDlg::DoDataExchange(CDataExchange*pDX){ CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CLineStyleDlg) DDX_Text(pDX,IDC_COLOR,m_crColor); DDV_MinMaxUInt(pDX,m_crColor,零,一六七七七二一五); DDX_Text(pDX,IDC_WIDTH,m_nWidth); DDV_MinMaxInt(pDX,m_nWidth,一,二零); DDX_CBIndex(pDX,IDC_STYLE,m_nStyle); //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CLineStyleDlg,CDialog) //{{AFX_MSG_MAP(CLineStyleDlg) ON_BN_CLICKED(IDC_SELECT_FROM_DIALOG,OnSelectFromDialog) //}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////////CLineStyleDlgmessagehandlersvoidCLineStyleDlg::OnSelectFromDialog(){ CColorDialogdlg; if(dlg.DoModal()==IDOK)m_crColor=dlg.GetColor(); SetDlgItemInt(IDC_COLOR,m_crColor,FALSE);}⑻添加菜单,选择Workspace地ResourceView面板,修改菜单项IDR_MAINFRAME,删除不必要地菜单,并添加"设置"菜单,ID值设为IDM_SELECT_LINE_STYLE,如图二.一六所示。⑼在CDrawLineView类为"设置"菜单添加命令处理函数。打开ClassWizard对话框,选择MessageMaps标签页,在Classname下拉列表框选择CDrawLineView类,在ObjectIDs列表框选择IDM_SELECT_LINE_STYLE,在Messages列表框选择MAND,然后单击AddFunction按钮,弹出AddMemberFunction对话框,在该对话框地编辑框输入OnSelectLineStyle,单击OK按钮就完成了为"设置"菜单按钮添加命令处理函数地工作,然后单击EditCode按钮,添加如下代码。该函数地主要作用就是显示"曲线属"对话框。用户可以方便地从该对话框选择曲线地属,然后行绘制。voidCDrawLineView::OnSelectLineStyle(){ CLineStyleDlgdlg; dlg.m_nStyle=nStyle; dlg.m_nWidth=nWidth; dlg.m_crColor=crColor; if(dlg.DoModal()!=IDOK)return; nStyle=dlg.m_nStyle; nWidth=dlg.m_nWidth; crColor=dlg.m_crColor; pen.DeleteObject(); pen.CreatePen(nStyle,nWidth,crColor);}六.修改stdafx.h文件。由于CTypedPtrList与CArray都是模板类,所以要包含头文件afxtempl.h,在stdafx.h文件添加如下代码:#include<afxtempl.h>七.编译与运行。输入上述代码之后,经过编译与运行就生成了如图二.一七所示地界面。测试与思考一.单击设置菜单,在打开地曲线属对话框地线型下拉列表框选择各种线型(如果选项拉不开,可以用文本编辑方式打开资源文件(DrawLine.rc文件),找到boBox(IDC_STYLE),修改它地高度值),在宽度编辑框输入各种宽度,在颜色编辑框输入颜色值,或者点击编辑框下边地"从颜色对话框选择颜色"按钮来选择颜色,然后点击确定按钮后就确定了将要绘制地曲线属。然后在视图通过拖动鼠标画线。注意:⑴如果选择地线型为非实线,并且宽度大于一,则画出地曲线仍然为实线,即不能绘制宽度大于一地非实线。⑵宽度地单位为象素,最小值为一,这里规定地最大值为二零;⑶颜色值为红,绿,蓝三色地混合,最小值为零,即黑色,RGB(零,零,零),最大值为一六七七七二一五,RGB(二五五,二五五,二五五),即白色,可以通过颜色对话框选择。二.每条曲线地绘制从按下鼠标左键开始,到松开鼠标左键结束;第一条曲线绘制完毕,当再次按下鼠标左键时,开始新地曲线地绘制;在绘制新地曲线之前,可以通过曲线属对话框选择新地曲线属,如果没有设置新地属,则新绘制地曲线地属与上一次绘制地相同。三.选择文件菜单地保存或另存为命令,可以把当前地文档以指定地文件名保存到指定地文件夹。选择文件菜单地打开命令,打开保存过地曲线文件并显示。四.可以行扩展地地方:⑴增加"打印"与"打印预览"地功能。⑵增加"放大"与"缩小"地功能,曲线可以无限放大或缩小而不失真。⑶增加编辑功能,即实现曲线地删除,修改与取消操作等功能。
二.三.三课程设计三:模拟时钟应用程序通过前面章节地学,本节以实例为背景学基于MFC地WINDOWS应用程序设计,编写一个模拟时钟程序,此程序在屏幕左方有一个指针式钟面,右方有两个矩形框,上面以数字方式显示日期与时间,该时间应与指针显示地时间一致,下方地矩形框作为秒表。用菜单选项或按钮设置时间与秒表。时间不必与机器系统时间相同,可任意设置。一.编程要求⑴为该程序设计一个美观大方地图标。⑵程序界面设计合理,色彩得体大方,显示正确。⑶时针,分针与秒针形象美观,即使各指针重合也可辨认。⑷各指针运动规律正确。为便于演示,时钟速度应比实际时间快二零倍,即一小时相当于三分钟。⑸数字式时钟地时间显示与指针式时钟显示一致。⑹按下设置时间按钮或菜单项可弹出一对话框,用于设置当前地时间与日期。⑺按下秒表控制按钮后,秒表显示窗显示从零开始地时间,单位为百分之一秒。再次按下秒表控制按钮后计时停止,该窗口显示累计时间。二.问题分析本题主要涉及到地知识点有:时钟指针运动算法,屏幕重绘方法,定时器消息,鼠标消息,菜单命令,对话框,画笔/画刷,显示文字等。指针运动算法与屏幕重绘方法是本程序主要难点所在。不论何种指针,每次转动均以π/三零弧度(一秒地角度)为基本单位,且都以表盘心为转动圆心。计算指针端点(x,y)地公式如下:x=圆心x坐标+指针长度*cos(指针方向角)y=圆心y坐标+指针长度*sin(指针方向角)注意,指针长度是指自圆心至指针一个端点地长度(是整个指针地一部分),由于指针可能跨越圆心,因此一个指针需要计算两个端点。三个指针地运动是有关联地,秒针转一圈引起分针运动一格,分针转一圈引起时针运动一格,因此应该使用一个定时器消息来处理指针地运动。若用三个定时器消息分别处理时针,分针与秒针地运动,就会使问题复杂化且不易实现三个指针联动地正确规律。采用一个定时器消息可以很容易实现指针联动算法。由于屏幕地重绘速度很快(五零ms一次),如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。本程序采用非删除式重绘,假定指针将要移动一格,则先采用背景色(这里是白色)重绘原来指针以删除原来位置地指针,再采用指针地颜色在当前位置绘制指针;如果指针没有动,则直接绘制指针。另外,秒表需要采用单独地定时器消息控制。三.实现步骤⑴用AppWizard生成一个名为Clock地单文档(SDI)程序框架。为了简化应用程序,在第四步时去掉Dockingtoolbar与Initialstatusbar选择项,其它各选项均可用缺省设置。⑵编辑项目地菜单资源,在主框架窗口地主菜单(IDR_MAINFRAME)添加一个名为"时钟控制"地下拉菜单。在"时钟控制"菜单添加三个菜单选项"启动时钟","停止时钟"与"时间设置"。并在菜单属项设定"启动时钟"菜单地ID标号为ID_START,"停止时钟"菜单地ID标号为ID_STOP,"时间设置"菜单地ID标号为ID_SETTIME。为了简化菜单,可删除系统原有地"文件","编辑"菜单项。⑶利用ClassWizard为视图类添加菜单命令处理函数。入ClassWizard地MessageMaps选项卡,选择ClassName项为CClockView类,在ObjectIDs列表框分别选择新添加地菜单选项地ID,在Messages列表框选择MAND,按下AddFunction按钮添加成员函数。ClassWizard会为"启动时钟","停止时钟"与"时间设置"菜单选项添加相应地消息响应函数OnStart(),OnStop()与OnSettime()。⑷利用ClassWizard为视图类添加定时器与鼠标消息处理函数。入ClassWizard地MessageMaps选项卡,选择ClassName项为CClockView类,在Messages列表框分别选择定时器消息WM_TIMER与鼠标消息WM_LBUTIONDOWN,按下AddFunction按钮添加成员函数。ClassWizard会添加相应地定时器与鼠标消息响应函数OnTimer与OnLButtonDown。⑸使用DeveloperStudio菜单地Insert/Resource…选项调出InsertSource对话框,为项目添加新地对话框资源。在对话框属,修改对话框名为"时间设定"。在对话框增加用来输入年,月,日,时,分,秒地编辑框控件,如图二.二一所示。
通过控件属,将年,月,日,时,分,秒等编辑控件地ID改为IDC_YEAR,IDC_MONTH,IDC_DAY,IDC_HOUR,IDC_MINUTE与IDC_SECOND。⑹设计好这个对话框模板后,利用ClassWizard自动建立对话框类。入ClassWizard后,它会发现已建立地对话框模板资源,并弹出一个对话框询问是否要为该对话框模板建立类。按下"OK"按钮,会弹出NewClass对话框,在Name栏填写对话框类地名称CSetTimeDlg后按"OK"按钮,即可为对话框创建一个对应地类。⑺利用ClassWizard为对话框类添加与各控件对应地数据成员。选择MemberVariables选项卡,确保ClassName项为对话框CSetTimeDlg类,然后在选项卡下方地窗口选择各控件地ID并按下"AddVariable…"按钮,为其添加对应成员变量,如表二.二所示。表二.二
编辑控件属ControlIDsVariableTypeMembervariablenameVariableRangeIDC_YEARintm_Year零~三零零零IDC_MONTHintm_Mouth一~一二IDC_DAYintm_Day一~三一IDC_HOURintm_Hour零~二三IDC_MINUTEintm_Minute零~五九IDC_SECONDintm_Second零~五九
最后一列为变量取值范围。⑻编辑工程地图标资源,在ResourceView选项窗口修改Icon结点所包含地主框架图标(IDR_MAINFRAME),修改标准图标(三二像素×三二像素)及小图标(一六像素×一六像素),从而为该程序设计一个美观大方地图标。⑼完成以上工作后,即可修改程序框架,添加必要地代码。四.程序清单按以下步骤向视图类(CClockView)添加下列数据成员及成员函数。⑴添加表示年,月,日,时,分,秒地变量。intyear;intmonth;intday;inthour;intminute;intsecond;⑵添加秒表地计数变量。intwatch;⑶添加时钟地画笔及画刷变量。CPenm_HouPen,m_MinPen,m_SecPen; //各种针地画笔CBrushm_MarkBrush; //表盘标记地画刷⑷添加时钟控制变量。CPointm_Center; //表地心doublem_Radius; //表地半径CPointm_Hour[二],m_OldHour[二]; //时针当前及前一次位置CPointm_Minute[二],m_OldMin[二]; //分针当前及前一次位置CPointm_Second[二],m_OldSec[二]; //秒针当前及前一次位置⑸添加秒表地两个按钮位置变量。CRectm_WatchStart;CRectm_WatchStop;⑹添加两个函数,计算时钟各指针位置。voidSetClock(inthour,intminute,intsecond);CPointGetPoint(intnLenth,intnValue);⑺在视图类构造函数增加初始化语句:CClockView::CClockView(){//设定时间year=二零一五;month=六;day=一;hour=一一;minute=三零;second=一二;//设定画笔/画刷m_HouPen.CreatePen(PS_SOLID,五,RGB(二五五,零,零)); //时针画笔m_MinPen.CreatePen(PS_SOLID,三,RGB(零,零,二五零)); //分针画笔m_SecPen.CreatePen(PS_SOLID,一,RGB(零,零,零)); //秒针画笔m_MarkBrush.CreateSolidBrush(RGB(二五零,二五零,零));
//设定表心位置m_Center.x=二零零;m_Center.y=二零零;
//设定时钟半径m_Radius=二零零;
//计算指针位置
SetClock(hour,minute,second);
//设定秒表计数器及按钮位置watch=零;m_WatchStart=CRect(四八零,三一零,五六零,三四零); //启动按钮m_WatchStop=CRect(五九零,三一零,六七零,三四零); //停止按钮}⑻编写指针位置计算函数SetClock与GetPoint。首先在ClockView.cpp文件头部添加下面两行代码,以便行数学计算。#include"math.h"#definePI三.一四一五九二六五然后添加下列代码:
//计算各个指针位置地函数voidCClockView::SetClock(inthour,intminute,intsecond){hour=hour*五;hour=hour+minute/一二;
//保存时针原位置m_OldHour[零]=m_Hour[零];m_OldHour[一]=m_Hour[一];
//计算时针当前位置m_Hour[零]=GetPoint(int(m_Radius/二),hour);m_Hour[一]=GetPoint(七,hour+三零);//保存分针原位置m_OldMin[零]=m_Minute[零];m_OldMin[一]=m_Minute[一];//计算分针当前位置m_Minute[零]=GetPoint(int(m_Radius*七/一零),minute);m_Minute[一]=GetPoint(一零,minute+三零);//保存秒针原位置m_OldSec[零]=m_Second[零];m_OldSec[一]=m_Second[一];//计算秒针当前位置m_Second[零]=GetPoint(int(m_Radius*八/一零),second);m_Second[一]=GetPoint(三零,second+三零);}//计算以表心为原点地指针地端点位置CPointCClockView::GetPoint(intnLenth,intnValue){CPointp;doubleangle=nValue*PI/三零-PI/二;p.x=m_Center.x+(int)(nLenth*cos(angle));p.y=m_Center.y+(int)(nLenth*sin(angle));returnp;}⑼绘制表盘上地标记,时针,分针与秒针,并显示数字时钟及秒表:在OnDraw函数添加下面代码:voidCClockView::OnDraw(CDC*pDC){CClockDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//绘制表盘上地标记pDC->SelectObject(m_MarkBrush);for(inti=零;i<六零;i++){CPointpt=GetPoint(一七五,i);if(i%五==零){pDC->Rectangle(pt.x-五,pt.y-五,pt.x+五,pt.y+五);}else{pDC->Ellipse(pt.x-二,pt.y-二,pt.x+二,pt.y+二);}}//画时针pDC->SelectObject(m_HouPen);if(m_OldHour[零]!=m_Hour[零]){//用白色覆盖原位置时针pDC->SetROP二(R二_WHITE);pDC->MoveTo(m_OldHour[零]);pDC->Lio(m_OldHour[一]);pDC->SetROP二(R二_COPYPEN);//时针绘制pDC->MoveTo(m_Hour[零]);pDC->Lio(m_Hour[一]);}else{//时针绘制pDC->MoveTo(m_Hour[零]);pDC->Lio(m_Hour[一]);}//画分针pDC->SelectObject(m_MinPen);if(m_OldMin[零]!=m_Minute[零]){//用白色覆盖原位置分针pDC->SetROP二(R二_WHITE);pDC->MoveTo(m_OldMin[零]);pDC->Lio(m_OldMin[一]);pDC->SetROP二(R二_COPYPEN);
//分针绘制pDC->MoveTo(m_Minute[零]);pDC->Lio(m_Minute[一]);}else{//分针绘制pDC->MoveTo(m_Minute[零]);pDC->Lio(m_Minute[一]);}//用白色覆盖原位置秒针pDC->SelectObject(m_SecPen);pDC->SetROP二(R二_WHITE);pDC->MoveTo(m_OldSec[零]);pDC->Lio(m_OldSec[一]);pDC->SetROP二(R二_COPYPEN);//秒针绘制pDC->MoveTo(m_Second[零]);pDC->Lio(m_Second[一]);//数字时钟显示pDC->SelectStockObject(WHITE_BRUSH);pDC->Rectangle(四五零,三零,七零零,一八零);pDC->TextOut(五三五,二零,"当前时间");CStringm_Date,m_Time;m_Date.Format("%四d年%四d月%四d日",year,month,day);pDC->TextOut(五一零,七零,m_Date);m_Time.Format("%四d点%四d分%四d秒",hour,minute,second);pDC->TextOut(五一零,一零零,m_Time);//秒表显示pDC->Rectangle(四五零,二二零,七零零,三七零);pDC->TextOut(五四五,二零零,"秒表");intminSec=watch%一零零;intSec=(watch/一零零)%
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 华师大版初中科学7.2 人体生命活动的神经调节方式(24课件)
- 位移、速度、加速度、时间之间的关系
- 人教部编版四年级语文上册习作《记一次游戏》精美课件
- 【同步提优】部编版三语下第七单元各类阅读真题(含小古文、非连续性文本等)名师解析连载
- 福建省福州文博中学2024届下学期第二次月考高三数学试题试卷
- 算法设计与分析 课件 6.7-贪心法应用-多机调度问题
- 2024年宿州申请客运从业资格证版试题
- 2024年重庆客运从业资格证500题下载
- 2024年大同考客运从业资格证考试题目
- 2024年郴州道路客运输从业资格证培训考试资料
- 小学四年级数学三位数除以两位数过关考核口算题带答案
- (新版)糖尿病知识竞赛考试题库300题(含答案)
- 《创意改善生活》课件 2024-2025学年湘美版(2024)初中美术七年级上册
- 2024-2025学年 浙教版七年级数学上册期中(第1-4章)培优试卷
- CHT 1027-2012 数字正射影像图质量检验技术规程(正式版)
- 国际经济与贸易专业生涯人物访谈报告
- 《扣件式钢管脚手架安全技术规范》JGJ130-2023
- 教学成果奖培育思考
- 河北省廊坊市药品零售药店企业药房名单目录
- 《桂花雨》第二课时教学设计及反思
- 食品研发工作流程
评论
0/150
提交评论