第一个MFC实例:计算圆周长和圆面积
一、基于Microsoft MFC的编程方法
MFC是微软基础类库(Microsoft Foundation Class)的缩写。与API不同,MFC不是Windows操作系统的组成部分,而是微软公司专为VC++开发的配套软件包。与VC6配套的是MFC6.0。MFC充分使用了面向对象方法中的继承和多态性技术,以类的方式封装了Windows应用程序所涉及的几乎所有的标准部件,如Windows应用程序的架构、各种标准的图形界面元素、其核心是它以C++的形式封装了Windows API的大部分函数。
MFC是一个很大的类层次体系(MFC6.0中包含了200多个类),它由一个称为CObject的类作为根基类,其他类大部分从该类派生而来,其整个类体系可大致划分为:
■基类
■应用程序框架类。 包括:应用程序类、命令类、文档/视窗类、框架窗口类、文档模板类等
■可视对象类。 包括:窗口类、对话框类、控件类等
■绘图类。 包括:绘图工具类、设备描述表类等。
■简单数据类型类
■通用类 包括:数组类、类表类、映像类
■文件和数据库类 包括:文件I/O类、ODBC类、ADO类
■Internet和网络工作类 包括:Win32 Internet类、Windows Socket类等
■对象链接和嵌入(OLE, Object Lingking and Embedding)类
■调试和异常类
事实上,MFC封装了一个Windows应用程序操作的每一方面,因此使用MFC编程,编程者可以把注意力集中于自己程序所特有的部分,不需要事事亲自动手。与直接调用API函数相比,这将大大减少编程者编写的代码数量,使编程工作变得更容易;同时,程序标准部分由MFC的类来提供,可使程序变得更规范,更具可读性,效率也更高。
二、实例讲解
闲话不多扯,下面说下这个实例怎么用VC++实现。我用的编译器是vc++6.0。
首先知道步骤:
开发一个MFC项目通常有四个步骤:
Step.1 建立项目架构
Step.2 设计图形用户界面
Step.3 设计对象的事件驱动程序
Step.4 项目的编译、链接和运行
第一步呢,建立项目架构,如图:


后面一系列默认步骤,最后出现:


下面便到了第二步,设计用户图形界面,就是玩玩控件。
可在对话框上建立(拖拽)如下控件:
■1个编辑框:用于用户输入半径值;
■5个静态文本框(静态文本框只能显示文本而不能输入文本),其中:2个静态文本框分别用于显示圆周长和圆面积,其余3个静态文本框分别用于对上述三个文本框进行文字说明。
■2个命令按钮,“确定”和“退出”: 前者用于确定输入值,计算圆周长和圆面积,然后把结果显示在对应的输出框上;后者用于结束程序的执行。
如下图:

