目录
1、MFC对话框退出时,有几种方式:
2、MFC窗口程序三个退出程序消息
3、如何在工程中重写OnDestroy()这些函数
4、各种消息投递函数
(1)点击IDOK按钮退出:先调用OnOK(),然后是OnDestory(),最后是PostNcDestroy();
(2)点击IDCANCEL按钮退出:先调用OnCancel(),然后是OnDestory(),最后是PostNcDestroy();
(3)点击右上角的关闭按钮退出:先OnClose(),然后是OnCancel(),再然后是OnDestory() ,最后是PostNcDestroy();
(1)WM_CLOSE、(2)WM_DESTROY、(3)WM_QUIT
只有关闭了消息循环,应用程序的进程才真正退出(在任务管理器里消失)。
win32应用程序的完整退出过程:点击窗口右上角的关闭按钮,发送WM_CLOSE消息。此消息处理中调用DestroyWindow函数,发送WM_DESTROY消息。此消息处理中调用PostQuitMessage(0)函数,发送WM_QUIT消息到消息队列中。GetMessage捕获到WM_QUIT,返回0,退出循环(应用程序真正退出)。
注意:按照上述正常流程,WM_QUIT是不会到达窗口过程的。(因为在GetMessage截获了WM_QUIT消息之后,程序已经彻底退出了!)
(1)首先了解下,消息发送的2种方式:
1)PostMessage将消息放入消息队列后马上返回;
2)SendMessage直到窗口过程处理完消息后才返回;
(2)三个消息的区别:
1)WM_CLOSE:关闭应用程序窗口
在系统菜单里选择了“关闭”或者点击了窗口右上角的“X”按钮,你的窗口过程就会收到WM_CLOSE。
2)WM_DESTROY:关闭应用程序
处理完WM_CLOSE消息后,接下来,DestroyWindow完成窗口的清理工作,最后像窗口过程发送WM_DESTROY。对于 WM_DESTROY,DefWindowProc不会处理。也就是说,你如果不处理这个消息,虽然你的窗口已经销毁,但进程并不会结束。一般处理 WM_DESTROY时都是释放资源(例如申请的内存等),然后调用PostQuitMessage。
3)WM_QUIT:关闭消息循环
PostQuitMessage会发送WM_QUIT给消息队列。注意,WM_QUIT永远不会到达窗口过程,因为GetMessage得到WM_QUIT后就会返回FALSE,从而结束消息循环,最后进程结束,程序退出。
注意:
WM_CLOSE是在窗口关闭前发送的,你还可以决定是否真的关闭窗口 ;
WM_DESTROY是在窗口关闭过程中发送的,窗口已被移出屏幕 ;
但是WM_CLOSE只是把窗口关闭,但是程序依然还在,接下来还可以WM_DESTROY窗口相关的资源,因为窗口的this指针还可以用,要是先WM_DESTROY再WM_CLOSE,发现this已经不可用了,所以要谨记销毁的顺序。(先WM_CLOSE,后WM_DESTROY,最后WM_QUIT)
(1)首先知道这个系统函数,对应的是什么消息
OnClose():ON_WM_CLOSE() 关闭应用程序窗口
OnDestroy():ON_WM_DESTROY() 关闭应用程序
以下是一些常用的消息宏示例:
ON_WM_LBUTTONDOWN():处理鼠标左键按下消息。
ON_WM_KEYDOWN():处理键盘按键按下消息。
ON_WM_PAINT():处理窗口重绘消息。
ON_WM_SIZE():处理窗口大小改变消息。
ON_WM_TIMER():处理定时器消息。
ON_WM_COMMAND():处理菜单或工具栏命令消息。
(2)把对应的消息加到MESSAGE MAP里面:
当你想要将ON_WM_DESTROY()添加到消息映射中时,你需要使用宏BEGIN_MESSAGE_MAP和END_MESSAGE_MAP来定义消息映射。然后,在消息映射中使用ON_WM_DESTROY()宏来处理窗口销毁消息。
下面是一个示例代码,展示了如何将ON_WM_DESTROY()添加到消息映射中:
// 在头文件中声明消息映射宏
class CMyWnd : public CWnd
{
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnDestroy();
};
// 在源文件中定义消息映射
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
ON_WM_DESTROY()
END_MESSAGE_MAP()
// 处理窗口销毁消息的函数
void CMyWnd::OnDestroy()
{
// 在此处添加窗口销毁时的处理逻辑
//todo
// 调用基类的处理函数
CWnd::OnDestroy();
}
在上述示例中,首先在头文件中使用DECLARE_MESSAGE_MAP()宏声明消息映射。然后,在源文件中使用BEGIN_MESSAGE_MAP宏开始定义消息映射,并使用ON_WM_DESTROY()宏将窗口销毁消息与处理函数关联起来。最后,实现OnDestroy()函数来处理窗口销毁时的逻辑,并在函数中调用基类的处理函数CWnd::OnDestroy()。
通过这样的方式,当窗口接收到销毁消息时,将自动调用OnDestroy()函数进行处理。
(1)SendMessage:发送消息给指定的窗口过程;直到窗口过程处理了消息才返回。
(2)PostMessage:将消息放入消息队列(与指定窗口创建的线程相关)中;无需等待消息处理,立即返回。
不能发送WM_QUIT消息,此消息只能由PostQuitMessage函数发送。
(3)PostThreadMessage:发送消息给指定线程的消息队列;无需等待线程处理消息,立即返回。
此函数发送的消息和窗口是无关的。我们只需指定线程ID就OK了,但要保证线程已创建,否则会失败。
(4)GetMessage:从调用线程的消息队列中取消息。
当第二个参数为NULL时,它检索以下两种消息:
a、属于调用线程的任何窗口的消息;
b、由PostThreadMessag投递给该调用线程的消息。
(5)PeekMessage:功能同GetMessage。区别是:
GetMessage:直到一个匹配了过滤条件的消息,被放到消息队列中才返回。
PeekMessage:不管消息是否放入队列,立即返回。
(6)DispatchMessage:派遣消息给相应的窗口过程。
(7)TranslateMessage:转换虚拟键信息到字符消息。