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

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

liebian365 2024-10-26 12:59 5 浏览 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-

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: