天下

记录修行的印记

窗口销毁的相关函数与消息

窗口销毁的相关函数与消息
DestroyWindow函数
DestroyWindow销毁窗口的正牌函数。
DestroyWindows的MSDN说明如下:
The DestroyWindow function destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain).
If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window.
DestroyWindow also destroys modeless dialog boxes created by the CreateDialog function.
A thread cannot use DestroyWindow to destroy a window created by a different thread.
If the window being destroyed is a child window that does not have the WS_EX_NOPARENTNOTIFY style, a WM_PARENTNOTIFY message is sent to the parent.
DestroyWindow的处理过程总结要点如下: 
1. 向父窗口发送WM_PARENTNOTIFY消息(仅当窗口具有WS_EX_NOPARENTNOTIFY样式); 
2. 向窗口发送WM_DESTROY消息; 
3. 使窗口转入非活动状态,移除键盘焦点; 
4. 销毁子窗口(应该是通过递归调用DestroyWindow完成); 
5. 销毁目标窗口资源:销毁菜单,清空线程的消息队列,销毁与窗口过程相关的定时器,解除窗口对剪贴板的拥有权,打断剪贴板器的查看链; 
6. 向窗口发送WM_NCDESTROY消息;
上述条目大致从前往后执行(1、2、3的顺序不一定,5、6的顺序不一定)。依据是: 
1. 根据WM_PARENTNOTIFY说明:销毁窗口时,系统在任何销毁窗口的操作执行前发送WM_PARENTNOTIFY至父窗口; 
2. 根据WM_DESTROY说明:此消息先被发送至目标窗口,然后发送给目标窗口的所有子窗口,处理此消息时,可以假定所有子窗口还存在着; 
3. 根据DestroyWindow说明:函数先销毁子窗口及所拥有的窗口,然后销毁目标窗口; 
4. 根据WM_NCDESTROY说明:与WM_DESTROY相反的是,此消息在所有子窗口销毁之后发送; 没有去看汇编代码,只是根据各个MSDN说明来大致推测的,基本够用了吧。
根据MSDN说明,不能在非创建线程上调用DestroyWindow;若要在其它线程上关闭窗口,不可以直接调用DestroyWindow(错误"拒绝访问"),也不可以只发送WM_DESTROY,因为DestroyWindow才能完整的关闭窗口,WM_DESTROY消息只是关闭流程的一部分,甚至是最"无用"的一部分--WM_DESTROY只是用户响应的接口,而真正清理窗口的工作由DestroyWindow的其它部分完成。 
要在其它线程上关闭窗口,可以向窗口发送WM_CLOSE消息,若窗口过程未在WM_CLOSE的处理中取消关闭操作,则DefWindowProc会默认调用DestroyWindow(彼时自然是在窗口的创建线程上)。
WM_CLOSE消息
WM_CLOSE的MSDN说明如下:
An application can prompt the user for confirmation, prior to destroying a window, by processing the WM_CLOSE message and calling the 
DestroyWindow function only if the user confirms the choice.
By default, the DefWindowProc function calls the DestroyWindow function to destroy the window.
WM_CLOSE消息提供取消关闭窗口操作的接口,也可以作为窗口关闭的关联处理的统一入口。点击窗口右上角的关闭按钮将导致窗口收到WM_CLOSE消息,一般情况下,菜单中的Exit项的处理代码中也应向窗口发送WM_CLOSE消息,这样可以使无论何种方式触发的窗口关闭操作,其程序流均会流入WM_CLOSE消息的处理过程。在WM_CLOSE中可以对程序状态进行确认,自动或由用户确认是否取消关闭操作。 
与接下来的其它消息相比,WM_CLOSE的特殊之处在于它发生在销毁过程启动之前。用户处理完WM_CLOSE消息后,如未取消,则DefWindowProc将调用DestroyWindow来关闭窗口,一旦进入DestroyWindow,则关闭过程将不可逆转。
WM_DESTROY消息
WM_DESTROY的MSDN说明如下:
The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen.
This message is sent first to the window being destroyed and then to the child windows (if any) as they are destroyed. During the processing of the message, it can be assumed that all child windows still exist.
A window receives this message through its WindowProc function.
If the window being destroyed is part of the clipboard viewer chain (set by calling the SetClipboardViewer function), the window must remove itself from the chain by processing the ChangeClipboardChain function before returning from the WM_DESTROY message.
最后一句值得注意,不过对剪贴板涉猎不多,暂且不究。
WM_PARENTNOTIFY消息
WM_PARENTNOTIFY的MSDN说明如下:
The WM_PARENTNOTIFY message is sent to the parent of a child window when the child window is created or destroyed, or when the user clicks a mouse button while the cursor is over the child window. When the child window is being created, the system sends WM_PARENTNOTIFY just before the CreateWindow or CreateWindowEx function that creates the window returns. When the child window is being destroyed, the system sends the message before any processing to destroy the window takes place.
A window receives this message through its WindowProc function.
WM_NCDESTROY消息
WM_NCDESTROY的MSDN说明如下:
The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY message. WM_DESTROY is used to free the allocated memory object associated with the window. The WM_NCDESTROY message is sent after the child windows have been destroyed. In contrast, WM_DESTROY is sent before the child windows are destroyed. A window receives this message through its WindowProc function. This message frees any memory internally allocated for the window.
关于WM_DESTROY与WM_NCDESTROY,从各种说明可以看出,一个大约充当关闭操作启动时的通知接口,一个大约充当关闭操作完成时的通知接口。这也是我认为在DestroyWindow的处理流程中,第6条在第5条之后的原因。 
另外,说明中有个值得一提的地方在于:WM_DESTROY用于释放关联到(associated to)窗口的已分配内存对象,WM_NCDESTROY用于释放内部为窗口分配的(internally allocated for)内存。 可以想象,后者应当指窗口的内核数据,但前者则有各种可能,菜单资源?GDI资源?异或是子窗口资源?这个就不好说了。 而且,根据这两句话的表述,似乎这两个清理操作是在消息的处理过程中发生的,然而显然又不是由用户来完成的工作,那么就应当是在DefWindowProc中完成的了。为什么不直接拿到Destroywindow中来执行呢?
ActiveX控件的销毁
销毁控件的最好方法是销毁宿主窗口。可以通过调用 CWindow::DestroyWindow 或 DestroyWindow API 显式地进行销毁,或者让宿主窗口的父级窗口的毁坏导致其死亡,从而隐式地进行销毁。这些方法的任何一种都将安全地销毁寄宿的控件。请注意,CAxWindow 对象的毁坏"不会"导致基础"AtlAxWin7"窗口的毁坏。 
来自:http://technet.microsoft.com/zh-cn/query/cc468138

posted on 2015-08-01 14:24 天下 阅读(504) 评论(0)  编辑 收藏 引用 所属分类: Win32


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿(4)

随笔分类(378)

随笔档案(329)

链接

最新随笔

搜索

最新评论