百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

VC|了解模态对话框与非模态对话框的内在机制及内存分配差异

liebian365 2024-10-26 12:59 23 浏览 0 评论

MFC中对话框有两种形式,一个是模态对话框(model dialog box),一个是非模态对话框(modeless dialog box)。

模态对话框是一种阻塞式的对话框,即没有处理完该对话框,不能对其他地方进行操作。非模态对话框和模态对话框相反,它不是阻塞型的,即你可以同时操作其他的窗口,比如父窗口。

模态对话框在关闭对话框(OnOk、OnCancel、OnClose)这三个消息产生之前不可对此对话框以外的对话框进行操作,当上面3个消息产生后系统负责删除模态对话框资源。而非模态对话框可以进行其他操作,但必须在三个消息发生后自己在析构函数里回收此对话框资源。

如word文档中的“查找”对话框就是一个非模态对话框,还可以从文档中复制文本,然后粘贴到“查找”对话框中,操作比较灵活、方便。当然模态对话框也有其存在的必要,例如一些警告对话框,就是必须要用户做出选择后才可以进行其它操作。

Windows是一种面向对象的体系结构,Windows环境和应用程序都是通过消息来交互的,由用户发出消息,系统响应处理。Windows应用程序开始执行后,Windows为该程序创建一个"消息队列(message queue)"的数据结构体,用以存放邮寄给该程序可能创建的各种不同窗口的消息。PostMessage()不等待该消息处理完就返回,SendMessage()则必须等待该消息处理完后方可返回(不进队消息)。

Windows 应用程序创建的每个窗口都在系统核心注册一个相应的窗口函数,窗口函数程序代码形式上是一个巨大的switch 语句,用以处理由消息循环发送到该窗口的消息,窗口函数由Windows 采用消息驱动的形式直接调用,而不是由应用程序显示调用的,窗口函数处理完消息后又将控制权返回给Windows。

非模态对话框是响应一个消息,系统处理一个消息,处理完毕后返回控制权给Windows。

模态对话框在对话框创建后,挂起外部的消息,只是响应对话框内部的消息,而外部消息则全部"过滤"掉了,直到系统接收到WM_DESTROY或WM_CLOSE后,系统返回控制权给模态对话框创建前的线程,继续模态对话框创建前的线程将执行的代码。

模态对话框的DoModal()方法可以产生、显示、销毁窗口。

非模态对话框需要调用Create()创建,调用ShowWindow进行显示,最后用delete销毁。

一、模态对话框(model dialog box)

在程序运行的过程中,若出现了模态对话框,那么主窗口将无法发送消息,直到模态对话框退出才可以发送。点击模态对话框中的OK按钮,模态对话框会被销毁。

创建一个模态对话框的代码:

CTestDialog td;

td.DoModal();

其中CTestDialog为所新建和一个对话框资源相关联的对话框类。

可以创建一个模态对话框类变量,不用担心它会随着所在函数返回而被销毁。因为DoModal()函数的一个功能是,当前只能运行此模态对话框,且停止主窗口的运行,直到模态对话框退出,才允许主窗口运行。

DoModal()函数也有显示对话框的功能,所以也无需调用其他函数来显示对话框。

二、非模态对话框(modaless dialog box)

在程序运行的过程中,若出现了非模态对话框,主窗口还可以发送消息。

点击非模态对话框中的OK按钮,非模态对话框没有销毁,只是隐藏了。若想点击OK按钮时,非模态对话框也销毁,那么CTestDialog类必须重载其基类CDialog的虚函数OnOK(),在此函数里调用DestroyWindow()来销毁此对话框。

若和上面一样的方式创建一个非模态对话框:

CTestDialog td;

td.Create(IDD_DIALOG1); //创建一个非模态对话框

td.ShowWindow(SW_SHOWNORMAL); //显示非模态对话框

那么,在运行时,你会发现此对话框无法显示。这是因为你声明的对话框变量td是局部变量,但这个函数返回时,td也被析构了,所以无法显示此对话框。

创建非模态对话框,必须声明一个指向CTestDialog类的指针变量,且需要显示地调用ShowWindow()才能将对话框显示出来。有两种创建方法:

