[MFC]DlgDemo2程序:非模态对话框的基本应用

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

1. 非模态对话框的创建方法以及和模态对话框的不同之处:

    1) 首先是创建非模态对话框使用的是CDialog::Create而不是CDialog::DoModal;

    2) 那么最大的问题就来了,Create是从CWnd继承而来的用来创建普通窗口用的函数,这就导致了关闭对话框时和模态对话框的大不相同!!

    3) 由于使用Create创建对话框窗口了,因此关闭它就也要和关闭普通窗口一样,必须使用DestroyWindow来关闭窗口,DestroyWindow会接着触发PostNcDestroy,这完全就和关闭普通窗口一模一样了,因此这里最大的区别就是模态对话框关闭必须靠EndDialog,而非模态对话框的关闭必须使用DestroyWindow;

    4) 那么这里就要特别强调了,再关闭非模态对话框的时候就绝对!绝对!不能使用基类CDialog的OnOK和OnCancel函数,因为基类的这两个函数底层都会默认调用EndDialog;

!!因此,再使用非模态对话框时如果要使用默认的IDOK和IDCANCEL按钮,就必须!必须!手动覆盖OnOK和OnCancel函数,并删去里面调用基类相应函数的语句,而剩下的数据回送(UpdateData(TRUE))函数也需要自己手动调用了,因为UpdateData(TRUE)是在基类的OnOK和OnCancel函数中调用的,由于删去了这两个函数的调用,UpdateData(TRUE)必须自己手写上去了;

    5) 非模态对话框的对象绝对不能建立在局部栈上,必须建立在堆上!!

         i. 原因是显而易见的,因为模态对话框一旦被激活显示,则其上层窗口将无法被激活而必须等待对话框处理完成并关闭后才能被重新激活,这就导致了直到关闭模态对话框DoModel才会返回值,因此在打开和关闭模态对话框中间的时间段里肯定不会做其它事情,所以模态对话框的对象完全可以建立在局部栈上,因为创建后立即使用,使用完立即就删除;

         ii. 而非模态对话框其实就跟普通窗口差不多,其被显示期间仍然可以激活其上层的父窗口,因此Create一定是立马返回值的,而不是要等待对话框关闭才返回值,否则程序就会卡在这个地方而无法实现重新激活其上层父窗口的功能了,因此非模态对话框在建立之后根本无法推测其什么时候才会关闭(这是和模态对话框最大的不同之处),在关闭之前可能还会利用上层的父窗口完成一些任务,所以非模态对话框的对象绝对不能建立在临时栈上,而必须建立在堆上(new),什么时候想关闭了(按下退出按钮)再临时删除(delete,所以必须在退出按钮的处理程序中使用delete删除对象);

!!一般标准的做法就是在OnCancel中调用DestroyWindow,然后在PostNcDestroy中使用delete删除对象(DestroyWindow会自动触发PostNcDestroy);

    6) 在Win32 API编程中,使用非模态对话框就必须修改消息循环,使用::IsDialogMessage将消息转发给相应的对话框,但是在MFC中这些都已经自动实现了,程序员完全不用关心这些细节;


!!关于CDialog::Create:

        a. 函数原型:BOOL CDialog::Create(UINT nIDTemplate, CWnd* pParent = NULL);

        b. 第一个参数是要绑定的对话框的资源ID,这里就会奇怪了,CDialog在构造函数创建的时候已经绑定过一次资源ID了,为什么这里还要绑定?没办法,就是要再绑定一次;

        c. 第二个参数是所属窗口的指针,如果为NULL就代表父窗口为主框架窗口;


