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

相关文章

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

springboot集成Deepseek4j的项目实践

《springboot集成Deepseek4j的项目实践》本文主要介绍了springboot集成Deepseek4j的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录Deepseek4j快速开始Maven 依js赖基础配置基础使用示例1. 流式返回示例2. 进阶

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

SpringBoot项目使用MDC给日志增加唯一标识的实现步骤

《SpringBoot项目使用MDC给日志增加唯一标识的实现步骤》本文介绍了如何在SpringBoot项目中使用MDC(MappedDiagnosticContext)为日志增加唯一标识,以便于日... 目录【Java】SpringBoot项目使用MDC给日志增加唯一标识,方便日志追踪1.日志效果2.实现步

Windows Server服务器上配置FileZilla后,FTP连接不上?

《WindowsServer服务器上配置FileZilla后,FTP连接不上?》WindowsServer服务器上配置FileZilla后,FTP连接错误和操作超时的问题,应该如何解决?首先,通过... 目录在Windohttp://www.chinasem.cnws防火墙开启的情况下,遇到的错误如下:无法与

Python解析器安装指南分享(Mac/Windows/Linux)

《Python解析器安装指南分享(Mac/Windows/Linux)》:本文主要介绍Python解析器安装指南(Mac/Windows/Linux),具有很好的参考价值,希望对大家有所帮助,如有... 目NMNkN录1js. 安装包下载1.1 python 下载官网2.核心安装方式3. MACOS 系统安