进行控件属性设置(即鼠标选中控件右键单击,点属性):
1.主窗口:将标题值设置为“计算圆周长和圆面积”,其他默认。
2.编辑框:ID默认为:IDC_EDIT1。在“样式”(Styles)选项卡中设置相关属性值为:“靠左”(Left)。其余属性采用默认值。
3.静态文本框:
ID 标题 其他属性
---------------------------------------------------------------------------------
IDC_STATIC1 输入半径 居中,垂直居中
IDC_STATIC2 圆周长 居中,垂直居中
IDC_STATIC3 圆面积 居中,垂直居中
IDC_STATIC4 默认 靠左,垂直居中,Client edge
IDC_STATIC5 默认 靠左,垂直居中,Client edge
4.按钮:
ID 标题
---------------------------------------
IDC_BUTTON1 确定
IDC_BUTTON2 退出
现在便到了第三步,设计对象的事件驱动程序。
这里说点知识。对象的事件驱动程序在VC++中称为消息处理成员函数。
在实际应用中,读取或更新控件上的数据是对话框的非常重要的工作。MFC为此提供了一套标准方法:DDX(Data Exchange,数据交换)和DDV(Data Validation,数据校验)技术。DDX通过成员变量(member variable)的方式实现对话框与控件之间的数据传递。如果要在对话框的消息处理函数中访问控件上的数据,就必须先在对话框类(CCase1Dlg类)中分别为这些控件添加(声明)一个成员变量,每一个成员变量绑定一个控件。在消息处理函数中是通过成员变量访问控件的。
成员变量是对话框的public数据成员。有两类成员变量:
■Value类成员变量:表示该变量的值为控件的数据。
■Control类成员变量:表示该成员变量就代表控件本身,即它是控件的一个对象,其值实际上就是控件的句柄。
句柄是什么?
Visual Studio系统给每个对象分配一个句柄(handle),它是一个4字节长的整数值,是对象的唯一内部编号。应用程序通过句柄访问相应的对象。每个对象除了句柄外,还有一个对象标识符ID,可看作是对象的外部名。ID与句柄的区别主要在于:ID可以是用户自行设定的;而句柄是系统内定的,对用户是透明的,这能防止应用程序直接访问对象的内部信息。
DDV用于数据的校验,例如自动校验字符串的长度和取值范围。
使用MFC DDX/DDV的流程是:
①首先定义用于接收控件数据的成员变量。例如,为编辑框IDC_EDIT1定义一个Value类的double型的成员变量,用于接收用户输入的半径值。定义变量的同时可以设定数据取值范围,提供校验。
②然后,在对应的消息处理成员函数中调用MFC函数传递数据。最简单的相关MFC函数有:
UpdateData() //更新成员变量,将控件上的数据传递给成员变量
UpdateData(FALSE) //更新控件,将成员变量的值传递给控件
对于本实例,可设计如下成员变量和消息处理函数:
■为编辑框IDC_EDIT1定义一个double型的成员变量m_r,用于接收用户在编辑框中输入的半径值;
■为静态文本框IDC_STATIC4和IDC_STATIC5分别定义一个Cstring型成员变量m_girth和m_area用于向静态文本框传递计算结果。静态文本框只能处理Cstring(字符串)型数据。
注意:成员变量名的前缀“m_”是MFC的风格。MFC也有自己的数据类型,不过与C++很相似,容易理解。
■为“确定”按钮建立一个“单击”(BN_CLICKED)消息处理函数,用于计算圆周长和圆面积,并显示计算结果。
■为“退出”按钮建立一个“单击”消息处理函数,用于结束程序的运行。
■建立一个对话框的初始化函数,对成员变量m_r、m_girth、m_area进行初始化。
操作步骤:
(1)添加成员变量
打开“MFC Class Wizard”(类向导)对话框。方法可以是:从VC6窗口的菜单栏上的“查看”菜单中选择“建立类向导”选项,或者用鼠标右击窗体,从弹出的快捷菜单中选择“建立类向导”,或者按快捷键Ctrl+W。选择“Member Variables”(成员变量)选项卡。从“Control IDs”(控件ID)列表框中,可以看到已经建立的各控件对象的ID。
为编辑框添加成员变量:选择IDC_EDIT1,单击右边的“Add Variable…”(添加变量)按钮,弹出“添加成员变量”对话框。
在第一个文本框(Member variable name)中输入成员变量名,如m_r;在第二个下拉框(Category)中选择成员变量的种类,Value;在第三个下拉框(Variable Type)中选择成员变量的数据类型,double。单击OK按钮。回到“Member Variables”选项卡,设置变量m_r的取值范围,如最小值为0,最大值为1000.0。用同样的方法为静态文本框IDC_STATIC4和IDC_STATIC5添加Cstring型成员变量m_girth和m_area,最大字符个数为10。
看下图:

(2)编写消息处理成员函数
①主窗口的初始化函数
切换到类向导的“Message Map”(消息映射)选项卡。在“Object IDs”(对象名)列表框中选择主窗口的对象名CCase1Dlg;在“Messages”(消息)列表框中选择消息WM_INITDIALOG;此时在“Member functions”(成员函数)列表框中会自动指出相应的MFC已定义的虚函数OnInitDialog(主窗口对象是由MFC默认生成的)。
单击“Edit Code”(编辑代码)按钮,弹出Case1Dlg.cpp文件的编辑窗口,并显示OnInitDialog()函数的代码清单,找到注释提示处:
// TODO: Add extra initialization here
(在此下边添加你初始化的代码)
对于本实例,可添加如下代码:
m_r =0.0;
m_girth=m_area="0.000";
UpdateData(FALSE); //将数据传给控件并显示
即:
BOOL CCase1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
……………
// TODO: Add extra initialization here
m_r =0.0;
m_girth=m_area="0.000";
UpdateData(FALSE); //将数据传给控件并显示
return TRUE;
// return TRUE unless you set the focus to a control
}
②“确定”按钮的消息处理函数
类似上述方法,在“Object IDs”列表框中选择IDC_BUTTON1;在“Messages”列表框中选择消息BN_CLICKED;单击“Add Function”(添加函数)按钮,此时在“Member functions”列表框中会出现一个新的函数名OnButton1,表示系统为该对话框生成了一个新成员函数(图21);单击“Edit Code”(编辑代码)按钮,弹出Case1Dlg.cpp文件的编辑窗口,并显示OnButton1()函数的代码清单,找到注释提示处:
// TODO: Add your control notification handler code here
(在此下边添加控件消息的处理代码)
对于本实例,可添加如下代码:
UpdateData(); //将编辑框的数据传递给成员变量
double girth=*3.1416*m_r; //计算圆周长
double area=3.1416*m_r*m_r; //计算圆面积
m_girth.Format(“%10.3f”,girth); //按格式写入成员变量
m_area.Format("%10.3f",area);
UpdateDtata(FALSE); //将数据传给控件并显示
注:函数Fornat()是CString类的成员函数,用来把数据转换成CString类型的字符串。
③“退出”按钮的消息处理函数
按上述方法,建立IDC_Button2的BN_CLICKED消息处理函数,并在注释提示处输入代码:
void CCase1Dlg::OnButton2()
{
// TODO: Add your control notification handler code here EndDialog(); //关闭对话框
}
下面进入最后一步,项目的编译、链接和运行。