2. DlgDemo2程序的设计:

    1) 功能完全和DlgDemo1一样,只不过不同之处在于,由于DlgDemo2使用的是非模态对话框,可以不关闭并使用上层父窗口,因此这里就要求按下OK按钮后对话框并不关闭,而是直接时上层的视图窗口中的矩形按照用户的输入更新并显示,只有点击Cancel才能关闭对话框;

    2) 因此这里的OK按钮改名为Apply(应用),而Cancel按钮改为Close(关闭),但是这些只是按钮上文本的改变,ID仍然使用MFC默认的IDOK和IDCANCEL;

    3) 由于对话框的对象要建立在堆上,因此就为视图类增加一个新的成员,即COptionsDlg* m_pDlg,在视图类的构造函数中初始化为NULL,然后在Options菜单项的处理函数中new出对象赋给m_pDlg,并且这里还有一个非常重要的陷阱要介绍:那就是非模态对话框打开时还可以玩转上层窗口,这就意味着此时仍能打开上层窗口中的菜单并再次点击Options菜单项,这不就重复建立了多个对话框了吗?所以在Options的处理函数中必须要进行逻辑判断,即m_pDlg非空的时候才能创建对话框,否则就不能(意味着已经打开了一个,不能再重复打开了);

    4) 剩下的最大的难处就是无法在Options的处理函数中将对话框的数据回送到视图类的相应数据中,因为非模态对话框的关闭时间点无法预测,所以Options中Create对话框后剩下的语句会立马顺序执行完,程序会立即退出处理函数,这中间的过程太快,用户根本来不及往对话框中输入数据,因此程序必须通过其它方式将数据回送至视图类:

         i. 思路是使用消息传递的方法进行回送;

         ii. 在OnOK中使用SendMessage函数将数据打包在一个结构中并通过lParam回送至MainFrame中,SendMessage必须通过AfxGetMainWnd调用,所以只能先回送到MainFrame中;

         iii. 接着在MainFrame的该消息的处理程序中利用m_wndView.SendMessage继续将消息传递给视图类;

         iv. 在视图类的相应的消息处理函数中将lParam中包裹的数据打开并复制给其数据成员完成对话框往视图类的数据回送全过程;

!!!同样,在关闭对话框时,在PostNcDestroy中不仅要delete掉自己(即delete this),也希望将m_pDlg也置空,但是m_pDlg是视图类的成员,因此在对话框内部无法访问它,所以还是需要通过消息传递的机制来完成该任务:

         i. 在PostNcDestroy中使用AfxGetMainWnd->SendMessage将关闭消息发送至MainFrame;

         ii. MainFrame再将消息继续传递给CChildView;

         iii. 最后再CChildView中就可以顺利地将自己的成员m_pDlg置为NULL了;

!!因此这里我们需要自创两个消息了,一个就是WM_USER_APPLY,还有一个就是WM_USER_DESTROY,我们可以利用MFC预定义好的WM_USER消息ID来定义它们,WM_USER是MFC规定的用户可以自定义的消息ID的下界,MFC标准规定用户可以自定义的消息ID的范围是0x0400 ~ 0x7FFF,而WM_USER就等于0x0400,因此我们可以定义WM_USER_APPLY为WM_USER + 0x0100等;

!!在给自定义消息ID命名时最好加上USER中缀,以表示该消息是一个用户自定义的消息;


3. COptions类的实现:

    1) .h:

#if !defined(AFX_OPTIONSDLG_H__525087D4_B252_423F_BB70_3F77BE9E4DD5__INCLUDED_)
#define AFX_OPTIONSDLG_H__525087D4_B252_423F_BB70_3F77BE9E4DD5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// OptionsDlg.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// COptionsDlg dialog

