WM_QUIT,WM_CLOSE,WM_DESTROY 消息出现顺序及调用方式

http://bbs.ednchina.com/BLOG_ARTICLE_3005455.HTM

 

VC中WM_CLOSE、WM_DESTROY、WM_QUIT消息出现顺序及调用方式

wxleasyland@sina.com

2012.7

 

wxleasyland试验:

 

一、VC建的标准WIN32-HELLO WORLD程序中,

case WM_DESTROY:

// PostQuitMessage(0);将这行屏蔽

则点关闭,窗口关闭了,但是程序进程还在!要在任务管理器中中止。 

 

二、VC建的标准WIN32-HELLO WORLD程序中,

1. 在WndProc()中加上

case WM_CLOSE:

           WinExec("cmd /k echo WM_CLOSE: ",SW_SHOW);

           break;

 

2. 按右上角的X、点图标\关闭、或者按ALT+F4,都只出现cmd窗,不会关闭程序。

因为原来是执行

  default: 

    return DefWindowProc(hWnd, message, wParam, lParam);

即DefWindowProc来处理WM_CLOSE消息。现在被case WM_CLOSE:拦截了。

 

3. 点菜单里的FILE\EXIT,则就是执行case WM_COMMAND: 里的case IDM_EXIT: DestroyWindow(hWnd); 了。 

不会执行

  case WM_CLOSE:!!!

  DestroyWindow(hWnd);

会销毁窗口,同时发送WM_DESTROY消息直接让WndProc()处理(不经过消息队列)。 

 

三、VC建的标准WIN32-HELLO WORLD程序中,

1. 在WndProc()中加上

case WM_CLOSE:

           WinExec("cmd /k echo WM_CLOSE: ",SW_SHOW);

           return DefWindowProc(hWnd, message, wParam, lParam);

           break;

    case WM_DESTROY:

           WinExec("cmd /k echo WM_DESTROY: ",SW_SHOW);

    PostQuitMessage(0);

           break;

 

2. 按右上角的X、点图标\关闭、或者按ALT+F4,会先出现WM_CLOSE,再出现WM_DESTROY。

 

3. 点菜单里的FILE\EXIT,则只出现WM_DESTROY。 

 

四、VC建的标准WIN32-HELLO WORLD程序中,

如果用PostQuitMessage(0); 则不出现WM_CLOSE。 

也不会出现WM_DESTROY!!!!!!! 窗口会关闭,程序退出。

这应该是正常的,WM_QUIT让GetMessage()为0,从而WinMain()退出,然后操作系统会自动去销毁窗口。

主程序已经没了,所以即使WM_DESTROY出现了也没用。

经试,在PostQuitMessage(0);后面的语句会继续执行到完。

PostQuitMessage只是产生一个WM_QUIT消息到消息队列中并马上返回。 

 

所以标准WIN32程序是:

按右上角的X->出现 WM_CLOSE  销毁窗口->产生WM_DESTROY->运行PostQuitMessage->WinMain退出

菜单点EXIT->出现WM_COMMAND 运行 PostQuitMessage 

 

五、在MFC对话框程序中,试验,是:

1. 先WM_CLOSE(这时窗口仍在显示)->再WM_DESTROY(窗口已经消失)->OnDestroy() 执行完后,程序完全退出 

2. WM_CLOSE不一定会出现。WM_CLOSE  点右上角的X,点图标\关闭,或者按ALT+F4,会出现。   点OK按钮、或者Cancle按钮,或者用任务管理器强行中止,都不会出现。 

3. WM_DESTROY  点右上角的X,点OK按钮、或者Cancle按钮,都会出现。而且晚于WM_CLOSE 出现。   用任务管理器强行中止,则不会出现。 

4. 如果在程序中按一个按钮,里有PostQuitMessage(0); 则不出现WM_CLOSE,但会出现WM_DESTROY,窗口会关闭,程序退出。

经试,按钮函数里,在PostQuitMessage(0);后面的语句会继续执行到完。PostQuitMessage只是产生一个WM_QUIT消息到消息队列中并马上返回。 

5. 如果在程序中按一个按钮,里有PostMessage(WM_DESTROY); 则不出现WM_CLOSE,但会出现WM_DESTROY。窗口不会关闭,还能正常用。

 

所以MFC对话框程序是:

按右上角的X->出现WM_CLOSE  销毁窗口->产生WM_DESTROY -> OnDestroy()执行完后程序退出

点确认或取消按钮 运行PostQuitMessage 

==================================

http://msdn.microsoft.com/en-us/library/windows/desktop/ms632617(v=vs.85).aspx

