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

相关文章

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

找不到Anaconda prompt终端的原因分析及解决方案

《找不到Anacondaprompt终端的原因分析及解决方案》因为anaconda还没有初始化,在安装anaconda的过程中,有一行是否要添加anaconda到菜单目录中,由于没有勾选,导致没有菜... 目录问题原因问http://www.chinasem.cn题解决安装了 Anaconda 却找不到 An

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.