class COptionsDlg : public CDialog
{
// Construction
public:
	COptionsDlg(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{
  
  {AFX_DATA(COptionsDlg)
	enum { IDD = IDD_OPTIONS };
	int		m_nHeight;
	int		m_nWidth;
	int		m_nUnits;
	//}}AFX_DATA


// Overrides
	// ClassWizard generated virtual function overrides
	//{
  
  {AFX_VIRTUAL(COptionsDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

	// 必须要覆盖OnOK和OnCancel避免其调用EndDialog函数
	virtual void PostNcDestroy(); // 在其中delete掉自身
	virtual void OnOK();
	virtual void OnCancel();
	//}}AFX_VIRTUAL

// Implementation
protected:

	// Generated message map functions
	//{
  
  {AFX_MSG(COptionsDlg)
		// NOTE: the ClassWizard will add member functions here
	afx_msg void OnReset();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{
  
  {AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
QT 主窗口和非模态对话框切换 以及消息通信 项目中要用到非模态窗口,程序一开始弹出一个主窗口来,点击一个按钮的时候弹出一个非模态窗口,虽然是一个比较简单的需求,但是在实现的过程中有各种问题。列一下自己遇到的问题并且说一下自己的解决方法。 1) 弹出的非模态窗口始终躲在最后面,并且非模态窗口上的控件不能操作。      主窗口是一个模态的窗口,非模态窗口在初始化的时候没有把主窗口作为他的父窗口。所以弹出来的非模态窗口就始终躲在最后面。 阅读详情

相关推荐

别再让网关坑了你!手把手教你排查和修复微信支付V3回调验签中的Base64乱码问题

本文深入解析微信支付V3回调验签中常见的Base64乱码问题,特别是因网关修改Header导致的`IllegalArgumentException`错误。通过实战案例和全链路解决方案,帮助开发者从代码防御、网关配置到监控预警,系统性地排查和修复验签失败问题,确保支付回调的可靠性。

weixin_30329623的博客 446

在VC环境下实现模态与非模态对话框

在VC环境下,分别实现模态与非模态对话框,可以比较它们的代码。

mfc中模态、非模态对话框与主对话框之间的数据交换

点击运行弹出一个对话框,点击DIALOG1按钮弹出一个模态对话框,在该对话框的编辑框输入文本点击确定该对话框消失且输入的文本被显示到主对话框MainDialog中,点击DAILOG2按钮弹出一个非模态对话框,操作现象和模态对话框一样。

MFC中的CDialog

CDialog::CDialog  构造 CDialog 对象。 CDialog::Create  初始化 CDialog 对象。 创建无模式对话框并将它附加到 CDialog 对象。   CDialog::CreateIndirect  在内存(基于的不是资源从创建对话框模板的无模式对话框)。   CDialog::DoModal  调用模式对话框并返回,在执行。   CD

7834

selenium自动化测试入门 浏览器多窗口切换

有时web应用会打开多个浏览器窗口,当我们要定位新窗口中的元素时,我们需要将webDriver的handle(句柄)指定到新窗口。 什么意思? 假设我们打开web应用,在系统运行过程中重新打开一个新窗口(可以是页签,当前浏览器存在两个窗口),这时我们webDriver对浏览器的操作指针(句柄)还再原窗口,如果需要操作新窗口元素就要将handle句柄切换到新窗口。 一、常用方法 driver.current_window_handle 获取当前窗口handle driver.window_handles 获取

公众号:【伤心的辣条】 1417

mfc中父对话框变量获取子对话框控件的变量

转载来自:https://zhidao.baidu.com/question/441623496.html void CGaoyacanxhuDlg::OnButton1() //父对话框中的按钮{ ClnputEDT dlg; dlg.DoModal();//弹出子对话框 if(IDOK) //按下子对话框的确定按钮 { UpdateData(TRUE)

songyimin1208的博客 2806

MFC对话框类的控件中变量如何获取其他对话框类的控件变量的值并使用

——————通过全局变量的使用来获取对话框的指针—————— 问题描述:假设CMyDialog对话框类1,CLoginDialog对话框2对话框1的IDC_STATIC2控件要获取对话框2的控件变量m_name 1.先在CLoginDialog.cpp中声明一个全局变量:CLoginDialog* pLogin;(指的是一个类对象) // 注意:这里的声明必须在CPP文件中的所有函数外部,而...

pengpengbenben的博客 2766

[MFC]DlgDemo1程序基本的模态对话框

1. 接下来所演示的DlgDemo1程序将演示基本的模态对话框的使用:     1) 该程序是基于视图的MFC程序;     2) 视图左上角将显示一个粉红色的矩形;     3) 菜单“文件”中有一个Options菜单项,点击后可以打开一个对话框;     4) 对话框中可以输入想设定的矩形的宽和高(范围必须在1 ~ 128内);     5) 还可以选择显示模式(英寸、厘米、像素,是

Lirx_Tech的专栏 1400

[MFC]PropDemo程序:属性表的应用

1. 属性表的功能和大致创建步骤:     1) 属性表是Windows提供的非常良好的性能之一,用于调节应用程序的相关参数,比如我的电脑右键后点击属性跳出的含有好几个选项卡的的对话框就是属性表;     2) 属性表在Win32 API中的实现相当琐碎,但是MFC有了主结构的支持使得其实现属性表相当容易;     3) 实现属性表的两个MFC类——CPropertySheet和CPrope

Lirx_Tech的专栏 2203

STRINGTABLE PRELOAD DISCARDABLE

STRINGTABLE PRELOAD DISCARDABLE

Y12231819的博客 418

PE文件解析-资源中的字符串结构

一、概述     想要获取一个可执行文件(PE文件)里包含的资源文件,首先要解析可执行文件,得到资源存储的地址及大小,可参考 https://blog.csdn.net/zhyulo/article/details/85717711 。然后,根据资源存储方式,得到各资源的数据内容及其大小,可参考 https://blog.csdn.net/zhyulo/article/details/85930...

zhyulo的博客 1532

MFC对话框类的控件如何获取其他对话框类的控件变量的值

MFC对话框类的控件如何获取其他对话框类的控件变量的值 ——————通过全局变量的使用来获取对话框的指针—————— 问题描述:假设CMyDialog对话框类1,CLoginDialog对话框2对话框1的IDC_STATIC2控件要获取对话框2的控件变量m_name 1.先在CLoginDialog.cpp中声明一个全局变量:CLoginDialog* pLogin; // 注意:这里...

jessica7105的博客 3947

VS2010/MFC编程入门之十(对话框:模态对话框及其弹出过程)

加法计算器对话框程序大家照着做一遍后,相信对基于对话框程序有些了解了,有个好的开始对于以后的学习大有裨益。趁热打铁,鸡啄米这一节讲讲什么是模态对话框非模态对话框,以及模态对话框怎样弹出。        一.模态对话框非模态对话框        Windows对话框分为两类:模态对话框非模态对话框。        模态对话框是这样的对话框,当它弹出后,本应用程序其他窗口将不

Cesar Wu 2163

WM_USER以及自定义消息WM_XXXX的定义 声明 实现

WM_USER     为了防止用户定义的消息ID与系统的消息ID冲突,MS(Microsoft)定义了一个宏WM_USER,小于WM_USER的ID被系统使用,大于WM_USER的ID被用户使用。 自定义消息的步骤编辑 (一)先在头文件中定义自己消息的ID,如 #define WM_MY_FIRST_MESSAGE (WM_USER + 0x001) (二)再声明自己

yangk1990的专栏 7135

自定义消息

<br />在stdafx.h中定义 #define WM_USER_APPLY WM_USER+100<br /><br /><br />然后在MyView.cpp中写代码:ON_MESSAGE(WM_USER_APPLY,OnApply)<br /><br />总是编译不过,提示 'WM_USER_APPLY' : undeclared identifier<br /><br />晕了,看了好多资料,都是这么弄的啊;谁能告诉我怎么弄啊。。。。在线等!谢谢了!<br /> <br /> <br />在My

tiger413的专栏 384

MFC对话框提示“未定义的基类CDialogEx“

问题:MFC对话框提示"未定义的基类CDialogEx" 解决:检查头文件afxdialogex.h 另外注意:#include “stdafx.h” 一定要放在第一行

m0_43605481的博客 3251

MFC在VS2008中如何手动添加消息映射

最近在学习MFC,使用的开发工具是VS2008,当时想在View类中添加一个按钮,需要WM_CREATE这个消息映射,可是View类中默认没有将这个消息添加进去,而我又没有找到自动的添加向导,所以就只能手动添加了。现在将手动添加消息映射的方法记录下来。 (1)在View类的头文件中,在如下所示的地方添加OnCreate()函数: // 生成的消息映射函数 protected: afx_msg

candyliuxj 1万+
上一篇: [MFC]DlgDemo1程序:基本的模态对话框
下一篇: [MFC]PropDemo程序:属性表的应用
Lirx_Tech
博客等级 码龄12年 216粉丝 148原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值