(1)采用局部变量创建一个非模态对话框

CTestDialog *pTD = new CTestDialog();

pTD->Create(IDD_DIALOG1); //创建一个非模态对话框

pTD->ShowWindow(SW_SHOWNORMAL); //显示非模态对话框

指针pTD本身存放在栈中,指针pTD指向的对象*pTD存放在堆中。*pTD只有整个应用程序关闭后才会被销毁,所以可以正常显示对话框。

这种方法虽然不影响程序的运行,可是指针pTD所指向的内存却导致不可用,这样的编程很不好。

(2)采用成员变量创建一个非模态对话框

首先在你所要编写的类的头文件中声明一个指针变量:

private:

CTestDialog *pTD;

然后再在相应的CPP文件,在你要创建对话框的位置添加如下代码:

//采用成员变量创建一个非模态对话框

pTD = new CTestDialog(); //给指针分配内存

pTD->Create(IDD_DIALOG1); //创建一个非模态对话框

pTD->ShowWindow(SW_SHOWNORMAL); //显示非模态对话框

指针pTD本身存放在堆中,指针pTD指向的对象*pTD也存放在堆中。

最后在所在类的析构函数中收回pTD所指向的内存:

delete pTD;

三、内存分配的区别

模态对话框定义的定义的局部变量,是在栈上分配的内存,程序一出函数,他的生命周期就终止了,也就被自动释放。

非模态对话框定义的指针,是在堆上分配的内存 。

在这里要解释一下程序在内存中的分布情况。

1 代码区

存放函数体的二进制代码。

2 全局区或静态区

程序结束后由系统释放。

2.1 数据区:初始化的全局和静态局部变量

2.2 BSS:未初始化的全局和静态局部变量

3 动态数据区

3.1 堆(heap)

以动态的方式分配内存,由程序员分配(在C中用malloc函数,在C++中用new运算符)和释放(free函数和delete去处符),若程序员不释放,程序结束时可能由操作系统回收。从低地址到高地址扩散。分配方式类似于数据结构的链表。(系统是用链表存储空闲内在地址,是不连续的内存区域,所以堆获得的空间比较灵活,也比较大)

3.2 栈(stack)

存放局部变量、函数参数和返回值。由编译器自动分配和释放。从高地址到低地址扩散(能从栈获得的空间较小)。栈区也称为动态数据区。操作方式类似于数据结构中的栈。

4 文字常量区

用于存放常量字符串,程序结束后由系统释放。

命令行参数与环境区:命令行参数和环境变量。

BSS和数据区统称为 全局区或静态区。

全局变量放在全局区(静态区),函数内部变量stattic in ncount也是放在全局区(静态区)。函数内部变量char *p = "AAA",p保存的位置在栈区,但p指向的空间位置在全局区(静态区);函数内部变量char *p = new char,p保存的位置在栈区,但p指向的空间位置却是在堆区。

低端内存区域→……动态数据区……代码区、静态数据区……←高端内存区域;

成员变量和局部变量的区别:

I 在类中位置不同:成员变量在类中方法外;局部变量在方法定义中或者方法声明上。

II 在内存中的位置不同:成员变量在堆内存;局部变量在栈内存。

III 生命周期不同:成员变量随着对象的创建而存在,随着对象的消失而消失。 局部变量随着方法的调用而存在,随着方法的调用完毕而消失。

IV 初始化值不同:成员变量有默认值初始化;局部变量没有默认值初始化,必须定义,赋值,然后才能使用。

V 局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。

-End-

相关推荐

go语言也可以做gui,go-fltk让你做出c++级别的桌面应用

大家都知道go语言生态并没有什么好的gui开发框架,“能用”的一个手就能数的清,好用的就更是少之又少。今天为大家推荐一个go的gui库go-fltk。它是通过cgo调用了c++的fltk库,性能非常高...

旧电脑的首选系统:TinyCore!体积小+精简+速度极快,你敢安装吗

这几天老毛桃整理了几个微型Linux发行版,准备分享给大家。要知道可供我们日常使用的Linux发行版有很多,但其中的一些发行版经常会被大家忽视。其实这些微型Linux发行版是一种非常强大的创新:在一台...