WM_CLOSE message

Sent as a signal that a window or an application should terminate.

A window receives this message through its WindowProc function.

窗口通过WindowProc函数来接收这个消息!

An application can prompt the user for confirmation, prior to destroying a window,

by processing the WM_CLOSE message and calling theDestroyWindow function only if the user confirms the choice.  

程序中可以让用户确认是否真的要退出。

By default, the DefWindowProc function calls the DestroyWindow function to destroy the window. 

 

WM_DESTROY message

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.  

窗口通过WindowProc函数来接收这个消息!

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_NCDESTROY message

Notifies 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_NCDESTROY是在WM_DESTROY消息之后。

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.    I

n contrast, WM_DESTROY is sent before the child windows are destroyed.

A window receives this message through its WindowProc function.

窗口通过WindowProc函数来接收这个消息!

This message frees any memory internally allocated for the window. 

 

WM_QUIT message

Indicates a request to terminate an application, and is generated when the application calls the PostQuitMessage function.    

This message causes the GetMessage function to return zero.

The WM_QUIT message is not associated with a window and therefore will never be received through a window's window procedure.   

WM_QUIT消息与窗口没有关联,所以窗口处理程序收不到这个消息。

It is retrieved only by the GetMessage or PeekMessage functions.

Do not post the WM_QUIT message using the PostMessage function;  use PostQuitMessage.

  

PostQuitMessage function

Indicates to the system that a thread has made a request to terminate (quit).   It is typically used in response to a WM_DESTROY message.

The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately;  

PostQuitMessage只是产生一个WM_QUIT消息到线程的消息队列中并马上返回。

the function simply indicates to the system that the thread is requesting to quit at some time in the future.

When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system.    

The exit value returned to the system must be the wParam parameter of the WM_QUIT message.

  

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,

WM_PARENTNOTIFY message is sent to the parent. 

 

====================================

引用网络上的:

====================================

WM_QUIT,WM_CLOSE,WM_DESTROY

2010-05-27 10:35:20|  分类: 编程天地|字号 订阅

  WM_DESTROY 是关闭程序

     WM_CLOSE 是关闭窗口

     WM_QUIT 是关闭消息环

WM_CLOSE和WM_DESTROY同属窗口消息,WM_QUIT则不在窗口消息之列。

 

三者先后执行顺序是WM_CLOSE、WM_DESTROY、WM_QUIT,

但需要注意的是MFC窗口默认取消按钮函数OnCancel()是不会触发WM_CLOSE消息,只触发WM_DESTROY。

  

WM_CLOSE:

在系统菜单里选择了“关闭”或者点击了窗口右上角的“X”按钮,你的窗口过程就会收到WM_CLOSE。 

DefWindowProc对WM_CLOSE的处理是调用DestroyWindow。

当然,你可以不让DefWindowProc处理,而是自己处理,例如询问用户是否保存更改等。

如果用户选择“取消”,你忽略此消息,那么程序照常运行;如果用户确认要退出,你就调用DestroyWindow。 

 

WM_DESTROY:

接下来,DestroyWindow完成窗口的清理工作,最后像窗口过程发送WM_DESTROY。 

对于WM_DESTROY,DefWindowProc不会处理。

也就是说,你如果不处理这个消息,虽然你的窗口已经销毁,但进程并不会结束。  

一般处理WM_DESTROY时都是释放资源(例如申请的内存等),然后调用PostQuitMessage。 

 

WM_QUIT:

PostQuitMessage会发送WM_QUIT给消息队列。

注意,WM_QUIT永远不会到达窗口过程,因为GetMessage得到WM_QUIT后就会返回FALSE,

从而结束消息循环,最后进程结束,程序退出。

  

假设使用者执行HELLOWIN,并且使用者最终单击了 Close按钮,或者假设用键盘或鼠标从系统菜单中选择了 Close,

DefWindowProc处理这一键盘或者鼠标输入,在检测到使用者选择了Close选项之后,它给窗口消息处理程序发送一条WM_SYSCOMMAND消息。

WndProc将这个消息传给DefWindowProc。

DefWindowProc给窗口消息处理程序发送一条WM_CLOSE消息来响应之。

WndProc再次将它传给DefWindowProc。

DestroyWindow呼叫DestroyWindow来响应这条WM_CLOSE消息。

DestroyWindow导致Windows给窗口消息处理程序发送一条WM_DESTROY消息。

WndProc再呼叫PostQuitMessage,将一条WM_QUIT消息放入消息队列中,以此来响应此消息。

这个消息导致WinMain中的消息循环终止,然后程序结束。 

 

==========================================================================

 

WM_DESTROY, WM_CLOSE, WM_QUIT 区别 (2009-01-19 18:46:37)转载▼

标签: 预处理程序 close of message box it  分类: Win32API

开始我也很迷糊,后来看了相关的资料,现在明白了,我这里就转一些相关的文章吧.

 

WM_DESTROY, WM_CLOSE, WM_QUIT

WM_DESTROY 是关闭程序的   

WM_CLOSE   是关闭窗口的

WM_QUIT    是关闭消息环的

以下是程序结束的过程:

1、使用者按[File/Close],系统发出WM_CLOSE消息

2、Frame把这条消息直接发给预处理程序

3、预处理程序发出WM_DESTROY消息

4、预处理程序收到WM_DESTROY后执行PostQuitMessage,发出WM_QUIT.

5、GetMessage收到这条消息后就推出消息循环,程序结束。

 

有三个消息看起来差不多,都是处理关闭的事情的。

它们是WM_DESTROY,WM_CLOSE,和WM_QUIT。

它们的确很相似,但你需要知道它们之间的不同!

一个窗口或者应用程序应该被关闭时发出WM_CLOSE消息,当接收到WM_CLOSE消息时,如果你愿意,向用户提出是否真的退出。

你知道让用户作确认或有错误出现或有什么应该注意的事情发生的时候,往往弹出一个消息框。

  插播:

   消息框

   int MessageBox(

   HWND hWnd, // handle of owner window

   LPCTSTR lpText, // address of text in message box

   LPCTSTR lpCaption, // address of title of message box

   UINT uType // style of message box

   );

  

* 当收到WM_CLOSE消息,你可以做两件事儿。

一件是你接受默认的处理返回一个值,你若这样做了,应用程序或窗口按照计划关闭;

再者,你返回0,应用程序或窗口将保持原样。以下是代码的基本部分:

   if (msg == WM_CLOSE)

   {

   if (MessageBox(hMainWindow, "Are you sure want to quit?", "Notice", MB_YESNO | MB_ICONEXCLAMATION) == IDNO)

   return(0);

   // otherwise, let the default handler take care of it

   }

  

* WM_DESTROY消息有点儿不同。它是窗口正在关闭时发出的。

当得到WM_DESTROY消息的时候,窗口已经从视觉上被删除。

 一个主窗口被关闭,并不意味着应用程序结束了,它将在没有窗口的条件下继续运行。

  

* 然而,当一个用户关闭了主窗口,也就意味着他要结束应用程序,

所以如果你希望应用程序结束,在收到WM_DESTROY消息的时候,你必须发出一个WM_QUIT消息。

   WM_QUIT是应用程序结束发出的消息,一般可以看成进程被kill掉的情况.

  

================================= 

 

参考网上的:

 

WM_DESTROY 是关闭程序的

WM_CLOSE 是关闭窗口的

WM_QUIT 是关闭消息环的

 

以下说明程序是如何退出的:

? 使用者选按,于是发出 WM_CLOSE。

? CMyFrameWnd 并没有设置WM_CLOSE 处理常式,于是交给预设之处理常式。

? 预设函数对于WM_CLOSE 的处理方式是呼叫 ::DestroyWindow, 并因而发出WM_DESTROY。

? 预设之WM_DESTROY 处理方式是呼叫::PostQuitMessage,因此发出WM_QUIT。

? CWinApp::Run 收到WM_QUIT 后会结束其内部之讯息回路, 然后呼叫ExitInstance,这是CWinApp 的一个虚拟函数。

? 如果CMyWinApp 改写了ExitInstance , 那么CWinApp::Run 所呼叫的就是CMyWinApp::ExitInstance,否则就是 CWinApp::ExitInstance。

? 最后回到 AfxWinMain,执行 AfxWinTerm,结束程序。

 

 

WM_CLOSE,调用DestroyWindow()

DestroyWindow()又发送WM_DESTROY

响应WM_DESTROY,调用WM_QUIT

GetMessage()发现WM_QUIT,退出程序

 

 

顺序是:

WM_CLOSE --> WM_DESTROY --> WM_QUIT

 

 

DefWindowProc收到WM_CLOSE后,调用DestroyWindow把窗口清除,

DestroyWindow本身又会发出WM_DESTROY,

程序的WM_DESTROY的标准反应是调用PostQuitMessage,发出WM_QUIT,然后结束程序 

WM_DESTROY是windows在关闭你的窗口时发给你的窗口的,你自己发有不可预料的后果。 

 

====================================

WM_DESTROY 和 WM_NCDESTROY

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) 我们再说

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值