当前课程知识点:程序设计基础(下) > 拓展学习 > MFC入门 > MFC入门
MFC入门
利用MFC,程序员可以高效地开发出基于Windows操作系统的各种应用程序,如界面化应用程序、数据库应用程序、Web应用程序等。本章对MFC进行简要介绍,并通过几个实例讲解如何开发基于对话框的Windows应用程序。学习本章后,应了解MFC应用程序的开发过程。
1.认识MFC
1.1 什么是MFC
MFC是Microsoft Foundation Class Library的简称,即微软提供的基础类库。MFC定义了应用程序的框架,并提供了用户接口的标准实现方法,程序员所要做的工作就是通过预定义的接口把具体应用程序特有的代码填入这个框架。通过它,程序员可以高效地开发出基于Windows操作系统的各种应用程序。
1.2 MFC特性
MFC建立在C++的基础上,因此,它具备C++中类的特性。
(1)封装性
MFC为程序员提供了大量封装好的类,程序员利用MFC类库可以容易地编写界面化应用程序、数据库应用程序、Web应用程序等。
(2)继承性
MFC提供了很多类供程序员直接使用,但对于实际的应用程序,开发者通常要对MFC提供的类做一些修改,使其能够适应实际应用需求。通过类的继承性,程序员可以结合实际需要,从MFC类中派生出自己的类,实现特定的功能。
(3)多态性
程序员可以在派生类中重新实现基类中的函数,当调用函数时,系统会根据对象的实际类型执行正确的函数。
1.3 MFC应用程序类型
MFC应用程序分为单文档应用程序、多文档应用程序和基于对话框的应用程序。
(1)单文档应用程序
单文档应用程序只允许用户一次打开一个文档,比如,Windows操作系统提供的记事本就是一个单文档应用程序。
(2)多文档应用程序
多文档应用程序允许用户一次打开多个文档,比如,Microsoft Word就是一个多文档应用程序。
(3)基于对话框的应用程序
基于对话框的应用程序仅显示一个对话框,用户可以在对话框上输入信息。比如,在Microsoft Visual C++ 2010集成开发环境中选择Tools->Choose Toolbox Items菜单项,就会弹出一个对话框(如图1所示)。本书中只介绍如何编写基于对话框的应用程序,有兴趣的读者可以阅读专门讲解MFC编程的书籍学习单文档应用程序和多文档应用程序的编写方法。
图1 对话框示意图
2. 一个简单的MFC应用程序
开发一个MFC应用程序分为以下几个步骤:
(1)使用MFC向导生成一个基于对话框的应用程序框架;
(2)在对话框上添加控件并设置控件属性;
(3)根据需要创建控件变量;
(4)编写事件代码,当事件被触发时执行相应的功能;
(5)保存和运行程序。
下面以一个简单的MFC应用程序为例介绍开发的具体过程。
【例1】开发一个基于对话框的MFC应用程序,运行后的效果如图2所示:当点击显示按钮时,文本框中会显示“一个简单的MFC应用程序”;当点击清除按钮时,文本框中的内容会被清空;当点击关闭按钮时,会关闭对话框、结束应用程序运行。
图2 程序运行效果
2.1 使用MFC向导生成程序框架
具体步骤为:
(1)打开Microsoft Visual Studio 2010集成开发环境,选择File->New->Project菜单项,弹出如图3所示的New Project对话框。在对话框的Project types列表中选择MFC,在Templates列表框中选择MFC Application,并在Name和Location中填入要创建的项目名称和项目存储路径,点击OK。
(2)弹出如图4所示的MFC Application Wizard-Overview对话框,如果当前的项目设置(current project settings)符合要求,则直接点击Finish。否则,可以通过选择Next或在左面的列表中选择相应的选项进行设置。本例在左面列表中直接选择Application Type,弹出如图5所示的MFC Application Wizard-Application Type对话框,在Application Type单选按钮组中选择Dialog based,点击Finish。
(3)出现工作界面,在Resource View标签页中双击IDD_P19_1_DIALOG打开如图6所示的工作界面,在该界面上开始进行添加控件并设置控件属性的操作(提示:鼠标停在界面右侧的Toolbox上时,会出现图6右侧的控件工具栏)。
图3 新建对话框
图4 MFC Application Wizard-Overview对话框
图5 MFC Application Wizard-Application Type对话框
图6 工作界面
2.2 添加控件并设置控件属性
具体步骤为:
(1)添加控件:选择控件工具栏上的编辑框控件, 在对话框上按住鼠标左键并拖动, 在对话框上添加文本框控件;选择按钮控件, 在对话框上添加两个按钮;用鼠标选中对话框上的不需要的控件,按Delete键将其删除;调整对话框大小和控件的位置。添加控件后的对话框如图7所示。
(2)设置对话框和控件属性:用鼠标点击对话框空白处(即没有被其它控件覆盖的区域),工作界面右侧的Properties窗口中将Caption属性改为“一个简单的MFC应用程序”(如图8所示),此时可以观察到对话框左上角的标题发生相应更改;按照同样的方式,将Button1、Button2和取消3个按钮控件的Caption属性分别改为“显示”、“清除”和“关闭”。设置属性后的对话框如图9所示。
图7 添加控件后的对话框
图8 设置对话框的Caption属性
图9 设置属性后的对话框
2.3 创建控件变量
具体步骤为:
(1)选择View->ClassView菜单项,切换到ClassView视图。
(2)选择Project->Add Variable…,弹出如图10所示的添加成员变量对话框,添加CString型成员变量m_editText,点击Finish。此时,m_editText与编辑框控件建立了关联,可以直接通过m_editText获取或修改编辑框控件中的内容。
图10 添加成员变量对话框
2.4 编写事件代码
具体步骤为:
(1)用鼠标右键点击显示按钮控件,并在弹出的快捷菜单中选择Add Event Handler,出现如图11所示的对话框。
图11 添加事件对话框
(2)在Message type列表中选择BN_CLICKED(表示单击按钮消息),点击Add and Edit,进入事件代码编辑窗口,编写如下代码:
void Cp19_1Dlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
m_editText = "一个简单的MFC应用程序";
UpdateData(FALSE); // 将m_editText的值传递给编辑框控件
}
(4)按照同样的方法为清除按钮添加成员函数,并为其编写事件代码:
void Cp19_1Dlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
m_editText = "";
UpdateData(FALSE); // 将编辑框控件的值传递给m_editText
}
关闭按钮是创建对话框时系统自动生成的按钮,系统已经为其提供了默认的事件代码,因此不必为关闭按钮编写事件代码。
2.5 保存和运行程序
MFC应用程序保存和运行的方法与前面学习的控制台应用程序的方法完全一样。运行后就可以看到题目要求的效果。
3. 常用控件
本节仅简要介绍一些常用MFC控件,有兴趣的读者可以阅读专门讲解MFC编程的书籍学习其它MFC控件。每个控件都有一个唯一的ID值,系统根据ID区分不同的控件。
(1)标签控件
标签控件用于显示文本信息,但是不能输入信息。通过Caption属性可以更改标签控件上显示的文本信息。
(2)编辑框控件
编辑框控件是一个文本编辑区域,不仅可以显示文本信息,而且允许用户输入信息。
(3)列表框控件
列表框控件可以显示多个选项供用户选择。
(4)组合框控件
组合框控件是文本框控件和列表框控件的组合。组合框在列表框中列出了可供用户选择的项,当列表框中没有用户所需的选项时,可以在文本框中直接输入信息。
(5)按钮控件
按钮控件在被单击或双击时可以触发单击事件或双击事件,执行指定的操作。
(6)复选框控件和单选按钮控件
复选框控件和单选按钮控件都用来表示选中和未选中两种状态,二者的区别在于:多个复选框控件可以同时是选中状态;而在一组单选按钮中,只允许其中一个是选中状态。
4. MFC应用程序开发实例
4.1 图形绘制程序
【例2】程序运行的效果如图12所示:当点击圆形按钮时,对话框上显示圆形图形;当点击正方形按钮时,对话框上显示正方形图形;当点击关闭按钮时,会关闭对话框、结束应用程序运行。
图12 图形绘制程序运行效果
具体步骤为:
1.使用MFC向导生成项目名称为p19_2的基于对话框的应用程序框架,并根据图13添加按钮控件。
2.将Button1、Button2和取消按钮的Caption属性分别改为圆形、正方形和关闭,将对话框的Caption属性改为图形绘制程序,生成图14所示的界面。
3.在CP19_2Dlg类中添加成员变量m_nShape,并在构造函数中将其初始化为0。
4.为圆形按钮和正方形按钮添加单击事件,并编写事件代码:
void Cp19_2Dlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
m_nShape = 1;
Invalidate(); // 刷新对话框显示
}
void Cp19_2Dlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
m_nShape = 2;
Invalidate();
}
5.将CP19_2Dlg 类中OnPaint函数的代码改为:
void Cp19_2Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
// 修改的代码
CPaintDC dc(this);
if (m_nShape == 1)
dc.Ellipse(120, 30, 240, 150);
else if (m_nShape == 2)
dc.Rectangle(120, 30, 240, 150);
// 修改结束
CDialog::OnPaint();
}
}
6.保存并运行程序。
图13 添加控件后的对话框
图14 设置控件属性后的对话框
4.2 计算器
【例3】程序运行的效果如图15所示:在操作数1和操作数2的文本框中输入数据并在组合框中选择要做的运算,点击计算按钮,在结果文本框中就会显示运算结果;当点击关闭按钮时,会关闭对话框、结束应用程序运行。
图15 计算器运行效果
1.使用MFC向导生成项目名称为p19_3的基于对话框的应用程序框架,并根据图16添加标签控件、编辑框控件、组合框控件和按钮控件。
2.设置控件属性,生成如图17所示的界面。
(1)将对话框的Caption属性设置为计算器。
(2)将3个标签的Caption属性分别设置为操作数1、操作数2和结果。
(3)将两个按钮的Caption属性分别设置为计算和关闭。
(4)选择组合框控件,在右侧的属性对话框中进行设置。Data属性:输入“加;减;乘;除”四种运算。Type属性:Drop List(这种样式表示只允许用户在列表中选择,不允许手动输入);Sort属性:False(表示组合框控件中的选项列表不自动排序)。
(5)用鼠标左键单击组合框控件中的下箭头,会出现一个矩形框,通过该矩形框可以设置下拉列表框的最大高度,如图18所示。
图16 添加控件后的对话框
图17 设置属性后的对话框
图18 组合框控件中列表框最大高度设置
3.创建控件变量
为组合框控件(IDC_COMBO1)、操作数1对应的文本框控件(IDC_EDIT1)、操作数2对应的文本框控件(IDC_EDIT2)和结果对应的文本框控件(IDC_EDIT3)创建控件变量,变量类型和变量名分别为:
IDC_COMBO1: int m_sel;
IDC_EDIT1: double m_op1;
IDC_EDIT2: double m_op2;
IDC_EDIT3: double m_result;
4.编写事件代码
为计算按钮添加单击事件,并编写事件代码:
void Cp19_3Dlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
UpdateData(); // 将控件中输入的数据存储到控件变量中
switch (m_sel)
{
case 0: // 加法
m_result = m_op1+m_op2;
break;
case 1: // 减法
m_result = m_op1-m_op2;
break;
case 2: // 乘法
m_result = m_op1*m_op2;
break;
case 3: // 除法
m_result = m_op1/m_op2;
break;
}
UpdateData(FALSE); // 用控件变量的值更新控件中显示的内容
}
5.保存并运行程序。
4.3 通信程序
【例4】程序运行的效果如图19所示:假设进行通信的两台机器的IP地址分别为192.168.0.5和192.168.0.3,在两台机器上分别运行通信程序,并输入对方IP地址。机器1在待发送的消息文本框中填入消息并点击发送按钮,此时,机器2就会接收到机器1发过来的消息并显示在接收到的消息文本框中。
(a)机器1
(b)机器2
图19 通信程序运行效
1.使用MFC向导生成项目名称为p19_4的基于对话框的应用程序框架,注意在MFC Application Wizard-Application Type对话框中需要选中Windows sockets复选框,如图20所示。
图20 MFC Application Wizard-Advanced Features对话框
2.根据图21添加标签控件、文本框控件和按钮控件。
图21 添加控件后的对话框
3.设置控件属性,生成如图22所示的界面。
(1)将对话框的Caption属性设置为通信程序。
(2)将3个标签的Caption属性分别设置为对方IP地址、接收到的消息和待发送的消息。
(3)将两个按钮的Caption属性分别设置为发送和关闭。
图22 设置控件属性后的对话框
4.创建控件变量和类成员变量
(1)为对方IP地址对应的文本框控件(IDC_EDIT1)、接收到的消息对应的文本框控件(IDC_EDIT2)和待发送的消息对应的文本框控件(IDC_EDIT3)创建控件变量,变量类型和变量名分别为:
IDC_EDIT1:CString m_ip;
IDC_EDIT2:CString m_receive;
IDC_EDIT3:CString m_send;
(2)为CP19_4Dlg添加CAsyncSocket类型的成员变量m_socket。
5.编写事件代码
(1)在p19_4Dlg.cpp的OnInitDialog事件中编写代码:
BOOL Cp19_4Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_socket.Create(6066, SOCK_DGRAM, NULL); // 创建本地套接字
m_socket.Bind(6606, LPCTSTR("127.0.0.1")); // 绑定本地套接字
SetTimer(1, 1000, NULL); // 设定计时器,每隔1秒执行一次OnTimer函数
……
}
(2)在ClassView视图中选择Cp19_4Dlg并在右侧的Properties窗口中选择Messages按钮,在事件列表中选择WM_TIMER事件,然后选择<Add>OnTimer为对话框添加计时器事件,如图23所示。最后,编写事件代码定时检测并接收对方发过来的消息:
void Cp19_4Dlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
UpdateData(); // 将控件中输入的IP地址存储到控件变量中
WCHAR* pcMsg = m_receive.GetBuffer(1024);
UINT uPort = 6066;
int iMode = 1;
ioctlsocket(m_socket,FIONBIO, (u_long FAR*) &iMode); //非阻塞设置
m_socket.ReceiveFrom(pcMsg, 100, m_ip, uPort); // 根据IP地址从对方接收消息
m_receive.ReleaseBuffer();
UpdateData(FALSE); // 将接收到的消息显示在文本框控件中
CDialog::OnTimer(nIDEvent);
}
(3)为发送按钮添加单击事件,并编写事件代码:
void Cp19_4Dlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
UpdateData(); // 将控件中输入的IP地址和待发送消息存储到控件变量中
m_socket.SendTo(m_send, 100, 6066, m_ip); // 根据IP地址发送消息
m_send = "";
UpdateData(FALSE); // 将待发送消息文本框清空
}
图23 对话框的WM_TIMER事件
6.保存并运行程序。
5. 小结
MFC是Microsoft Foundation Class Library的简称,即微软提供的基础类库。
MFC定义了应用程序的框架,并提供了用户接口的标准实现方法,程序员所要做的工作就是通过预定义的接口把具体应用程序特有的代码填入这个框架。通过它,程序员可以高效地开发出基于Windows操作系统的各种应用程序。
MFC建立在C++的基础上,因此,它具备C++中类的特性:封装性、继承性和多态性。
MFC应用程序分为单文档应用程序、多文档应用程序和基于对话框的应用程序。
开发一个MFC应用程序分为以下几个步骤:(1)使用MFC向导生成一个基于对话框的应用程序框架;(2)在对话框上添加控件并设置控件属性;(3)根据需要创建控件变量;(4)编写事件代码,当事件被触发时执行相应的功能;(5)保存和运行程序。
-C++的常见错误
--C++的常见错误
-MFC入门
--MFC入门
-STL及使用示例
--STL及使用示例
-算法设计与算法分析基础
-算法设计基本方法与策略基础
-计算机前沿问题思考
-QT编程入门
--QT编程入门
-C++中的string类
-面向对象方法应用实例
-继承与多态应用实例
-排序算法
--排序算法
-C++常见问题汇总
-学习感悟(1)
--学习感悟(1)
-学习感悟(2)
--学习感悟(2)
-学习感悟(3)
--学习感悟(3)
-学习感悟(4)
--学习感悟(4)
-1.1面向对象方法的基本概念
-1.1面向对象方法的基本概念--作业
-1.2 C++中类的定义
-1.2 C++中类的定义
-1.3C++中对象的定义和访问
-1.3C++中对象的定义和访问--作业
-1.4类成员的访问控制
-1.4类成员的访问控制--作业
-1.5析构函数
--1.5析构函数
-1.5析构函数--作业
-1.6拷贝构造函数
-1.6拷贝构造函数--作业
-1.7 类声明与类实现的分离
-1.7 类声明与类实现的分离--作业
-1.8类的静态成员
-1.8类的静态成员--作业
-1.9类的常量成员
-1.9类的常量成员--作业
-1.10this指针
-1.10this指针--作业
-1.11类的友元
--1.11类的友元
-1.11类的友元--作业
-1.12类的对象成员
-1.12类的对象成员--作业
-1.13自定义类的运算符重载
-1.13自定义类的运算符重载--作业
-2.1 派生类的定义和继承方式
-2.1 派生类的定义和继承方式--作业
-2.2 派生类中函数的重定义
-2.2 派生类中函数的重定义--作业
-2.3派生类的构造函数和析构函数
-2.3派生类的构造函数和析构函数--作业
-2.4多继承
--2.4多继承
-2.4多继承--作业
-2.5多态
--2.5多态
-2.5多态--作业
-2.6抽象类
--2.6抽象类
-2.6抽象类--作业
-3.1cout和cin对象及插入和提取运算符
-3.1cout和cin对象及插入和提取运算符--作业
-3.2 使用put和get函数进行标准输出和输入
-3.3使用getline函数进行标准输入
-3.3使用getline函数进行标准输入--作业
-3.4 文件流对象
-3.5文件流对象及插入和提取运算符
-3.5文件流对象及插入和提取运算符--作业
-3.6文件流对象及put、get和getline函数
-3.7按数据块进行输入输出
-3.8按数据块进行输入输出实例
-3.8按数据块进行输入输出实例--作业
-3.9文件的随机读写
-3.9文件的随机读写--作业
-3.10用户自定义数据类型的输入输出
-3.10用户自定义数据类型的输入输出--作业
-4.1函数模板
--4.1函数模板
-4.1函数模板--作业
-4.2类模板
--4.2类模板
-4.2类模板--作业
-5.1数据结构基本概念(一)
-第五章 概论--5.1数据结构基本概念(一)
-5.2数据结构基本概念(二)
-5.2数据结构基本概念(二)--作业
-6.1线性表及其抽象数据类型
-6.1线性表及其抽象数据类型--作业
-6.2顺序表类模板
-6.2顺序表类模板--作业
-6.3顺序表的实现
-6.3顺序表的实现--作业
-6.4简单数据元素顺序表的应用问题
-6.4简单数据元素顺序表的应用问题--作业
-6.5复杂数据元素顺序表的应用问题
-6.5复杂数据元素顺序表的应用问题--作业
-6.6单向链表及其类模板
-6.6单向链表及其类模板--作业
-6.7单项链表的实现(一)
-6.7单项链表的实现(一)--作业
-6.8单项链表的实现(二)
-6.8单项链表的实现(二)--作业
-6.9单向链表的应用
-6.10循环链表及双向链表
-7.1栈及顺序栈
--7.1栈及顺序栈
-7.1栈及顺序栈--作业
-7.2 顺序栈的实现
-7.2 顺序栈的实现--作业
-7.3顺序栈的应用
-7.4 链接栈及其实现
-7.4 链接栈及其实现--作业
-7.5队列及其顺序存储
-7.5队列及其顺序存储--作业
-7.6 顺序循环队列的实现
-7.6 顺序循环队列的实现--作业
-7.7顺序循环队列的应用
-7.8链接队列及其实现
-7.8链接队列及其实现--作业
-8.1树的基本概念
-8.1树的基本概念--作业
-8.2二叉树及其性质
-8.2二叉树及其性质--作业
-8.3二叉树的抽象数据类型和顺序表示
-8.3二叉树的抽象数据类型和顺序表示--作业
-8.4二叉树的链式表示
-第八章 树和二叉树--8.4二叉树的链式表示
-8.5二叉链表的实现(一)
-8.6二叉链表的实现(二)先序和中序遍历
-8.6二叉链表的实现(二)先序和中序遍历--作业
-8.7二叉链表的实现(三)后序和逐层遍历
-8.7二叉链表的实现(三)后序和逐层遍历--作业
-8.8二叉链表的实现(四)
-8.9 二叉排序树
-8.10哈夫曼树和哈夫曼编码
-9.1图的基本概念及其特征
-9.1图的基本概念及其特征--作业
-9.2图的抽象数据类型和表示方式
--Video
-9.2图的抽象数据类型和表示方式--作业
-9.3图的邻接矩阵表示法的实现
-9.3图的邻接矩阵表示法的实现--作业
-9.4图的广度优先遍历
--Video
-9.4图的广度优先遍历--作业
-9.5图的深度优先遍历
-9.5图的深度优先遍历--作业
-9.6图的应用
--9.6 图的应用
-面向对象方法
--面向对象例题讲解
--友元和运算符重载
--对象成员
-继承与多态
--多重继承
--虚函数
--抽象类和纯虚函数
-输入输出流
--输入输出流操作
-模板
--函数模板
--类模板