VC++窗口关闭全过程

窗口关闭全过程 

一、对于非模态窗口,必须重载OnCancel函数,在函数中调用DestroyWindows()方法,且不能调用基类的函数。因为基类函数中调用的是 EndDialog()方法。而OnClose()也会调用OnCancel()方法。另外想通过OnOK关闭对话框,也必须同样处理,不能直接用默认方法。

   1 、只有点击标题栏的叉号图标、在桌面任务栏右键-关闭、Alt+F4、标题栏最左边图标上单击-关闭,发送WM_CLOSE消息,触发 OnClose()。

 所以对于非模态窗口,其关闭过程

OnClose()->OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy() ,                 ->仅表示时间先后而已

而OnNcDestroy()最后又调用了PostNcDestroy()

  2、回车、ESC、点击“确定”或“取消”,都不会调用OnClose()

  一般来说,OnOK是对ID_OK的响应, OnCancel是对IDCANCEL的响应. 前者对应键盘的Enter, 后者对应Esc。

  OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy()

  OnOK()->DestroyWindow()->OnDestroy()->OnNcDestroy()

  OnNcDestroy()最后又调用了PostNcDestroy()

 

  OnOK()与OnCancel()
       如前面所述,OnOK是对ID_OK的响应, OnCancel是对IDCANCEL的响应. 前者对应键盘的Enter, 后者对应Esc。

  OnOK()和OnCancel()都调用了EndDialog().OnOK调用了UpdateData(TRUE)而OnCacel()没有调用。
  在OnOK()结束刚进入DestroyWindow时,其实窗口并未关闭,依然可以用ShowWindow显示出来


  模态的对话框可以用EndDialog来销毁, 非模态的对话框要用DestroyWindow来


  EndDialog()
  该函数清除一个模态对话框,并使系统中止对对话框的任何处理

 

  对于DoModal出来的窗口,可以使用默认的OnOk()和OnCancel()来处理。其基类方法中会调用EndDialog()方法。

  它只能在对话框的消息处理函数里使用,并且这个函数调用之后,没有立即就删除对话框的,而是设置了操作系统里的结束标志。当操作系统查检到有这个标志时,就去删除对话框的消息循环,同时也去释放对话框占用的资源。其实对话框的生命周期是这样的,先由函数DialogBox创建对话框,这样函数 DialogBox完成创建对话框但还没有显示前会发出消息WM_INITDIALOG,让对话框有机会初始化上面所有窗口或控件的显示,比如设置文本框的字符串等。最后当用户点出确定或者取消的按钮,就收到两个命令IDOK或IDCANCEL,这时就可以调用函数EndDialog来结束对话框的生命。
见《Windows API一日一练(18)EndDialog函数》http://blog.csdn.net/caimouse/archive/2007/07/30/1716140.aspx

 

  DestroyWindows()

  CWnd::DestroyWindow销毁m_hWnd(必须非空),同时销毁其菜单、定时器,以及完成其他清理工作。
  ::DestroyWindow使将被销毁的窗口失去激活、失去输入焦点,并发送WM_DESTROY、WM_NCDESTROY消息到该窗口及其各级子窗口。如果被销毁的窗口是子窗口且没有设置WM_NOPARENTNOTFIY风格,则给其父窗口发送WM_PARENTNOFITY消息。

 

  CWnd::OnDestroy()  和 CWnd::OnNcDestroy() 以及 CWnd::PostNcDestroy()

  CWnd::OnDestroy()  调用缺省处理函数Default()。

  CWnd::OnNcDestroy() 首先判断当前线程的主窗口是否是该窗口,如果是且模块非DLL,则发送WM_QUIT消息,使得程序结束;
然后,判断当前线程的活动窗口是否是该窗口,如果是则设置活动窗口为NULL;
     接着,清理Tooltip窗口,调用Default由 Windows缺省处理WM_NCDESTROY消息,UNSUBCLASS,把窗口句柄和MFC

窗口对象分离(Detach);

    最后,调用虚函数PostNcDestoy()。

    见《MFC教程_应用程序的退出》http://www.vczx.com/tutorial/mfc/mfc6.php

 

    总结一下的话,DestroyWindows可以理解成是主动的,OnDestroy是被动的.  
    用户主动调用DestroyWindows来关闭窗口,而当窗口被关闭时OnDestroy函数被调用!  
    你调用DestroyWindow(),那么系统就会发一个WM_DESTROY的消息,这个消息会调用OnDestroy()函数.

    DestroyWindow()     ------>   WM_DESTROY + WM_NCDESTROY   ------>OnDestroy()   
                                         发消息                                                               响应消息映射

 

   另外,如果要在退出时提示用户,应在 OnClose()或OnOK()、OnCancel()中作出处理,而不能在响应WM_DESTROY时处理

,因为那是窗口已经销毁了(但应用程序并没有退出)。在处理WM_DESTROY消息时,系统会调用

 PostQuitMessage()向消息队里投递WM_QUIT消息,结束消息循环。(见《VC++深入详解》P18)

 

   最后注意一个问题,通常我们创建一个非模态窗口时,可能会这样写

{

   CDialog * pWnd = new CMyDialog();

   pWnd->Create(……);

   pWnd->ShowWindow(SW_SHOW);

}

   很肯能是在一个模块或者一个函数中创建窗口,但是却无法知道什么时候关闭窗口。而pWnd也只是作为一个局部变量。那么如何对它进行析构呢?

通常这样是重载虚函数PostNcDestroy()来实现

void CMyDialog::PostNcDestroy()
{
       CDialog::PostNcDestroy();
       delete this;
}

 为什么把对话框类的delete this放在PostNcDestroy中而不是OnNcDestroy

   这是因为OnNcDestroy只被已建立的窗口调用。如果建立窗口失败(如PreCreateWindow), 则没有窗口处来发送

WM_NCDESTROY消息。PostNcDestroy是在对象窗口被完全删除, 在OnNcDestroy后,甚至在窗口建立失败之后

调用的。

 

    以上是学习MFC窗口关闭销毁等相关知识时的一些总结。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值