这是c++课程设计ppt,包括了课程设计基本要求,Windows 编程基础,什么是VC++的MFC,什么是MFC编程,MFC应用程序的开发流程,单文档【ClassView】面板,登录对话框与单文档视图联接,单文档中菜单项与对话框联接,实例介绍等内容,欢迎点击下载。
c++课程设计ppt是由红软PPT免费下载网推荐的一款课件PPT类型的PowerPoint.
C++课程设计内容及要求 主要内容课程设计基本要求 Windows 编程基础什么是VC++的MFC 什么是MFC编程 MFC应用程序的开发流程单文档【ClassView】面板登录对话框与单文档视图联接单文档中菜单项与对话框联接实例介绍一、课程设计基本要求自学MFC(2学时) 知识扩充 C++:了解并掌握MFC程序结构、消息映射机制、MFC类库中的常用类(对话框、各种常用控件)。软件开发的基本知识结合设计任务清楚软件开发的基本流程、各个阶段的目标和主要工作。上机调试程序(30学时)其他(14学时)程序调试的基本方法和论文撰写要求(2学时)掌握调试程序的方法与技巧。清楚论文组织结构、格式编排等相关知识学生资料查阅与自主学习(2学时)代码编写(10学时)二、Windows 编程基础 Windows 编程就是基于Windows 的应用程序。 2种重要的Windows应用程序基于对话框的应用程序基于文档/视图结构的应用程序主要特点具有标准的图形用户界面具有与硬件无关的特性采用“消息传递,事件驱动”的运行机制,即根据Windows发送的消息来处理用户的输入编写Windows应用程序的主要方法(2种)使用Windows提供的应用程序接口(API)函数使用Microsoft提供的微软基础类(MFC) 三、什么是VC++的MFC MFC(Microsoft Foundation Class Library,基础类库) 是微软提供的用来编写Windows应用程序的C++类库;封装了API(Windows的接口函数),是Win API与C++的结合。 MFC大约有200多个类,封装了Windows的大部分编程对象以及与它们有关的操作。即它由几百个执行文件和源代码文件组成。 注意C++和VC++的区别 C++是一种程序设计语言,是一种大家都承认的软件编制的通用规范,即C++是一套语法规则的名字,类似汉语,英语。 VC++是一个软件{IDE(编译、编辑、调试 )集成开发环境} MFC是一个非外挂式的软件包,类库, MFC类是微软为VC++专配的。四、什么是MFC编程 MFC编程指的就是使用VC++进行开发,并且是在使用VC++提供的各种向导的情况下的MFC编程。在VC++中可以创建3类典型的Windows应用程序基于对话框的应用程序单文档界面(SDI)应用程序多文档界面(MDI)应用程序五、MFC应用程序的开发流程应用程序编程的基本步骤:(1)根据应用程序的特性在MFC AppWizard[exe]应用程序中选择合适的应用程序框架。(2)利用资源编辑器编辑资源,如菜单等。(3)利用类向导(ClassWizard)或手工添加类、成员变量、成员函数声明。(4)编写具体的成员函数代码。(5)编译、链接程序检查程序中是否存在语法错误。(6)调试应用程序。六、单文档【ClassView】面板 CAboutDlg(关于对话框类) 管理关于对话框。 CFrameWnd( 框架窗口类) CWxling_27App(应用程序类)用来处理消息。 CWxling_27Doc (文档类) MFC中的数据是存储在类文档中。文档类负责管理和维护数据本身。 CWxling_27View(视图类)结果的显示是在视图类中。视图类负责处理用户鼠标和键盘的操作。七、登录对话框与单文档视图联接新建单文档工程:TEXT(注意此名由设计者自己任取);在ResourceView, 单击Insert Dialog,插入一对话框IDD_DIALOG1(默认ID号);右键选中新建的对话框,利用类向导建立一个新类Create a new class,名称为:Cdlg_login ;在MainFrm.cpp文件的前面,语句#include “MainFrm.h”的后面添加新类的头文件: #include "dlg_login.h " 在FileView中点击source files,双击MainFrm.cpp。找到: CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct),这是窗体框架创建函数。在该函数的后面(在return 0 ;的前面)加入语句(注意大小写): Cdlg_login dlg; //定义一个登录对话框对象dlg dlg.DoModal(); //让对话框对象以有模式形式显示出来此时对话框与单文档联接完成。下载“格式工厂3.011”将自己的照片转换成BMP格式,通过插入Bitmap命令,将照片引入至资源中,并添加至对话框中。七续、登录对话框退出按钮代码 //确定按钮 void CDlg_login::OnOK() { // TODO: Add extra validation here this->UpdateData(true); if(this->m_name=="wxl" && this->m_paw=="1234") CDialog::OnOK(); else { MessageBox("登录有误"); ExitProcess(0); //退出 } //CDialog::OnOK(); } //取消按钮 void CDlg_login::OnCancel() { // TODO: Add extra cleanup here ExitProcess(0); //退出 } 八、单文档中菜单项与对话框联接新建单文档工程:Ys1(注意此名由设计者自己任取);在ResourceView, 单击Insert Dialog,插入一对话框IDD_DIALOG1(默认ID号);右键选中新建的对话框,利用类向导建立一个新类Create a new class,名称为:Cdlg_jc(自己命名) ,如右图1所示;在// Ys1View.cpp :文件中语句#include " Ys1View.h"的后面添加新类的头文件: #include "dlg_jc.h " 编辑主菜单如图2所示:在主菜下通过“建立类向导”命令,从“Class name”组合框中选择CYs1View,如图3,4所示,并在函数OnJc()编写代码如下: void CYs1View::OnJc() { // TODO: Add your command handler code here Cdlg_jc jc; //定义一个求阶层对话框对象jc jc.DoModal(); //让对话框对象以有模式形式显示出来 } 此时单文档菜单项与对话框联接完成。 1.求阶层按钮的代码使用MFC进行程序设计时,如输出结果是单值,可用以下代码作为模板: void Cdlg_jc::OnOK() { // TODO: Add extra validation here UpdateData(TRUE); //更新控件值 double i,jsz=1.0; for(i=1;i<=m_srs;i++) jsz*=i; //求阶乘 m_jsz.Format (" %f ",jsz); //将双精度型转换为字符,f 对应浮点数 //其中m_jsz为输出编辑框的成员变量名 UpdateData(FALSE); //控件值更新编辑框显示 //CDialog::OnOK(); } 2.求素数按钮的代码 void Cdlg_zss::OnOK() { // TODO: Add extra validation here UpdateData(TRUE); //更新控件值 CDC *pDC=GetDC(); // 获取视图初始的客户区DC //DC表示设备环境 int a=m_szqz; int b=m_szzz; int i,j,n=0; int x=70,y=220; CString s; if(b<=100) //控制只求100内的素 { 注:CDC类有4个派生类 CClientDC类只能在窗口的客户区(不包括边框、标题栏、菜单栏以及状态栏的空白区域)进行绘图。 CMetaFileDC 封装了在一个Windows图元文件中绘图的方法。 CPaintDC 只在处理WM_PAINT消息中使用,用户一旦获得相关的CDC指针,就可以将它当做任何设备环境(包括屏幕、打印机)的指针来使用。 CWindowDC 允许在窗口的任意位置中进行绘图,点(0,0)指整个窗口的左上角。 3.单文档菜单项中画直线代码菜单项“画直线”按钮代码: void CYs1View::OnHzx() { // TODO: Add your command handler code here //使用CClientDC类来画图,创建的是视图窗口的dc对象,作图只能在视图的客服区内作图 Invalidate(true); //擦除窗口原有内容重新绘制 UpdateWindow(); //使窗口立即重绘 CClientDC dc(this); //创建一个名为dc的视图窗口的dc对象,this指向当前的对话框 CPen pen; //设置画笔 //创建一支5号粗细画实线的绿色画笔, pen.CreatePen(PS_SOLID,5,RGB(0,255,0)); //选用新画笔 CPen *oldpen=dc.SelectObject(&pen); dc.MoveTo(500,100); //线段的起点 dc.LineTo(300,500); //线段的终点 } //RGB(红,绿,蓝) 4.单文档菜单项中画矩形代码菜单项“画矩形”按钮代码: void CWxling_28View::OnHjx() { // TODO: Add your command handler code here CClientDC dc(this); CPen pen; //定义画笔 //创建红色3号粗细实线画笔 pen.CreatePen(PS_SOLID,3,RGB(255,0,0)); CPen *oldpen=dc.SelectObject(&pen); CBrush brush; //定义画刷 //创建绿色画刷 brush.CreateHatchBrush(HS_CROSS,RGB(0,255,0)); dc.SelectObject(&brush); dc.Rectangle(300,300,400,500); //画矩形 } 5.单文档菜单项中画椭圆代码菜单项“画椭圆”按钮代码: void CWxling_28View::OnHty() { // TODO: Add your command handler code here CClientDC dc(this); CPen pen; //设置画笔 pen.CreatePen(PS_SOLID,3,RGB(0,255,0)); CPen *oldpen=dc.SelectObject(&pen); dc.Ellipse(300,100,600,300); //画椭圆 } /*(int x1,int y1,int x2,int y2) (x1,y1)和(x2,y2)表示所画椭圆外切矩形的左上角和右下角坐标*/ 6.单文档菜单项中画sin曲线代码在// Wxl_30View. cpp中加入头文件: #include "math.h“ 菜单项“画sin曲线”按钮代码: void CWxl_30View::OnSin() { // TODO: Add your command handler code here CClientDC dc(this); CRect rect; //定义矩形对象 GetClientRect(rect); int x0=rect.Width()/2; int y0=rect.Height()/2; dc.MoveTo(20,y0); dc.LineTo(rect.Width()-20,y0); dc.MoveTo(x0,20); dc.LineTo(x0,rect.Height()-20); double setp=3.14159/100; for(int i=-200;i<200;i++) dc.SetPixel(x0+(i/300.0)*rect.Width()/2.0, y0-sin(setp*i)*rect.Height()/4.0,RGB(255,0,0)); } 7.单文档菜单项中画澳运图标代码 void CA12View::OnHy() { // TODO: Add your command handler code here CClientDC dc(this); CPen pen1,pen2,pen3,pen4,pen5; //设置画笔 pen1.CreatePen(PS_SOLID,5,RGB(0,0,255)); //兰色 pen2.CreatePen(PS_SOLID,5,RGB(0,0,0)); //黑色 pen3.CreatePen(PS_SOLID,5,RGB(255,0,0)); //红色 pen4.CreatePen(PS_SOLID,5,RGB(255,255,0)); //黄色 pen5.CreatePen(PS_SOLID,5,RGB(0,255,0)); //绿色 //创建一支透明画刷,这样先前画的图不会被后面画的挡住 CBrush brush1; //设置画刷,在对话框不要此句 //类名可以调用静态成员函数,而不可以调用非静态成员函数。但是对象都可以调用。 CBrush*brush1=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); //CBrush *pOldbrush=dc.SelectObject(brush1); //选择透明画刷 ,在对话框不要此句 CBrush *pOldbrush=dc.SelectObject(&brush1); //选择透明画刷,在视图窗显示用 dc.SelectObject(&pen1); dc.Ellipse(250,150,350,250); //画兰色圆 dc.SelectObject(&pen4); dc.Ellipse(310,210,400,310); //画黄色圆 dc.SelectObject(&pen2); dc.Ellipse(360,150,460,250); //画黑色圆 dc.SelectObject(&pen5); dc.Ellipse(410,210,510,310); //画绿色圆 dc.SelectObject(&pen3); dc.Ellipse(470,150,570,250); //画红色圆 } 8.常见问题解决方法(1)如何删除一个新建的类?先从workspace中的fileview中删除对应的.h和.cpp文件。再关闭项目,从实际的文件夹中删除对应的.h和.cpp文件。再删除.clw文件。打开项目,全部重建(rebuild all)。(2)某个类突然在工作区间里面突然看不见了? 只是类隐藏了,打开FILEVIEW,找到隐藏类的头文件,随便敲一下键盘的空格键,类就会在CLASSVIEW中显示了(3) 为什么MFC 中自动显示成员列表功能时有时无? 删除该项目扩展名为.ncb 文件,重新打开该项目。(4)如何在应用程序中打开一个超级链接?使用ShellExecute API 函数。例:打开中南大学网站。 ShellExecute(NULL,"open","http://www.csu.edu.cn", NULL, NULL, SW_SHOWNORMAL); 8.常见问题解决方法(5)怎样改变VC++编辑器默认的颜色? 工具/选择/格式,选中注释的颜色即可改变。(6)复制了一段代码到当前工作空间里,可是代码排列很乱,如何调整?按下鼠标左键拖动鼠标将代码选择上,同时按下键盘的ALT+F8 键 (7)设置单文档中标题栏和窗口大小对主框架添加函数PreCreateWindow(),代码如下: BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: 在此处通过修改 //CREATESTRUCT cs 来修改窗口类或样式 cs.style &=~FWS_ADDTOTITLE; cs.lpszName = "我的标题"; //设定窗口的尺寸 cs.cx = 1024; cs.cy = 768; return TRUE; } 8.常见问题解决方法(8)如何处理按回车或ESC键对话框关闭?主要是由于回车键响应OnOK()函数、ESC键响应OnCancel()函数而引起的,解决方法是在Cdlg_js类中添加PreTranslateMessage函数(将按键消息转换成字符消息),代码如下,使用消息传递时过滤掉这两个键盘消息。 BOOL Cdlg_js::PreTranslateMessage(MSG *pMsg) { // TODO: Add your specialized code here and/or call the base class if(pMsg->message == WM_KEYDOWN) //键盘消息 { if(pMsg -> wParam == VK_ESCAPE) //键盘上的Esc键 return TRUE; if(pMsg -> wParam == VK_RETURN) //键盘上的回车键 return TRUE; } return CDialog::PreTranslateMessage(pMsg); } 8.常见问题解决方法建好MFC之后(基于对话框的),然后点击Insert->New Class 弹出对话框之后,Class Type:MFC Class 在Base Class:CRecordset类,点击Ok的时候,会弹出要你添加数据库的对话框你就可以添加了。 (9)如何为MFC 应用程序添加ODBC 功能? (1)在文件Stdafx.h 文件末尾添加下面一行: #include // MFC ODBC database classes (2)在文本模式下编辑RC 文件(利用File->Open As text 方式) 在下面的程序行(共有两处) #include "l.chs\afxprint.rc" // printing/print preview resources 添加下一行: #include "l.chs\afxdb.rc" // Database resources 9.特殊效果(1)如何给MFC单文档添加背景?为CTestView类添加一个变量 CBrush m_brushBackground; //定义画刷用于画背景在CTestView的构造函数中加入如下代码 CBitmap bmp; bmp.LoadBitmap(IDB_BITMAP1); //加载位图 m_brushBackground.CreatePatternBrush(&bmp); //创建位图画刷在OnDraw函数中画出来代码如下 CRect rect; GetClientRect(rect); //取得客户区域 pDC->FillRect(rect,&m_brushBackground); //用背景画刷填充区域为了避免背景的闪烁,使显示更完美,添加WM_ERASEBKGND消息的处理函数,并取消调用父类的处理函数,代码如下 BOOL CTestView::OnEraseBkgnd(CDC* pDC) { return TRUE; } 编译运行该程序! 9.特殊效果(2)在工程调用其他可执行的文件(.EXE) 在w1View.cpp :中加入头文件: #include "windows.h " 在编辑好的菜单项中编写代码如下 void CW1View::OnWord() { // TODO: Add your command handler code here WinExec("CLOCKYS.exe",NULL); //调用可执行文件 } 注意:将可执行文件拷贝至本工程所在的文件夹下,否则要获取文件的路径。若要打开其他类型的文件,见本片的下面的备注。 9.特殊效果(3)在工程调用其他任意文件菜单项按钮代码 void CW12View::OnYy() { // TODO: Add your command handler code here CString path; //返回文件所在的路径,含该文件名 GetModuleFileName( NULL, //要获取文件名的模块句柄(见备注),null表示当前模块 path.GetBufferSetLength(MAX_PATH+1), //存放取得的文件名 MAX_PATH //存放取得的文件名参数的长度 ); path.ReleaseBuffer(); //字符串的缓冲区长度锁定解除 int pos = path.ReverseFind('\\'); //从后向前查找"\" path = path.Left(pos) path = path.Left(pos); //取左,参数为字符串的个数 //MessageBox(path); //调试程序时用来显示查找到的当前运行程序所在目录 ShellExecute(NULL,"open",path+"\\2013年C++课程设计任务书wxl.doc", NULL,NULL, SW_SHOWNORMAL); } 9.特殊效果(4)仅修改工程中某个对话框的图标对对应的对话框添加初始化函数OnInitDialog(),并添加以下代码: BOOL Cdlg_login::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here HICON m_hIcon; //IDR_ICON1为图标资源名 m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1); SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE 9.特殊效果如何去掉单文档界面中主框架的“无标题”? 修改IDR_MAINFRAME字符串资源中第2个参数(共有7个参数),分别以\n结束,即如下格式: \n\n\n\n\n\n\n 例,将主框架标题改为”我的应用程序” 在程序中使用对话框在程序中使用对话框在程序中使用对话框在程序中使用对话框几种常见的几何图形绘制。利用MFC AppWizard建立一个SDI应用程序,在OnDraw()函数中添加如下程序代码: void CMyGraphView::OnDraw(CDC* pDC) { CTexthtDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here for(int xPos=20;xPos<100;xPos+=10) pDC->SetPixel(xPos,30,RGB(0,0,0)); // 绘制像素点 POINT polylpt[5]={{10,100},{50,60},{120,80},{80,150},{30,130}}; pDC->Polyline(polylpt,5); // 绘制4条折线 POINT polybpt[4]={{150,160},{220,60},{300,180}, {330,20}}; pDC->PolyBezier(polybpt,4); // 绘制贝塞尔曲线 CBrush *pBrhOld; pBrhOld=(CBrush*)pDC->SelectStockObject( LTGRAY_BRUSH); // 使用浅灰色堆画刷 pDC->RoundRect(400,30,550,100,20,20); // 绘制圆角矩形 pDC->Arc(20,200,200,300,200,250,20,200); // 绘制椭圆弧 pDC->Pie(220,200,400,380,380,270,240,220); // 绘制扇形 pDC->Chord(420,120,540,240,520,160,420,180); // 绘制弦形 POINT polygpt[5]={{450,200},{530,220},{560,300},{480,320},{430,280}}; pDC->Polygon(polygpt,5); // 绘制五边形 pDC->SelectObject(pBrhOld); // 恢复系统默认的画刷 } 绘制效果九、实例介绍实例1——静态控件的使用实例2——编辑框应用实例3——单选钮应用程序实例4——简易时钟应用程序实例5——计算器应用程序实例6——调用自定义对话框实例7——数据库编程实例实例1——静态控件的使用创建步骤:建立基于对话框的MFC应用程序框架;设置对话放置控件;在菜单或工具栏的空白处,单击右键,弹出控件工具栏,再选择所需控件;设置控件属性;调试程序步骤1:建立基于对话框应用程序框架(1)创建工程:TEST1 步骤2、3:放置控件;调试程序(1)删除现有控件(2)设置对话框标题利用“属性”设置(3)添加组框设置属性(4)添加静态文本框设置属性(5)添加图片单击“插入/资源”命令,通过菜单引入:(位图(BMP或.DIB)、图标(Icon)、图元文件(wMF )图片控件属性对对话框中的类型、图像进行设置特殊效果——对话框中设置静态文本框字体及颜色操作步骤: 1. 添加对话框类声明中字体和颜色变量 class CDHK2013Dlg : public CDialog { // Construction public: CFont m_myFont; // 字体对象 COLORREF m_myColor; // 颜色对象 ……. 2. 在对话框初始化函数OnInitDialog()中对字体和颜色进行初始化 m_myFont.CreatePointFont(150, _T(“华文彩云”)); //150是字体大小 m_myColor = RGB(255, 0, 255); 续上: 3. 为对话框类添加WM_CTLCOLOR消息响应函数,并在其消息响应函数OnCtlColor()中添加代码 // 消息响应函数实现 HBRUSH CDHK2013Dlg::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor ) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here (在此更改 DC 的任何属性) if(pWnd->GetDlgCtrlID()==IDC_STATIC_1) { pDC->SelectObject(&m_myFont); // 设置字体 pDC->SetTextColor(m_myColor); // 设置颜色 } // TODO: Return a different brush if the default is not desired(如果默认的不是所需画笔,则返回另一个画笔 ) return hbr; } 实例2——编辑框应用创建步骤:建立基于对话框的MFC应用程序框架;设置对话放置控件;设置控件属性;为控件连接变量,即为控件命名;添加并且编写消息处理函数;调试程序。 步骤1,2:建立框架、添加控件(1)创建工程:TEST2 (2)添加控件,并设置控件相关属性步骤3:连接变量(1)单击“建立类向导”命令,启动类向导;(2)选择“成员变量”选取项卡,连接变量;(3)结果如右图所示步骤4:进行消息映射(1)初始化对话框(是程序运行时的开始状态的设定)进入ClassWiZard(类向导),Message Maps,在Object IDs里选择要添加OnInitDialog()函数的对话框类,在Messages里选择WM_INITDIALOG,单击Add Function(增加函数),此时对话框类就新增了一个函数是OnInitDialog()。(2)编辑初始化代码: 步骤5:编写代码_对“计算平均分”按钮(1)双击“计算平均分”按钮,为IDC_JS添加BN_CLICKED消息映射:(2)编写代码。步骤6:编写代码_对“退出”按钮(1)双击“退出”按钮,为IDC_OK添加BN_CLICKED消息映射:(2)编写代码。步骤7:调试程序_运行注意:对话框中平均分显示部分是在设置属性时,选择了“扩展样式”选项卡中的“客户边缘”选项的效果。实例3——单选钮应用程序设计如右图所示的程序。基本步骤:创建工程TESTp246,并进行界面设计;为编辑框连接到CString类型的添加成员变量m_xm,其余控件不需连接;为控件编辑ID 4. 对单选钮编写初始化函数代码 5. 对对话框的“确定”按钮编写代码步骤1~3:建立框架,连接变量,编辑ID 注意对组框1中2个单选按钮,在设置第一个按钮(男)的属性时,需选定“组”选项,表示此组默认第1个按钮;同理对组框2中3个单选按钮,在设置第一个按钮(教授)的属性时,需选定“组”选项,表示此组默认第1个按钮;组框本身的属性不要选中“组”选项。步骤4:单选钮初始化函数代码 BOOL CTESTp246Dlg::OnInitDialog() { CDialog::OnInitDialog(); CheckRadioButton(IDC_RADIO1,IDC_RADIO2,IDC_RADIO1); CheckRadioButton(IDC_RADIO3,IDC_RADIO5,IDC_RADIO3); // Add "About..." menu item to system menu. …… 步骤5:对话框的“确定”按钮代码 void CTESTp246Dlg::OnButton1() { // TODO: Add your control notification handler code here UpdateData(TRUE); CString s; s=s+m_xm; if(IsDlgButtonChecked(IDC_RADIO1)) s=s+"男"; else s=s+"女"; if(IsDlgButtonChecked(IDC_RADIO3)) s=s+"教授"; else if(IsDlgButtonChecked(IDC_RADIO4)) s=s+"副教授"; else s=s+"讲师"; AfxMessageBox(s); } 实例4——简易时钟程序——基于对话框基本步骤:创建工程(基于基本对话框的)CLOCKYS(时钟演示) 添加新类CClockEx,实现时钟控件类。添加消息响应及函数,来建立时钟控件的轮廓。时钟设计——时钟元素创建时钟基类——CClockElement 添加时针类、分针类、秒针类编译执行。 步骤1:创建工程CLOCKYS 步骤2:创建一个新类CClockEx 从CStatic(静态控件)类派生出类CClockEx 来实现时钟控件类,这样,就可以继承MFC静态控件的很多已经具备的功能和特点. 步骤3:添加消息响应——建立时钟控件的轮廓时钟控件的轮廓单击“查看\建立类向导” 调出Class Wizard,在class name中选择刚建立的新类CClockEx,进行如下工作:步骤4:时钟设计——时钟元素时钟绘制的具体实现。时钟大致由:时钟背景、时针、分针、秒针4个部分构成。这4个部分可看作4个不同的对象,可以考虑建立类来分别实现。 。 CClockBackground (背景) CClockHourHand(时针) CClockMinHand(分针) CClockSecHand(秒针)这4个类有它们的共同点:都有自己的绘图函数;都有自己的绘图颜色;都应有颜色设置函数;都有绘图区域和区域设置函数等等。因此,可以为它们的共性建立一个基类,命名为: CClockElement(时钟元素)。步骤4续:创建时钟基类——CClockElement 先建各个组成类的基类: CClockElement 方法:右键单击ClassView的工程选择New Class;在ClassType里面选择Genenric Class,类; CClockElement不需要从其它类派生,所以Base Class可以不填,效果如右图所示。步骤4续:创建时钟基类——CClockElement代码对类CClockElement的源代码进行编写。添加头文件 #include 因后面的绘图中需要用到sin和cos这两个数学计算公式。为后面计算使用,定义数学常量 PI(3.1415926535)。在基类中定义绘图区域变量时钟的每个组成部分都有绘图区域区域,可定义颜色变量。为了是颜色不显得单调,这里为每个控件设置两种颜色(如果想使程序更加绚丽,可以设置更多颜色)。增加接口函数这些变量需增加接口函数来进行访问。每个组成部分都应该有的Draw(绘图)函数也需在基类中定义,但是,该函数对于基类来说是无需函数实现的,因此可定义为纯虚函数。步骤4续:创建时钟基类——CClockElement代码 // ClockElement.h: interface for the CClockElement class. CClockElement的实现的头文件代码如下: #if !defined(AFX_CLOCKELEMENT_H__08A9DFB3_95C0_4D70_9BC0_96D3BACAB74A__INCLUDED_) #define AFX_CLOCKELEMENT_H__08A9DFB3_95C0_4D70_9BC0_96D3BACAB74A__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include #define PI 3.1415926535 class CClockElement { public: void SetColor(COLORREF crMain, COLORREF crOther); //设置颜色 void SetTime(const CTime &tmCur); //设置当前时间 void SetRegion(LPRECT lprcRect); //设置绘图区域 virtual void Draw(CDC *pDC) = 0; //绘图函数,此函数是一虚函数 CClockElement(); virtual ~CClockElement(); protected: COLORREF m_crMain; //主要颜色 COLORREF m_crOther; //辅助的其他颜色 CTime m_tmCur; //当前时刻 CRect m_rcRegion; //绘图区域 int m_nRadius; //时钟半径 }; CClockElement的实现的源文件关键代码如下: // ClockElement.cpp: CClockElement::CClockElement() //时钟基类构造函数 { m_nRadius = 0; //时钟半径 m_crMain = RGB(255, 255, 255); //主要颜色 m_crOther = RGB(128, 128, 128); //辅助的其他颜色 } CClockElement::~CClockElement() { } //时钟基类析构函数 //设置绘图区域函数 void CClockElement::SetRegion(LPRECT lprcRect) { m_rcRegion = lprcRect; //区域取值 m_nRadius = m_rcRegion.Width() / 2; //半径取值 if (m_rcRegion.Width() > m_rcRegion.Height()) //半径的宽度和顶点比较 { m_nRadius = m_rcRegion.Height() / 2; } } //设置当前时间函数 void CClockElement::SetTime(const CTime &tmCur) { m_tmCur = tmCur; } //设置颜色函数 void CClockElement::SetColor(COLORREF crMain, COLORREF crOther) { m_crMain = crMain; //获取主颜色 m_crOther = crOther; //获取其他颜色 } 步骤5:创建时钟背景类——CClockBackground 时钟背景类——CClockBackground 操作方法:在ClassView的工程名上面点右键,选择New Class,在ClassType里面选择Genenric Class,选择类Base Class CClockElement类因CClockBackground需从类CClockElement派生效果如图所示。步骤5续:创建时钟背景类——CClockBackground CClockBackground只需实现基类的虚函数Draw即可,因此这里重载基类的虚函数Draw,其头文件实现代码如下(不用编写,由系统生成): #include "ClockElement.h" class CClockBackground : public CClockElement { public: CClockBackground(); virtual ~CClockBackground(); }; CClockBackground源文件代码如下: // ClockBackground.cpp: //时钟背景函数 CClockBackground::CClockBackground() { //为时钟背景定义默认的颜色设置 m_crMain = RGB(0, 255, 0); //主颜色为绿色 m_crOther = RGB(0, 128, 0); //其他颜色为深绿色 } CClockBackground::~CClockBackground() { } CClockBackground源文件代码如下(续1): //Draw 绘图函数 void CClockBackground::Draw(CDC *pDC) { //准备设备环境(也称设备上下文,简称DC),是图形设备的主要接口 CPen penMain(PS_SOLID, 1, m_crMain), //创建一支主颜色为绿色能画实线(SOLID)1号粗细的画笔 penOther(PS_SOLID, 1, m_crOther); //创建一支其他颜色为深绿色能画实线1号粗细的画笔 CBrush brMain(m_crMain), brOther(m_crOther); //创建主画刷和其他画刷 //将其他画笔选入内存DC,同时暂时挤出并保存原画笔 CPen *pOldPen = pDC->SelectObject(&penOther); //将主画刷选入内存DC,同时暂时挤出并保存原画刷 CBrush *pOldBrush = pDC->SelectObject(&brMain); //绘制60个小圆点,表示分针和秒针的刻度 CPoint ptCenter = m_rcRegion.CenterPoint(); //创建画点对象并初始化 int nRadius = m_nRadius - 8; //定义半径的初值 for(int i=0; i<60; i++) { CPoint ptEnd = ptCenter; ptEnd.Offset((int)(nRadius * sin(2 * PI * (i % 60) / 60)), (int)(-nRadius * cos(2 * PI * (i % 60) / 60))); // CRect是MFC定义的一个矩形类有4个数据成员: //(left,top)和(right,bottom)分别表示一个矩形左上角坐标和右下角坐标 CRect rcDot(-2, -2, 2, 2); //创建矩形上的小圆点并初始化 rcDot.OffsetRect(ptEnd); pDC->Ellipse(rcDot); } } CClockBackground源文件代码如下(续2): //绘制12个小方框,表示12个正点 pDC->SelectObject(&penMain); //恢复内存DC中原有的主画笔 pOldBrush = pDC->SelectObject(&brOther); for(i=0; i<12; i++) { CPoint ptEnd = ptCenter; double fRadian = 2 * PI * (i % 12) / 12; ptEnd.Offset((int)(nRadius * sin(fRadian)), (int)(-nRadius * cos(fRadian))); CRect rcDot(-3, -3, 3, 3); rcDot.OffsetRect(ptEnd); pDC->Rectangle(rcDot); } //还原设备环境 pDC->SelectObject(pOldPen); //恢复内存DC中原有的画笔 pDC->SelectObject(pOldBrush); //恢复内存DC中原有的画刷 步骤6:创建时针类——CClockHourHand实现实现时针类CClockHourHand 该类新建的过程与CClockBackground一样。选择类Base Class CClockElement类因CClockHourHand需从类CClockElement派生 CClockHourHand同样只需实现基类的虚函数Draw即可其头文件实现代码如下: #include "ClockElement.h" class CClockHourHand : public CClockElement { public: CClockHourHand(); virtual ~CClockHourHand(); virtual void Draw(CDC *pDC); }; CClockHourHand源文件代码如下: CClockHourHand::CClockHourHand() { //定义默认颜色 m_crMain = RGB(0, 255, 100); m_crOther = RGB(128, 128, 0); } CClockHourHand::~CClockHourHand() { } void CClockHourHand::Draw(CDC *pDC) { //初始化设备环境 CPen penMain(PS_SOLID, 1, m_crMain), penOther(PS_SOLID, 1, m_crOther); CBrush brMain(m_crMain), brOther(m_crOther); CPen *pOldPen = pDC->SelectObject(&penOther); CBrush *pOldBrush = pDC->SelectObject(&brMain); //确定当前指针的弧度 int nTime = (m_tmCur.GetHour() % 12) * 3600; nTime += m_tmCur.GetMinute() * 60; nTime += m_tmCur.GetSecond(); double fRadian = 2 * PI * nTime / 3600 / 12; CClockHourHand源文件代码如下(续): //确定绘制菱形指针所需的四个角的坐标 CPoint ptDiamond[4]; for(int i=0; i<4; i++) { ptDiamond[i] = m_rcRegion.CenterPoint(); } int nRadus = m_nRadius / 2; ptDiamond[0].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); fRadian += 0.5 * PI; nRadus = m_nRadius / 20; ptDiamond[1].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); fRadian += 0.5 * PI; nRadus = m_nRadius / 10; ptDiamond[2].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); fRadian += 0.5 * PI; nRadus = m_nRadius / 20; ptDiamond[3].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); //绘制菱形时针 pDC->Polygon(ptDiamond, 4); //恢复设备环境 pDC->SelectObject(pOldPen); pDC->SelectObject(pOldBrush); } 步骤7:创建分针类——CClockMinHand实现实现分针类CClockMinHand 该类新建的过程与CClockHourHand一样,类的实现也基本相似,其头文件实现代码如下: CClockMinHand类因CClockMinHand需从类CClockElement派生 CClockMinHand同样只需实现基类的虚函数Draw即可 #include "ClockElement.h" class CClockMinHand : public CClockElement { public: CClockMinHand(); virtual ~CClockMinHand(); virtual void Draw(CDC *pDC); }; CClockMinHand源文件代码如下: CClockMinHand::CClockMinHand() { //定义默认颜色 m_crMain = RGB(0, 255, 100); m_crOther = RGB(128, 128, 0); } CClockMinHand::~CClockMinHand() { } void CClockMinHand::Draw(CDC *pDC) { //初始化设备环境 CPen penMain(PS_SOLID, 1, m_crMain), penOther(PS_SOLID, 1, m_crOther); CBrush brMain(m_crMain), brOther(m_crOther); CPen *pOldPen = pDC->SelectObject(&penOther); CBrush *pOldBrush = pDC->SelectObject(&brMain); //确定分针所在位置的弧度 int nTime = m_tmCur.GetMinute() * 60; nTime += m_tmCur.GetSecond(); double fRadian = 2 * PI * nTime / 3600; CClockMinHand源文件代码如下(续): //确定绘制菱形指针所需的四个角的坐标 CPoint ptDiamond[4]; for(int i=0; i<4; i++) { ptDiamond[i] = m_rcRegion.CenterPoint(); } int nRadus = m_nRadius / 2; ptDiamond[0].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); fRadian += 0.5 * PI; nRadus = m_nRadius / 20; ptDiamond[1].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); fRadian += 0.5 * PI; nRadus = m_nRadius / 10; ptDiamond[2].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); fRadian += 0.5 * PI; nRadus = m_nRadius / 20; ptDiamond[3].Offset((int)(nRadus * sin(fRadian)), (int)(- nRadus * cos(fRadian))); //绘制菱形分针 pDC->Polygon(ptDiamond, 4); //恢复设备环境 pDC->SelectObject(pOldPen); pDC->SelectObject(pOldBrush); } 步骤8:创建秒针类——CClockSecHand实现实现秒针类CClockSecHand 此类与CClockHourHand一样建立,类的实现也基本相似其头文件实现代码如下: #include "ClockElement.h" class CClockSecHand : public CClockElement { public: CClockSecHand(); virtual ~CClockSecHand(); virtual void Draw(CDC *pDC); }; CClockSecHand源文件代码如下: CClockSecHand::CClockSecHand() { //设定秒针的默认颜色 m_crMain = RGB(0, 200, 200); m_crOther = RGB(0, 200, 200); } CClockSecHand::~CClockSecHand() { } void CClockSecHand::Draw(CDC *pDC) { int nTime = m_tmCur.GetSecond(); CPoint ptStart = m_rcRegion.CenterPoint(); CPoint ptEnd = ptStart; int nRadius = m_nRadius - 10; ptEnd.Offset((int)(nRadius * sin(2 * PI * nTime / 60)), (int)(-nRadius * cos(2 * PI * nTime / 60))); CPen penMain(PS_SOLID, 1, m_crMain); CPen *pOldPen = pDC->SelectObject(&penMain); pDC->MoveTo(ptStart); pDC->LineTo(ptEnd); pDC->SelectObject(pOldPen); } 步骤9:组装。到目前为止,时钟的各个部件都已经设计完毕,现在该把它们组装起来了。刚才建立的4个类CClockBackground、CClockHourHand、CClockMinHand、CClockSecHand要为CClockEx服务,正如CClockElement为它们服务一样,不过服务的方式发生了变化,刚才是以继承的方式使用,现在需要将上面4个类实例化供CClockEx使用。因此,首先应该在类CClockEx为上4个类分别建立对象。 在CClockEx的头文件中恰当位置加入以下代码: #include "ClockBackground.h" #include "ClockHourHand.h" #include "ClockMinHand.h" #include "ClockSecHand.h" class CClockEx : public CStatic { private: CClockBackground m_clockBK; //时钟背景 CClockHourHand m_clockHour; //时指针 CClockMinHand m_clockMin; //分指针 CClockSecHand m_clockSec ; //秒指针为了存储绘图区域的大小,需要在CClockEx中加入一个变量m_rcClient: CRect m_rcClient; //客户区域 在PreSubclassWindow函数中进行时钟的初始化工作。首先得为各个部件设定区域大小;然后启动定时刷新的定时器(100毫秒的定时器已经足够)。由于每个部件都有自己的默认颜色配置,因此这里暂且先使用默认配置,当然也可以自定义颜色: GetClientRect(m_rcClient); //获取当前客户区域 m_clockBK.SetRegion(m_rcClient); m_clockHour.SetRegion(m_rcClient); m_clockMin.SetRegion(m_rcClient); m_clockSec.SetRegion(m_rcClient); SetTimer(1, 100, NULL); //每100毫秒刷新一次 当控件大小发生变化时,控件状态要能够自动更新: void CClockEx::OnSize(UINT nType, int cx, int cy) { CStatic::OnSize(nType, cx, cy); GetClientRect(m_rcClient); m_clockBK.SetRegion(m_rcClient); m_clockHour.SetRegion(m_rcClient); m_clockMin.SetRegion(m_rcClient); m_clockSec.SetRegion(m_rcClient); } 每个定时器时间触发时,需要刷新控件以保证时钟的走动: void CClockEx::OnTimer(UINT nIDEvent) { Invalidate(FALSE); CStatic::OnTimer(nIDEvent); } 实现时钟的绘制下面实现时钟的绘制,由于控件在不断刷新,按一般方式绘图,屏幕会不断闪烁,因此此处使用双缓冲绘图——就是在内存中绘图,绘制完毕时再Copy到屏幕上,这样可以有效的防止屏幕闪烁: void CClockEx::OnPaint() { CPaintDC dc(this); // device context for painting //实现双缓冲绘图——防止屏幕闪烁 CDC dcMem; //建立一个和pDC兼容的内存DC: dcMem dcMem.CreateCompatibleDC(&dc); CBitmap bmp; //建立一个位图对象,其宽度和高度用当前绘图区的 bmp.CreateCompatibleBitmap(&dc, m_rcClient.Width(), m_rcClient.Height() ); dcMem.SelectObject(&bmp); //将bmp选入到dcMem中 DrawClock(&dcMem); //绘制时钟 dc.BitBlt(0, 0, m_rcClient.Width(), m_rcClient.Height(), &dcMem, 0, 0, SRCCOPY); //将dcMem中的图拷贝到pDC上进行显示。 } DrawClock的函数实现:将绘图函数放在一个单独的函数DrawClock中。并写入到文件CLOCKYS.cpp 中,另外,在ClockEx.h的头文件中添加函数声明如下图所示。 // CLOCKYS.cpp void CClockEx::DrawClock(CDC *pDC) { CTime tmCur = CTime::GetCurrentTime(); m_clockBK.SetTime(tmCur); m_clockHour.SetTime(tmCur); m_clockMin.SetTime(tmCur); m_clockSec.SetTime(tmCur); m_clockBK.Draw(pDC); m_clockMin.Draw(pDC); m_clockHour.Draw(pDC); m_clockSec.Draw(pDC); } 步骤5:添加Static控件打开资源编辑器,在对话框中拖入一个Static控件,调整外观至合适,将其ID改为IDC_CLOCK。如图效果所示:测试看时钟的实现效果。步骤6: 为IDC_CLOCK控件映射变量打开Class Wizard,为IDC_CLOCK映射一个变量,变量类型为CClockEx。如下图效果所示:步骤7: 编译执行在对话框类的头文件中加入头文件: #include "ClockEx.h"。程序代码基本编写完毕。编译整个工程,执行可执行程序,就可以看到整个时钟控件的效果图了。实例5——简易计算器程序 基本步骤:创建工程MyCal(Calculator)及可视化设计为控件编辑ID 为控件(IDC_0 , IDC_1 ……)插入消息映射及函数为编辑框添加成员变量m_result 对主要成员函数编写代码步骤1:创建工程并进行可视化设计 创建工程(基本对话框) MyCal(工程名)可视化设计(计算器界面设计)添加控件添加计算器中的数字、运算符等按钮和数字显示编辑框,如右图。控件的两个要素 ID标识符 Caption文本编辑框 IDC_DISPLAY 用于显示数据输入输出步骤2:为控件编辑ID 步骤3:为控件插入消息映射及函数进入ClassWizard界面选择Message Maps为控件插入消息映射及消息函数,实现控件命令功能。右键单击控件“0”,选择“建立类向导”,单击“ADD Function”按钮,如图所示,输入成员函数名,单击“OK”按钮;单击“Edit code”按钮,直接进入函数体编辑,如图所示。其他控件操作类似注意:编辑控件(IDC_DISPLAY)不要插入消息映射及函数步骤4:为编辑框添加成员变量m_result 进入ClassWizard界面Message Varibles为编辑框IDC_DISPLAY添加成员变量m_result用以显示结果。如图:步骤5:对主要成员函数编写代码在MyCalDlg.h中加入主要成员函数和成员变量的申明在MyCalDlg.cpp中加入主要成员函数实现过程和成员变量的初始化代码片段后面介绍步骤5续:对头文件MyCalDlg.h编写代码 //在头文件中手动添加成员函数与成员变量声明 // MyCalDlg.h : header file //定义两个euum枚举类型Operator, CalcError结构 enum Operator { OpNone, OpAdd, OpSubtract, OpMultiply, OpDivide }; enum CalcError { ErrNone, ErrDivideByZero }; double m_operand; //存储当前输入的操作数 double m_accum; //存储当前的计算处理结束 BOOL m_bCoff; //标识当前输入是否是小数 double m_coff; //小数输入时的系数 Operator m_operator; //定义 枚举变量 m_operator 用以标识当前运算符 CalcError m_errorState; // 定义 枚举 变量m_errorState 用以标识当前运算状态 BOOL m_bOperandAvail; //标识当前输入是否是新输入数字 void UpdateDisplay(); //成员函数处理显示 void Calculate(); //成员函数处理计算 void OnOperandInput(int a); //成员函数处理数字输入 步骤5续:对原文件MyCalDlg.cpp编写代码 //在执行文件中添加成员函数实现部分与变量初始 // MyCaDlg.cpp : implementation file #include “math.h“ //需使用平方根函数,所以要添加此头文件 //以下是对声明变量进行初始化 MyCalDlg::MyCalDlg(CWnd* pParent /*=NULL*/) : CDialog(MyCalDlg::IDD, pParent) { //{{AFX_DATA_INIT(CCaaDlg) m_result = _T(“”); //默认为m_result变量初始化 //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 //m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_coff=0.1; //为变量进行初始化 m_bCoff=0; //为变量进行初始化 m_errorState = ErrNone; //为变量进行初始化 m_bOperandAvail=FALSE; //为变量进行初始化 m_operator=OpNone; //为变量进行初始化 } 步骤5续:对控件0~9编写代码 //以下是消息处理函数,用以响应消息映射 void CMyCalDlg ::On0() //处理“ 0”按钮 { // TODO: Add your control notification handler code here OnOperandInput(0); } void CMyCalDlg::On1() //处理“ 1”按钮 // TODO: Add your control notification handler code here OnOperandInput(1); } 注意:处理“0~9”按钮的代码都类同。方法为:进入类向导中,单击“Edit code”按钮,直接进入函数体编辑或手动进入 (MyCalDlg.cpp : implementation file)编辑步骤5续:对控件“*,/,+” 编写代码 void CMyCalDlg ::Oncheng() //处理“ *”按钮 { // TODO: Add your control notification handler code here Calculate(); m_operator = OpMultiply; } void CMyCalDlg ::Onchu() //处理“ /”按钮 { // TODO: Add your control notification handler code here Calculate(); m_operator = OpDivide; } void CMyCalDlg ::Onjia() //处理“ +”按钮 { // TODO: Add your control notification handler code here Calculate(); m_operator = OpAdd; } 步骤5续:对控件“=, .” 编写代码 void CMyCalDlg ::Ondengyu() //处理“ =”按钮 { // TODO: Add your control notification handler code here Calculate(); m_operator = OpNone; //无任何操作 } void CMyCalDlg ::Ondian() //处理“ .”按钮 { // TODO: Add your control notification handler code here m_bCoff=1; UpdateDisplay(); } 步骤5续:对控件“-, X*X, sqrt,” 编写代码 void CMyCalDlg ::Onjian() //处理“ -”按钮 { // TODO: Add your control notification handler code here Calculate(); m_operator = OpSubtract; } void CMyCalDlg ::Onpingfang() //处理“ x*x”按钮 { // TODO: Add your control notification handler code here m_operand*=m_operand; UpdateDisplay(); } void CMyCalDlg ::Onsqrt() //处理“ sqrt”按钮 { // TODO: Add your control notification handler code here m_operand=sqrt(m_operand); UpdateDisplay(); } 步骤5续:对控件“+/-,CE” 编写代码 void CMyCalDlg ::Onzhengfu() //处理“ +/-”按钮 { // TODO: Add your control notification handler code here m_operand*=-1; UpdateDisplay(); //成员函数处理显示(代码在后面定义) } void CMyCalDlg ::Onqinglin() //处理“ CE”按钮 { // TODO: Add your control notification handler code here m_operator = OpNone; //无操作符 m_operand = 0; m_accum = 0; m_bOperandAvail = FALSE; m_errorState = ErrNone; //无错误 m_coff=0.1; m_bCoff=0; UpdateDisplay(); } 步骤5续:编写自定义函数(实现计算) //以下是自定义函数,用于实现计算功能,在MyCalDlg.cpp编写代码 void CMyCalDlg ::OnOperandInput(int a) //处理0-9 数字的输入函数 { if (m_errorState != ErrNone) //判断当前运算是否有误,若有则返回 return; if (!m_bOperandAvail) //判断是否输入新的数字,1-是 0-否 m_operand = 0; if(!m_bCoff) //判断是否是小数输入,1-是 0-否 m_operand=m_operand*10+(a); else { m_operand=m_operand+(a)*m_coff; m_coff*=0.1; } m_bOperandAvail=TRUE; UpdateDisplay(); //更新显示 } 步骤5续:编写处理计算函数 //处理计算函数 void CMyCalDlg ::Calculate() { if (m_errorState != ErrNone) return; if (m_bOperandAvail) { //如果没有计算符就将m_operand值 //赋予m_accum if (m_operator == OpNone) m_accum = m_operand; else if (m_operator == OpMultiply) //否则按计算符进行计算 m_accum *= m_operand; else if (m_operator == OpDivide) { if (m_operand == 0) m_errorState = ErrDivideByZero; else m_accum /= m_operand; } else if (m_operator == OpAdd) m_accum += m_operand; else if (m_operator == OpSubtract) m_accum -= m_operand; } m_bOperandAvail = FALSE; m_bCoff=0; m_coff=0.1; UpdateDisplay(); } 步骤5续:编写处理显示函数 void CMyCalDlg ::UpdateDisplay() //处理显示函数 { if (GetSafeHwnd() == NULL) return; if (m_errorState != ErrNone) m_result="除数不能为零"; else //如果当前计算无错误那么进行显示 { //如果是输入计算数,那么显示输入情况,如果按下计算符,则显示结果 float lVal = (m_bOperandAvail) ? m_operand : m_accum; m_result.Format(_T("%f"), lVal); //将float型转化为CString型 int i=m_result.GetLength(); while(m_result.GetAt(i-1)=='0') { m_result.Delete(i-1,1); i-=1; } } //用编辑控件变量m_result改变编辑控件的值,更新显示 UpdateData(FALSE); } 步骤6:技术要点——UpdateData函数 UpdateData函数是CDialog的基类CWnd的成员函数; ①函数原型如下: BOOL UpdateData( BOOL bSaveAndValidate = TRUE ); ②一般在对话框的派生类中,利用UpdateData函数进行控件和相应变量之间的数据传递,形式如下: UpdateData(TRUE); //将控件中的数据传递给相应的变量 UpdateData(FALSE) //将变量中的数据传递给相应的控件,即显示 步骤7:优化计算器程序——使用宏用一个消息处理函数来处理对某个ID范围内所有控件的命令响应,该宏的原型为: ON_COMMAND_RANGE(ID1,ID2, memberFxn); 其中 ID1是控件ID的起始值; ID2是控件ID的结束值; memberFxn为消息响应函数。用OnOperandInput处理数字按钮“0”〜“9”的消息响应函数的方法是: (1)手工添加函数声明,也就是在MyCalculatorDlg.h中“{{AFX_MSG(CMyCalculatorDlg)”与“}}AFX_MSG”之间,添加下面的语句: afx_msg void OnOperandInput(UINT nID); (2) 在MyCalculatorDlg.cpp文件中 “{{AFX_MSG_MAP(CMyCalculatorDlg)”与“}}AFX_MSG_MAP”之间,加入语句: ON_COMMAND_RANGE(IDC_BUTTON0,IDC_BUTTON9, OnOperandInput); 实例6——调用自定义对话框编写在文档区单击左键,则弹出输入成绩对话框,选择OK后,平均成绩和总分在文档窗口的客户区输出。创建步骤:创建应用程序框架(基于单文档);设计自定义对话框;创建对话框类;编辑自定义对话框;调用对话框类。步骤1:创建应用程序框架(基于单文档)(1)用类向导生成SDI应用程创建工程TEST_SDI(单击“文件/新建”命令,…选定“单文档(S)”,单击“完成”按钮)。(2)系统生成的框架如下图:创建程序框架工作结束,运行此应用程序结果如右图。步骤2:设计自定义对话框(1)选择“插入/资源”命令;(2)在弹出“插入资源”对话框中,选定“Dialog”,然后选择“新建”;(3)在资源视图中展开Dialog,可以看到新增了ID为IDD_DIALOG1的资源,双击该ID,则在窗口中间显示对话框设计界面(在此进行可视化设计,如右图所示);(4)测试对话框,即选择“布局/测试”命令测试对话框,若符合要求,则对话框设计完成。步骤3:创建对话框类(1)双击对话框设计界面,选择“建立类向导”,则弹出“Adding a Class”对话框; (2)选择“Create a new class”,单击“ok”按钮;(3)在“New Class”对话框中输入对话框类名:CInput,如图所示,对话框类创建完成。步骤4:编辑自定义对话框(1)为对话框中的5个编辑框连接到CSting类型的变量。(2)设置相关属性。步骤5:调用对话框(1)在视图类的实现文件TEST_SDIView.cpp中添加类头文件的包含命令: #include "Input.h" (2)在文档类(TEST_SDIDoc)中添加一个公有的数据成员total,用于存放总分。 Public: double total; 步骤5续:调用对话框_对对象进行初始化在CTEST_SDIDoc.cpp文件中对文档类对象Total进行初始化: total=0; 步骤5续:调用对话框——编写按压左键函数 OnLButtonDown()函数 void CTEST_SDIView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CTEST_SDIDoc* pDoc=GetDocument(); CInput dlg; //说明自定义对话框对象dlg if(dlg.DoModal()==IDOK) // dlg.DoModal()显示对话框,并单击OK按钮后 { pDoc->total =atoi(dlg.m_hx )+atoi(dlg.m_sx )+atoi(dlg.m_wl) +atoi(dlg.m_yw) +atoi(dlg.m_yy) ; Invalidate(); //使对话框无效 } CView::OnLButtonDown(nFlags, point); } 注意:atoi()函数是将字符串转为整型。步骤5续:调用对话框——编写显示函数 OnDraw()函数 void CTEST_SDIView::OnDraw(CDC* pDC) //OnDraw()是实现输出的关键函数 //参数pDC指向窗口中央的客户区对象 { //说明pDoC为一个指向CTEST_SDIDoc类对象的指针 CTEST_SDIDoc * pDoc = GetDocument(); //获得指向文档类对象的指针 ASSERT_VALID(pDoc); //检查pDoc是否有效,若有效,则结束程序 // TODO: add draw code for native data here CString str; //构造对象str if (pDoc->total !=-1) { str.Format ("平均成绩:%.2f",pDoc->total /5); pDC->TextOut (50,10,str); str.Format ("总 分:%.2f",pDoc->total ); pDC->TextOut (50,30,str); //TextOut()函数用于输出文字 } } 注意:添加一个消息处理,一般要改动3个地方,以WM_LBUTTONDOWN消息为例, ①在视图类的定义(test1View.h)中添加一个成员函数, ②在视图类(test1View.cpp)中添加一条消息映射, ③在视图类(test1View.cpp)中实现消息处理的成员函数。操作方法在“类视图”中选中“Ctest1View”,再在“属性”工具中选择“WM_LBUTTONDOWN”消息,同时选上“OnLButtonDown”后回车就可以。 实例7 ——数据库编程一般分为3个步骤:(1)利用ODBC数据源管理器配置与数据库对应的数据源(2)利用MFC AppWizard应用程序向导生成数据库应用程序框架(3)根据需要对框架添加具体的源代码 步骤1:利用ODBC数据源管理器 ODBC的相关概念 数据库访问技术 步骤1续:利用ODBC数据源管理器 ODBC的相关概念 MFC ODBC MFC 的 ODBC 类对较复杂的 ODBC API 进行了封装, 提供简化的调用接口, 方便数据库应用程序的开发。 MFC 的 ODBC 类主要包括: CDatabase 类针对某个数据库,负责连接数据源 CRecordset 类针对数据源中的记录集, 负责对记录的操作 CRecordView 类负责界面 CFieldExchange 类支持记录字段数据交换(DFX) CDBException 类代表ODBC 类产生的异常(Exception) 步骤1续:利用ODBC数据源管理器 ODBC的相关概念 ODBC组成部件: 步骤1续:利用ODBC数据源管理器配置与数据库对应的数据源单击“开始/控制面板/管理工”,打开“管理工具”窗口,双击图标在弹出的对话框中选择“用户DSN”选项卡,单击“添加”按钮,从弹出的对话框中选中“Microsoft Access Driver(*.mdb)”;单击“完成”后,将弹出一个新的对话框,在数据源名编辑框中填入 “student” ; 连接成功后画面如图所示. 步骤2:使用MFC AppWizard向导应用向导MFC AppWizard(exe) 制作程序框架的步骤:第一步:选择程序类型单文档应用程序SDI(一次只允许打开一个文档)多文档应用程序MDI(允许同时打开多个文档)基于对话框的应用程序(不支持文档/视图结构,简单对话框)第二步:程序对数据库的支持选择应用程序所需的数据库支持(4选项)、默认None(不需要) 第三步:程序对OLE和ActiveX控件的支持第四步:程序外观和对通信的支持第五步:程序的风格、代码加注释、链接库设置第六步:选择视类的基类步骤2续:利用MFC AppWizard向导创建数据库应用程序(EX88)框架设置工程属性(1)设置应用程序为单个文档模式选中“文档/查看结构体系支柱”复选框 步骤2续:利用MFC AppWizard向导设置工程属性(2)选择“数据库查看使用文件支持”单选框在“Datasouce”区域中选择ODBC单选框,选择数据源;在Recordeset Type区域中选择Dynaset单选框(动态集)(3)取消选择“ActiveX”复选框(4)取消选择“打印和打印预览”复选框(5)按向导提示做完 步骤2续:利用MFC AppWizard向导应用程序的主画面步骤3:调试和编辑框架运行效果根据需要对框架添加具体的源代码 二、学生基本信息管理系统 ——MFC创建该应用程序实例步骤1:确定应用程序的基本类型单文档应用程序类型使用ODBC建立数据连接记录集为“动态集” 步骤2:使用MFC创建应用程序界面创建工程EX01DB 设置工程EX01DB属性(1)设置应用程序为单个文档模式,选中“文档/查看结构体系支柱”复选框(2)选择“数据库查看使用文件支持”单选框,在“Datasouce”区域中选择ODBC单选框,选择数据源;在Recordeset Type区域中选择Dynaset单选框(动态集)(3)取消选择“ActiveX”复选框(4)取消选择“打印和打印预览”复选框步骤2:使用MFC创建应用程序界面此时在程序中自行生成一个数据源和数据源中的一个表的相关程序,其程序清单如图: class CEx88Set : public CRecordset //基于CRecordset的CEx88Set新类 说明:MFC生成的应用程序界面运行效果 MFC创建应用程序EX01DB的框架解释左窗格中包含的内容类视图面板(系统产生6个基类)对话框类应用程序类文档类记录集类视图类框架窗口类 Globals 存放的全局变量 theApp 说明:使用MFC创建应用程序界面 MFC创建应用程序EX01DB的框架解释资源视图面板(7个文件夹) Accelerator(加速器) 包含模拟菜单和工具栏选择的键定义 Dialog(对话框) 包括对话框的样式和内容EX01DB中只有ABOUT对话框 Icon(图标) 描绘图标(16x16象素和32x32象素) Menu(菜单) 描绘为应用程序的顶级菜单和关连的快捷菜单 String table(字符串表) 包含字符串但不包括C++源代码的部分 Toolbar(工具栏) 描述为直接在菜单下的一行按钮 Version(版本信息) 包括程序说明,版本号,语言等等说明:使用MFC创建应用程序界面 MFC创建应用程序EX01DB的框架解释文件视图面板源文件夹头文件夹资源文件夹 步骤3:实现程序的显示记录的功能在对话框编辑器中(如左图)设计自己的窗体。 CRecordView应用程序围绕着充当应用程序主窗口的对话框而创建。设计象窗体一样的对话框来显示存储在student数据库记录域中的值。如图所示来放置静态文本框与编辑文本框。步骤3:实现程序的显示记录的功能为了实现数据传输,把每个控件与代表数据库域的CEX88Set变量联系起来单击“查看/建立类向导”菜单命令,在弹出的“MFC ClassWizard ”对话框中选择成员变量选项卡;单击“Add Variable按钮”,从下拉表中直接选择相应的成员变量名;全部设置好之后单击“OK”。运行应用程序 4.建立应用程序主窗口标题方法一: 利用ResourceView打开工程的资源,修改String Table中的IDR_MAINFRAME的值。 4.建立应用程序主窗口标题一个学生信息管理系统。用的是MFC ODBC来完成的。在成绩管理系统中,当查询到记录后要刷新,使所有的记录从新显示出来的话,如果系统中存在7000条记录的话,刷新一次的时间要20多秒钟,处理后,可以在用户查询后,在不到一秒中的时间内来完成刷新。另:用户名:good,密码:py-a 4.建立应用程序主窗口标题方法二:改变CSDIMainFrame的成员函数PreCreateWindow()为: 5.更改单文档应用程序标题再app类中的InitInstance()函数中添加下面的语句 m_pMainWnd->SetWindowText( "学生信息管理系统"); 6.更改MFC创建应用程序系统图标插入想要的图标将系统生成的图标的名字复制,再删除将自己插入的图标更名为系统定义的名字即可 7.在单文档界面上添加控件并建立关联编辑框控件成员变量命令按钮建立类向导 7.在单文档界面上添加控件并建立关联系统自动生成 结束!谢谢! ClassView类视图 ClassView(类视图):显示项目中定义的C++类图标的含义: ResourceView资源视图 ResourceView(资源视图) 内容显示项目中所包含的资源文件。作用管理所有:菜单、图标、光标、图片、对话框等资源。 FileView文件视图——显示所创建的工程 主框架窗口类的源文件标准Afx(全局)源文件 App(应用程序)类的源文件应用程序的资源文件用户文档类的源文件用户视图类的源文件 与上述文件一一对应的头文件 是你的工程要用到的头文件 1.简单应用程序实例——对话框程序例1:编写如图所示的应用程序。创建步骤:建立基于对话框的MFC应用程序框架;放置控件;设置控件属性;为控件连接变量,即为控件命名;添加并且编写消息处理函数。步骤1:建立基于对话框的MFC应用程序框架单击“文件/新建”命令;在“工程”选项卡中,选定“MFC AppWizard(exe)”,输入工程名称TEST,单击“确定”按钮;选定“基本对话框(D)”,即创建基于对话框的应用程序,单击“完成”按钮;在随后弹出的对话框中显示了工程汇总信息,单击“确定”按钮。创建程序框架工作结束,Developer Studio(开发者工作室)窗口如图所示。步骤2:放置控件先删除原有控件然后放置本例所需要的控件放置控件的方法单击控件工具栏上的控件图标,选择所需的控件,然后在对话框设计界面上按住鼠标左键拖拉出所需要的大小后释放。步骤3:设置控件属性命令按钮属性设置(1)设置IDcopy属性(2)设置IDend属性编辑框IDC_EDIT1的属性设置为:(1)选定“多行”复选框,编辑框中可以输入多行文本;(2)选定“垂直滚动”和“水平滚动”,编辑框将有垂直滚动条;(3)选定“需要返回”。用同样的方法设置编辑框IDC_EDIT2的属性步骤4:连接变量即给每一个对象连接一个变量(此变量将成为类中的一个数据成员)。(1)为IDC_EDIT1连接变量m_e1 在IDC_EDIT1编辑框的快捷菜单中选择“建立类向导”(如右图);在“Member Variables”选项卡中,选定“IDC_EDIT1”,再选择”Add Variable”命令;在图中所示的“Add Member Variable”对话框中输入以下数据: Member Variable name(成员变量名):m_e1; Category(类别):Control; Variable type(类型):CEdit (2)用同样的方法为IDC_EDIT2连接变量m_e2 步骤5:添加并且编写消息处理函数在程序运行时,在“复制”按钮上发生单击事件后,Windows向对话框发出一个BN_CLICKED消息,CTESTDlg类应有一个处理的函数。(1)双击“复制”按钮,在“Add Member Function”对话框中输入函数名(缺省函数名为OnButton1),单击“OK”按钮后,添加一个空函数。(或用类向导建立)步骤5续: (2)为void CTESTDlg::OnButton1() 添加代码: (3)为void CTESTDlg::OnButton2() 添加代码: 对话框中的属性中的字体大小的设置 1.改静态文体的ID:IDC_STATIC1 2.在OnInitDialog中添加如下代码: CFont * f; f = new CFont; f->CreateFont(16, // nHeight 0, // nWidth 0, // nEscapement 0, // nOrientation FW_BOLD, // nWeight TRUE, //是否斜体,布尔值 FALSE, // bUnderline 0, // cStrikeOut ANSI_CHARSET, // nCharSet OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily _T("Arial")); // lpszFac GetDlgItem(IDC_S)->SetFont(f); 关闭对话框 void CT1Dlg::OnB1() { // TODO: Add your control notification handler code here EndDialog(IDC_B1); //关闭对话框 CInput dlg; //定义对话框对象dlg dlg.DoModal(); }Esm红软基地