第一个MFC实例:计算圆周长和圆面积的更多相关文章
- MFC 只启动一个程序实例
问题描述: 我们开发过程中可能会经常遇到,只启动一个程序实例.即一个程序启动之后,如果再次执行该程序,将会恢复之前打开的程序,而不是打开一个新的程序. 实现原理:利用FindWindow/FindWi ...
- MFC-01-Chapter01:Hello,MFC---1.3 第一个MFC程序(02)
1.3.1 应用程序对象 MFC应用程序的核心就是基于CWinApp类的应用程序对象,CWinApp提供了消息循环来检索消息并将消息调度给应用程序的窗口.当包含头文件<afxwin.h>, ...
- 如何让Windows程序只运行一个程序实例?
要实现VC++或者MFC只运行一个程序实例,一般采用互斥量来实现,即首先用互斥量封装一个只运行一个程序实例的函数接口: HANDLE hMutex = NULL; void MainDlg::RunS ...
- 我的第一个MFC的ArcGIS Engine程序
原文 http://blog.csdn.net/zzahkj/article/details/9003518 (第一版,以VC++6.0+AE9.3为例) 首次,学习MFC,写个笔记,MFC还是挺好学 ...
- Android NDK入门实例 计算斐波那契数列一生成jni头文件
最近要用到Android NDK,调用本地代码.就学了下Android NDK,顺便与大家分享.下面以一个具体的实例计算斐波那契数列,说明如何利用Android NDK,调用本地代码.以及比较本地代码 ...
- Socket TCP Server一个端口可以有多少个长连接?受到什么影响?linux最大文件句柄数量总结
Socket TCP Server一个端口可以有多少个长连接? 网上答案很多,不知道那个才是正确的 理论上是无限的 16.Linux中,一个端口能够接受tcp链接数量的理论上限是? A.1024 B. ...
- 【ZH奶酪】如何用Python计算最长公共子序列和最长公共子串
1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公共子序列(Longest-Common-Subseq ...
- C 语言实例 - 计算自然数的和
C 语言实例 - 计算自然数的和 自然数是指表示物体个数的数,即由0开始,,,,,,……一个接一个,组成一个无穷的集体,即指非负整数. 实例 - 使用 for #include <stdio.h ...
- 用Python计算最长公共子序列和最长公共子串
如何用Python计算最长公共子序列和最长公共子串 1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公 ...
随机推荐
- BZOJ4057 [Cerc2012]Kingdoms
题意 有一些王国陷入了一系列的经济危机.在很多年以前,他们私底下互相借了许多钱.现在,随着他们的负债被揭发,王国的崩溃不可避免地发生了--现在有n个王国,对于每对王国A和B,A欠B的钱被记为d_AB( ...
- testem方便的web tdd 测试框架使用
备注: 单元测试,对于日常的开发是比较重要的,testem 简化了我们的代码编写,以及运行. 主要特性: a. 支持的测试框架有:jasmine quint mocha buster ...
- Oracle12c之 CDB数据库中数据字典架构
数据字典就是元数据的集合,比如创建的表,列,约束,触发器等等这些都是元数据,需要保存到数据库中.除此之外,Oracle自身的一些数据库对象,如目录,PL/SQL代码等等这些都是元数据,都需要存放在数据 ...
- jieba分词初学
昨天,做的那个数据分析报告用到了jieba分词.但是只是借用了别人的部分代码.具体函数代表什么还不太明白.今天去官网研究了下..... jieba官网简介 "结巴"中文分词:做最好 ...
- Maven使用中的常见问题整理
1.更新eclipse的classpath加入新依赖 1.在dependencyManagement里面加入包括版本在内的依赖信息,如: <dependency> <groupId ...
- erlang异常处理备忘
捕获所有异常得用_:_,看例子 try aa:bb() of Value -> Value catch _:_ -> "" end 如果单表达式不需要有返回值,直接异常 ...
- cowboy的中间件
想不到cowboy这样的,居然也有中间件的概念,膜拜作者 创建工程 rebar-creator create-app testCowboy testCowboy_app.erl -module(tes ...
- C++中如何在顺序容器中删除符合特定条件的元素
以前很少做删除操作,vector一直当成数组用,而实际追求效率时又经常舍弃vector选用C风格数组.看<C++ Primer>到顺序容器删除这节时试着实现课后习题结果一动手我就出错了. ...
- jq from表单 取值
//获取表单参数 var DataDeal = { formToJson: function (id) { var data=$(id).serialize();//获取值 data = decode ...
- java代码FileInputStream的复制粘贴练习
所有的输入输出流都是对于程序来说的,这个图是实现文件内容的复制粘贴功能的e 首先把文件读到哦程序里,然后把程序读出到文件l package com.a.b; //这个复制和粘贴-----------首 ...