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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别