在发送 WM_QUIT消息时,要使用PostMessage发送,否则,窗口已经关闭,但任务管理器中进程还存在。可以通过 pDlg->PostMessage(WM_QUIT);或DWORD dwThreadId = GetWindowThreadProcessId(pDlg->GetSafeHwnd(),NULL);
PostThreadMessage(dwThreadId,WM_QUIT,0,0);
结束进程。
WM_DESTROY消息有点儿不同。它是窗口正在关闭时发出的。
当得到WM_DESTROY消息的时候,窗口已经从视觉上被删除。
三个退出程序消息:WM_CLOSE、WM_DESTROY、WM_QUIT
一个主窗口被关闭,并不意味着应用程序结束了,它将在没有窗口的条件下继续运行。
然而,当一个用户关闭了主窗口,也就意味着他要结束应用程序,所以如果你希望应用程序结束,在收到WM_DESTROY消息的时候,你必须发出一个WM_QUIT消息。
WM_QUIT是应用程序结束发出的消息,一般可以看成进程被kill掉的情况.
PostQuitMessage是向系统发出要终止线程的请求, 在终止线程前系统还要做些内存的清理工作, 我们关闭一个程序时是发送WM_CLOSE消息, 然后调用DestroyWindow函数,调用DestroyWindow时系统会向程序发WM_DESTROY消息,终止整个程序
用自己的话总结一下:WM_CLOSE 消息发出的时候,用户可以根据自己的意愿来选择到底是否关闭,WM_DESTORY 是真的关闭一个窗口。WM_QUIT是退出一个应用程序。
/////////////////////////////////////////////////
WM_CLOSE:关闭应用程序窗口
WM_DESTROY:关闭应用程序
WM_QUIT:关闭消息循环
只有关闭了消息循环,应用程序的进程才真正退出(在任务管理器里消失)。
win32应用程序的完整退出过程:点击窗口右上角的关闭按钮,发送WM_CLOSE消息。此消息处理中调用DestroyWindow函数,发送WM_DESTROY消息。此消息处理中调用PostQuitMessage(0)函数,发送WM_QUIT消息到消息队列中。GetMessage捕获到WM_QUIT,返回0,退出循环(应用程序真正退出)。
tips:按照上述正常流程,WM_QUIT是不会到达窗口过程的。(因为在GetMessage截获了WM_QUIT消息之后,程序已经彻底退出了!)
MFC应用程序的完整退出过程:点击窗口右上角的关闭按钮,或选择【File/Close】,发出 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,结束程序。
附加:当调用DestroyWindow函数后,操作系统就会进行一系列的删除动作,先发送WM_DESTROY消息,接着发送WM_NCDESTROY消息。如果这个窗口还有子窗口或者是其它窗口的所有者,就需要给所有子窗口发送删除消息。
WM_QUIT是唯一可以使GetMessage(&msg,NULL,0,0)返回假值的消息.
相关代码分析:
//主函数中进入消息循环的代码片断
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg); //将消息进行处理一下
DispatchMessage(&msg); //再将消息变量msg传给windows,让windows来调用消息处理函数
}
如果把GetMessage(&msg,NULL,0,0)改为GetMessage(&msg,hWnd,0,0),则发现关闭应用程序后,任务管理器中仍有该程序的进程,且占用大量的内存,why?
msdn中的原因解释;对于GetMessage(&msg,hWnd,0,0),当第二个参数无效时,此函数返回值为-1。对于上述循环来说,此while条件为真,因此进入死循环,进程无法退出。