codeblocks和VS2019下的fltk使用中文

在fltk中用中文有点问题。英文是这样。中文就成这个样子了。我查了查资料,说用UTF-8编码就行了。edit->Fileencoding->UTF-8然后保存文件。看下下边的编码指示确...

FLTK(Fast Light Toolkit)一个轻量级的跨平台Python GUI库

FLTK(FastLightToolkit)是一个轻量级的跨平台GUI库,特别适用于开发需要快速、高效且简单界面的应用程序。本文将介绍Python中的FLTK库,包括其特性、应用场景以及如何通过代...

中科院开源 RISC-V 处理器“香山”流片,已成功运行 Linux

IT之家1月29日消息,去年6月份,中科院大学教授、中科院计算所研究员包云岗,发布了开源高性能RISC-V处理器核心——香山。近日,包云岗在社交平台晒出图片,香山芯片已流片,回片后...

Linux 5.13内核有望合并对苹果M1处理器支持的初步代码

预计Linux5.13将初步支持苹果SiliconM1处理器,不过完整的支持工作可能还需要几年时间才能完全完成。虽然Linux已经可以在苹果SiliconM1上运行,但这需要通过一系列的补丁才能...

Ubuntu系统下COM口测试教程(ubuntu port)

1、在待测试的板上下载minicom,下载minicom有两种方法:方法一:在Ubuntu软件中心里面搜索下载方法二:按“Ctrl+Alt+T”打开终端,打开终端后输入“sudosu”回车;在下...

湖北嵌入式软件工程师培训怎么选,让自己脱颖而出

很多年轻人毕业即失业、面试总是不如意、薪酬不满意、在家躺平。“就业难”该如何应对,参加培训是否能改变自己的职业走向,在湖北,有哪些嵌入式软件工程师培训怎么选值得推荐?粤嵌科技在嵌入式培训领域有十几年经...

新阁上位机开发---10年工程师的Modbus总结

前言我算了一下,今年是我跟Modbus相识的第10年,从最开始的简单应用到协议了解,从协议开发到协议讲解,这个陪伴了10年的协议,它一直没变,变的只是我对它的理解和认识。我一直认为Modbus协议的存...

创建你的第一个可运行的嵌入式Linux系统-5

@ZHangZMo在MicrochipBuildroot中配置QT5选择Graphic配置文件增加QT5的配置修改根文件系统支持QT5修改output/target/etc/profile配置文件...

如何在Linux下给zigbee CC2530实现上位机

0、前言网友提问如下:粉丝提问项目框架汇总下这个网友的问题,其实就是实现一个网关程序,内容分为几块:下位机,通过串口与上位机相连;下位机要能够接收上位机下发的命令,并解析这些命令;下位机能够根据这些命...

Python实现串口助手 - 03串口功能实现

 串口调试助手是最核心的当然是串口数据收发与显示的功能,pzh-py-com借助的是pySerial库实现串口收发功能,今天痞子衡为大家介绍pySerial是如何在pzh-py-com发挥功能的。一、...

为什么选择UART(串口)作为调试接口,而不是I2C、SPI等其他接口

UART(通用异步收发传输器)通常被选作调试接口有以下几个原因:简单性:协议简单:UART的协议非常简单,只需设置波特率、数据位、停止位和校验位就可以进行通信。相比之下,I2C和SPI需要处理更多的通...

同一个类,不同代码,Qt 串口类QSerialPort 与各种外设通讯处理

串口通讯在各种外设通讯中是常见接口,因为各种嵌入式CPU中串口标配,工业控制中如果不够还通过各种串口芯片进行扩展。比如spi接口的W25Q128FV.对于软件而言,因为驱动接口固定,软件也相对好写,因...

嵌入式linux为什么可以通过PC上的串口去执行命令?

1、uboot(负责初始化基本硬bai件,如串口,网卡,usb口等,然du后引导系统zhi运行)2、linux系统(真正的操作系统)3、你的应用程序(基于操作系统的软件应用)当你开发板上电时,u...

取消回复欢迎 发表评论: