C++ MFC框架结构的分析

2023-11-08 00:59
文章标签 分析 c++ mfc 框架结构

本文主要是介绍C++ MFC框架结构的分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一节我们基于MFC的框架结构,创建了一个默认的基于对话框的应用程序。没有添加一行代码,但是运行程序却弹出了一个对话框界面。本节将要介绍上一节所生成的框架代码,来更多地了解MFC应用程序,能更好地在MFC框架上快速地开发软件。

框架代码文件的结构

基于MFC对话框程序的框架结构如图1-3-1所示:


图1-3-1 基于MFC对话框程序的框架代码结构示意图


主要有4个部分组成:
1) 资源文件Resource.h:主要是定义资源的ID。
2) 预编译文件:可以用来解决头文件包含冲突的问题,定义一些需要全局性包含的文件。
3) 应用程序类对应文件:项目名称是TestOne,对应类名为CTestOneApp。
4) 对话框类:项目名称是TestOne,对应类名为CTestOneDlg。

应用程序类

MFC定义了一个应用程序基类CWinApp,所有基于MFC的应用程序都会继承这个类。TestOne项目也不例外,此时的应用程序类是CTestOneApp,定义如下:

class CTestOneApp : public CWinApp
{
public:CTestOneApp();
public:// 重载虚函数virtual BOOL InitInstance();// 实现DECLARE_MESSAGE_MAP()
};

这个类的定义很简单,重点来看一下InitInstance函数:

BOOL CTestOneApp::InitInstance()
{  //初始化应用程序环境包控件等操作,省略部分代码.CWinApp::InitInstance();..//省略部分代码...    //定义对话框对象CTestOneDlg dlg;//保存对话框到全局变量m_pMainWnd = &dlg; //显示对话框INT_PTR nResponse = dlg.DoModal();if (nResponse == IDOK){//“确定”来关闭对话框的代码}else if (nResponse == IDCANCEL){//“取消”来关闭对话框的代码}// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序, 而不是启动应用程序的消息泵。return FALSE;
}

这个函数可以看作MFC程序的入口函数,main函数隐藏在这个函数中。在实际的开发中,一般不需要对这个类进行操作,但如果需要在建立主对话框之前处理一些数据或者准备工作,那么就可以把代码添加到这个函数中,主对话框显示之前。

这里有两个比较个典型的应用。
1) 启动界面之前弹出登陆界面,需要正确输入用户名和密码才能弹出主界面;

2) 启动界面之前,弹出一个项目配置界面,例如操作员,设备编号,项目名称,批次等信息,同时这些信息需要传递到主界面中,主界面根据项目和批次决定某种操作方式。

上面两个应用在实际的项目开发中很常见,需求比较普遍。

第一个需求不涉及数据传递,可以在代码中将用户名和密码固定,如果输入的结果与设定的结果一致,那么就开放此软件的使用权限;稍微复杂一点的,可以比较输入的结果与数据库中存储的用户名和密码是否匹配,如果匹配,才开放此软件的使用权限;再稍微复杂一点的,还可以将界面输入结果与服务器中的信息比较,查看当前用户是否有此软件的使用权限,当然这个还涉及到服务端的处理,与网络通信有关。

第二个需求涉及不同对话框之间的数据传递,应用也比较广泛。

篇幅有限,这里不再展示这两个需求的源码,源码统一在本教程的源码获取链接中获取。

对话框类

MFC主对话框类(主对话框是指与项目名称一致的那个类对应的对话框,下同)CTestOneDlg继承CDialogEx类,CDialogEx又继承CDialog类,这个可以通过类转到定义查看,对话框类负责与用户交互,处理用户消息,接受用户输入。类的定义如下:

// CTestOneDlg 对话框
class CTestOneDlg : public CDialogEx
{
public:// 标准构造函数CTestOneDlg(CWnd* pParent = NULL);// 对话框数据enum { IDD = IDD_TESTONE_DIALOG }; 
protected:// 动态数据交换,负责控件与变量之间的关联virtual void DoDataExchange(CDataExchange* pDX);   
protected://应用程序句柄HICON m_hIcon;//重载初始化对话框virtual BOOL OnInitDialog();//定义消息WM_SYSCOMMAND处理函数afx_msg void OnSysCommand(UINT nID, LPARAM lParam);//定义消息WM_PAINT处理函数afx_msg void OnPaint();//定义消息ON_WM_QUERYDRAGICON处理函数afx_msg HCURSOR OnQueryDragIcon();//消息映射DECLARE_MESSAGE_MAP()
};

从这个类的定义可以看出以下几点:
1) 控件与数据关联,可以简单地交给框架来实现;
2) 在MFC框架上开发主要是针对消息处理机制。

添加消息响应

MFC消息响应机制过程比较复杂,这里因为还只是基础部分,不做深入的探讨,只做一个简单的过程演示,给读者一个初步的印象,后面会在专门的章节中讨论这个问题。本节演示在界面中添加一个按钮的消息响应。

首先把工作区间切换到“资源视图”,如果工作区间没有显示资源视图,在菜单中的视图中查找“资源视图”并点击,这样工作区间就会显示出来。切换到资源视图后,找到Dialog文件夹找到IDD_TESTONE_DIALOG,如图1-3-2所示。


图1-3-2 MFC对话框程序资源视图示例


双击图1-3-2中选中的对话框ID就会显示这个对话框窗口,从工具栏中选择“Button”按钮后,可以直接将按钮拖至显示的这个对话框窗口中。说明一下,工具栏只有当主工作区间显示对话框时才会显示,初学者可能会碰到找不到工具栏的情况。用鼠标右键点击按钮,选择“属性”切换到属性页,修改按钮的名称(对应Caption)“Test”,同时修改按钮的ID为IDC_BTN_TEST。有两种方式可以完成添加按钮的消息处理函数。
1) 直接双击按钮;
2) 右键选中按钮,点击“添加事件处理程序”;

两种方式区别在于,第一种方式添加的消息响应函数名称是默认的,第二种方式添加的消息响应函数名称是可以编辑的。


图1-3-3 MFC添加按钮消息响应事件处理向导


代码如下所示:

//添加按钮IDC_BTN_TEST的单击消息处理函数
void CTestOneDlg::OnBtnTest()
{AfxMessageBox(_T("测试成功!"));
}

添加一个MessageBox之后,编译并执行。在软件中添加我们添加的“Test”按钮之后,出现消息框,如图1-3-4所示。


图1-3-4显示处理按钮的消息

 

这篇关于C++ MFC框架结构的分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/367044

相关文章

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景