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

相关文章

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

Spring中Bean有关NullPointerException异常的原因分析

《Spring中Bean有关NullPointerException异常的原因分析》在Spring中使用@Autowired注解注入的bean不能在静态上下文中访问,否则会导致NullPointerE... 目录Spring中Bean有关NullPointerException异常的原因问题描述解决方案总结

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit