Windows编程_Lesson004_项目预备_重新认识MFC

2024-06-06 12:18

本文主要是介绍Windows编程_Lesson004_项目预备_重新认识MFC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MFC本质

MFC本质上就是一套开发框架,它可以帮助我们快速开发。MFC是以类的方式重新将Windows API进行了归类,MFC层次结构图链接。一提到类,相信对于了解C++或者其它比较高级一点的开发语言的同学肯定就不会感到那么恐惧MFC了。MFC既然是一套,所以你就不一定非得在VS环境下编译,它可以在任何支持C++的编译器下面进行编译,但是这些编译器必须是在Windows下的,因为它所使用的大多数API都是Windows下的,和Linux或者Unix是不兼容的。虽然说可以在任何编译器下进行编译MFC这套框架,但是我们还是最好在VS下面进行MFC的编译和开发,因为VS对MFC的支持是最好的。
下面是MFC层次结构图,看到这些图,我们对MFC是不是了解更加清晰了呢?
它就是一层一层的继承,和C++的继承是一模一样的。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
上面所述的目的就是我们(主要是刚接触MFC的同学)不要觉得MFC有多难多复杂,它其实就是一个一个的类,一步一步的看这个类是从哪儿继承过来的,然后我们就知道这个类中都有什么函数(接口)可供我们使用了,用到什么函数,直接就去这个类里面查找就OK了!这么一解释,MFC是不是变得不是那么难了呢?

Dialog创建过程

XXX代表的数创建的对话框工程的名字。
MFC的对话框创建完成后,存放代码的有两个类,一个是XXXApp的类,另一个是XXXDlg的类。我们需要注意一下几个点:

第一个点,在XXXApp类中,有这样的一个虚函数:

virtual BOOL InitInstance();

这个函数在程序启动的时候被被动的调用。

第二个点,在XXXDlg类中,有这样的一个函数:

BOOL OnInitDialog() override;

注意:所有的OnXXX函数,代表的意思都是被被动的调用,意思就是当发生某些消息的时候就会调用OnXXX函数!

特别需要注意的是:
XXXDlg类是完成界面功能的,而XXXApp类是主要实现程序逻辑的功能的。
在MFC这套框架中,程序和窗口是分开的。窗口只是响应一些界面的消息,它一定不是来完成逻辑的,XXXApp才是来完成逻辑的。

详细的执行过程是这样的,XXXApp类会生成唯一的一个全局对象theApp,这个theApp会执行它的InitInstance()函数,而 InitInstance()函数里面会生成XXXDlg类的对象dlg,dlg调用它的函数DoModal(),DoModal()再调用BOOL OnInitDialog() override,此时,一个对话框界面就活生生的展现在我们的面前了,我们可以在对话框界面上做一些事情,当这个对话框关闭的时候,它也会返回一个值,我们可以根据返回值,也可以做一些相应的收尾工作。

这里写图片描述

这就是MFC的对话框创建和销毁的全部过程,是不是很简单呢?

对话框的使用

这里写图片描述

这里写图片描述

这里写图片描述
如果按照上面进行添加对话框标题,会弹出下面的错误
这里写图片描述

当我们单步调试,进入SetWindowText函数,如下图所示:
这里写图片描述
我们可以看到hWnd是一个空指针,所以就会出现崩溃。那么有的同学就会产生疑问,我们的对话框对象不是已经创建出来了吗?那么为什么不能调用SetWindowText函数呢?这是因为SetWindowText函数是针对于窗口来进行操作的,而窗口是属于内核对象,也就是意味着,有没有类,跟我内核对象是一点关系都没有的,也就是说,只要你有窗口,我就能做窗口相关的事情。
总的来说就是对话框对象是我们自己程序的对象,我们的程序对象维护了一个窗口内核对象,注意:我们只是维护一个窗口内核对象,它是不属于我们自己程序的,应该说,所有的内核对象都是不属于程序的,它们是属于操作系统的,我们能做的是,我们需要什么,操作系统帮我们拿出来我们需要的东西,然后在确保拿过来这个东西的时候,我们再对它们进行相关操作。,所以我们当前的对话框对象并没有拿到内核对象,因为必须在DoModal之后,才能拿到窗口内核对象,也就是说,DoModal函数里面才能拿到窗口内核对象。
我们的对话框类严格来说是一个窗口管理类,我们的窗口是一个内核对象,而窗口内核对象是通过操作系统来分配的,所以我们的窗口管理类唯一能做的是向操作系统要一个窗口内核对象(起到一个通知的作用),然后再让这些窗口对象做一些相应的改变,比如通过SetWindowText函数来修改对话框标题等。
这里写图片描述

那么问题又来了,SetWindowText函数只能在DoModal函数之后才能起作用,但是DoModal函数是一个阻塞函数,SetWindowText函数是不能被执行到的呀!!!这该怎么办呢?如果我们使用的是非模态对话框,那么在Create函数之后,是可以进行SetWindowText函数来修改标题的。
那么对于模态对话框,我们就没有办法解决这个问题了吗?办法是有的,比如我们可以对DoMoDal函数进行改造。我们可以想象一下DoModal函数里面做的事情:

可定CreateWindow -> 发送WM_CREATE消息 -> OnInitialDialog函数里面可以做初始化操作

所以我们可以重写OnInitialDialog函数,在OnInitialDialog函数中,我们首先可以调用父类里面的CDialogEx::OnInitialDialog函数,然后再做窗口设置操作,调用SetWindowText函数,来更改对话框标题,重写的OnInitialDialog函数如下所示:

这里写图片描述

此时,我们再看一下执行效果:

这里写图片描述

我们只重写OnInitialDialog函数,就解决了程序崩溃的问题,原来的调用没有任何一点儿改变:
这里写图片描述

从上面的例子可以看出,MFC实际上是以C++的方式对Windows里面的很多特性进行了一层一层的封装,然后对Windows中的每一个消息都相应的产生一个On…的函数,所以我们可以利用C++里面的特性,来对MFC进行各种各样的填充、扩充以及修改。

我们如果想正儿八经使用MFC这套框架的话,把MFC写的与众不同一些的话,我们更多的是对MFC的类进行继承,然后对特定的消息进行特定的操作。

下面介绍三种方式来定制MFC

1. 构造函数接收参数修改对话框风格的例子
2. 重载一个接收参数的DoModal函数
3. 设置一个方法

1. 构造函数接收参数例子
增加一个带参数的构造函数
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

上面的方式虽然可以,但是并不推荐。我们应该使用一个enum来枚举一些对话框风格
这里写图片描述

这里写图片描述

这里写图片描述

2. 重载接收参数的DoModal函数修改对话框风格的例子

这里写图片描述

这里写图片描述

3.设置一个方法改对话框风格的例子就不再举例子了

DoModal函数的返回值

当我们点击对话框上面的×号关闭对话框时,DoModal函数会返回2,它代表是IDCANCEL消息,然后就将对话框关闭掉了,如果我们想使用自己的按钮来关闭对话框,该如何实现呢?
那么这样实现我们的关闭按钮函数,可以将对话框关闭掉吗?

这里写图片描述

我们也不知道OnClose函数里面到底做了什么事情,调试一下!!!

这里写图片描述
这里写图片描述
这里写图片描述
从上面可以看出OnClose函数什么事情都没有做,所以这个按钮是不能将对话框关闭掉的。

如果我们调用父类的OnClose函数,效果会怎样呢?

这里写图片描述
通过调试,可以看出,跟调用本类中的OnClose函数是一模一样的。

那么我们该如何才能自己将对话框关闭呢?很简单,自己重载一个OnClose函数,让OnClose函数调用CloseWindow函数,就可以将对话框关闭。
这里写图片描述
这里写图片描述

MFC的按钮约定俗成的一些按钮。
这里写图片描述

我们还可以使用EndDialog函数,根据传入的不同的参数,来决定DoModal函数的返回值。
这里写图片描述
这里写图片描述
从上面可以看出,如果我们传入的是IDCANCEL,那么DoModal函数的返回值就是2了。

这篇关于Windows编程_Lesson004_项目预备_重新认识MFC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

SpringBoot项目是如何启动

启动步骤 概念 运行main方法,初始化SpringApplication 从spring.factories读取listener ApplicationContentInitializer运行run方法读取环境变量,配置信息创建SpringApplication上下文预初始化上下文,将启动类作为配置类进行读取调用 refresh 加载 IOC容器,加载所有的自动配置类,创建容器在这个过程

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念