随笔-60  评论-262  文章-1  trackbacks-0
WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别?

原文链接 What is the difference between WM_DESTROY and WM_NCDESTROY?

在窗口销毁时有两个紧密关联的 windows 消息, 就是 WM_DESTROY 和 WM_NCDESTROY. 它们有何区别?

区别就是 WM_DESTROY 消息是在窗口销毁动作序列中的开始被发送的, 而 WM_NCDESTROY 消息是在结尾. 这在你的窗口拥有子窗口时是个重大区别. 如果你有一个带子窗口的父窗口, 那么消息的发送序列 (在没有怪诞行为影响的前提下) 就像这样:

hwnd = parent, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_NCDESTROY
hwnd = parent, uMsg = WM_NCDESTROY

注意, 父窗口是在子窗口被销毁之前收到 WM_DESTROY 消息, 在子窗口被销毁之后收到 WM_NCDESTROY 消息.

两个销毁消息, 一个在开头, 一个在结尾, 这意味着, 对于你自己的模块, 你可以通过处理相应的消息来执行清理操作. 例如, 如果有些东西必须在开头清理, 那么你可以使用 WM_DESTROY 消息.

WM_NCDESTROY 消息是你窗口将会收到的最后一个消息 (在没有怪诞行为影响的前提下), 因此, 这里是做 "最终清理" 的最佳场所. 这就是为什么我们的 new scratch 程序会一直等到 WM_NCDESTROY 销毁它的实例变量, 才会返回.

与这两个销毁消息配对的, 是 WM_CREATE 和 WM_NCCREATE 这两个类似的消息. 与 WM_NCDESTROY 是你窗口收到的最后一条消息类似, WM_NCCREATE 消息是第一条消息, 这是一个创建你自己的实例变量的好地方. 需要注意的是, 如果你导致 WM_NCCREATE 消息返回失败, 那么所有你将收到的消息就只有 WM_NCDESTROY 了; 不会有 WM_DESTROY 消息了, 因为你根本就没有收到相应的 WM_CREATE 消息.

那么什么是我一直在暗示的 "怪诞行为" 呢? 下一次 (When the normal window destruction messages are thrown for a loop) 我们再说.


posted on 2008-01-23 13:10 free2000fly 阅读(8439) 评论(10)  编辑 收藏 引用

评论:
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2008-01-24 08:10 | Enoch
期待下一篇。  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2008-01-24 18:58 | ood
很好,明白了  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2008-01-30 14:55 | 天之骄子
哦。
请问PostNcDestroy()函数在什么时候调用呢?在响应WM_DESTROY或者WM_NCDESTROY消息之后呢,还是什么时候?  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2008-01-31 11:50 | free2000fly
@天之骄子
这是 MFC 里的函数, 不是一个 Win32 API, 看看以下 MFC 源代码:

// WM_NCDESTROY is the absolute LAST message sent.
void CWnd::OnNcDestroy()
{
// ...
// call special post-cleanup routine
PostNcDestroy();
}

void CWnd::PostNcDestroy()
{
// default to nothing
}

你就明白了, 作为虚函数的 PostNcDestroy 函数, 可以在你的派生类里被你改写, 做你自己的清理. 但你不能自己调用这个函数, 而是由 MFC 框架在其内部调用.
  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2008-09-20 17:24 | vfdff
WM_CLOSE是在窗口关闭前发送的,你还可以决定是否真的关闭窗口
WM_DESTROY是在窗口关闭过程中发送的,窗口已被移出屏幕
你的程序的错误在于调用 CMDIFrameWnd::OnClose(); 后窗体已经
被Destroy掉了,this指针指向的窗口对象已经不存在了,所以出错
也就是处理顺序是先处理WM_CLOSE(窗口未关闭),后处理WM_DESTROY(窗口已关闭)
CMDIFrameWnd::OnClose();后的部分不执行,如需要执行,可放到OnDestroy()中  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2008-09-22 08:28 | free2000fly
@vfdff
你可看明白了, 我抄的是 mfc 的源代码, 没出错. 你说的没错, 但说话的对象错了.  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2008-10-07 00:10 | vfdff
@free2000fly
但说话的对象错了.???  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2011-03-22 09:23 | 冯绣慧
大师:
请求您的指教。
我发调用了DestroyWindow(hwnd);函数之后为什么我在过程函数里面收不到WM_DESTROY消息,只能收到WM_NCDESTROY消息。
请加我QQ,望告之。  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2011-03-22 09:25 | 冯绣慧
QQ:582528935  回复  更多评论
  
# re: WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别? (译) 2011-03-26 10:33 | free
@冯绣慧
在哪里调用 DestroyWindow(hwnd); 的?
http://blogs.msdn.com/oldnewthing/archive/2005/07/27/443824.aspx

  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理