MFC模态模式对话框,MessageBox消息循环原理,定时器TIMER消息响应处理函数重入

更新时间:2023-07-08 08:00:40 阅读: 评论:0

MFC模态模式对话框,MessageBox消息循环原理,定时器
TIMER消息响应处理函数重⼊
2020.10
⼀、MessageBox和定时器TIMER
MessageBox是Win32 API全局函数,必须指定标题和样式。共有4个参数。没有⽗窗⼝就NULL。返回值是int,看选什么按钮。
⽐如:MessageBox( NULL, "选什么?", "标题", MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
如何教育孩子::表⽰全局函数。
在MFC中,可使⽤全局API函数::MessageBox(NULL,………),⼦程序会被暂时中断在这个MessageBox上!其后的代码⽆法运⾏,等到MessageBox返回后会继续运⾏代码。但⽗窗⼝可以被点出来,其它程序段可以运⾏,⽐如其它按钮。  因为NULL没有指定⽗窗⼝,所以不会使⽗窗⼝⽆效!
MFC中直接使⽤MessageBox,则是使⽤CWnd类的MessageBox⽅法,这时⽗窗⼝⽆法被点出来,等同于::MessageBox(m_hWnd,………)。同时⼦程序被暂时中断在这个MessageBox上。但关了其中⼀个消息框,则⽗窗就可以点出来了。 原理应该是m_hWnd 指定了⽗窗,MessageBox使⽗窗⼝⽆效,然后进⼊⾃⼰的消息循环,关闭时,使⽗窗有效。
在TIMER的响应函数中,有MessageBox的话,则会暂时中断在这个MessageBox上,但当下个时间到时,⼜会出现⼀个新的MessageBox,且也是暂时中断在这个MessageBox上...  即出现了多个消息响应函数的例程!!多次重⼊!!每个例程都中断在MessageBox上,MessageBox返回后,例程会继续执⾏到结束!  各个消息框都是⽗窗的⼦窗,所以是平等的,所以各个消息框都可以点出来,但⽗窗点不出来。  可以关闭任何⼀个消息框,但是这个重⼊例程MessageBox之后的代码不会运⾏,要按倒序关闭其后的消息框后才会运⾏。
⼆、消息框原理分析:参考《深⼊探讨MFC消息循环和消息泵》和调试时断点看代码
注意:
MFC是单线程运⾏的。
MFC内部是有消息循环。
消息循环的DispatchMessage()会阻塞,需要等窗⼝消息处理函数处理完了以后,才会返回。
窗⼝消息处理函数是由操作系统调⽤的。
窗⼝消息处理函数是可以多次重⼊的!类似函数⾃⼰可以嵌套⼀样。
单线程运作:阻塞→重⼊→阻塞→重⼊。。。
时间到→操作系统放WM_TIMER到线程队列→MFC消息循环DispatchMessage()阻塞→系统调⽤窗⼝消息处理函数OnTimer()处理完→消息循环继续
操作系统⼀到时间就会放WM_TIMER到线程队列。因为是单线程,如果窗⼝消息处理函数如果⼀直没处理完,则WM_TIMER会堆积在队列中。
OnTimer()中有消息框时情况就复杂了。MessageBox内部是⼀个模态对话框,模态对话框有消息循环。换号短信
时间1到,系统放WM_TIMER到队列
环保科技小制作
MFC程序主消息循环DispatchMessage()阻塞
世道变了
操作系统调⽤第1个OnTimer()
MessageBox⽣成⼀个模态对话框对象1,显⽰出来,运⾏对话框内的消息循环1
时间2到,系统放WM_TIMER到队列
MessageBox1的消息循环1 DispatchMessage()阻塞
操作系统调⽤第2个OnTimer() (函数重⼊了!)
MessageBox⽣成⼀个模态对话框对象2,显⽰出来,运⾏对话框内的消息循环2
时间3到,MessageBox2的消息循环2 DispatchMessage()阻塞,操作系统调⽤第3个OnTimer() (函数重⼊了!)。。。
即⼀个串⼀个,只有最后⼀个消息框的消息循环在起作⽤,前⾯的消息循环全部阻塞了。
OnTimer()是主窗(⽗窗)函数,所以各个MessageBox都是⼦窗,各个⼦窗是都可以点出来,但⽗窗会被⼦窗失效掉,所以⽗窗点不出来。
当任何⼀个⼦窗关掉后,会使⽗窗有效,这时⽗窗可以点出来了。
三、消息框对话框关闭时原理
天猫魔盒关闭时是怎样?为什么关闭时是按倒序在执⾏代码?
MessageBox⽆法调试进⼊内部看代码,就⽤模态对话框来代替吧:
CAboutDlg dlgAbout;
dlgAbout.DoModal();  // DoModal就会⽣成模态对话框
CDialog::DoModal()⾥⾯有CreateRunDlgIndirect()。
CWnd::CreateRunDlgIndirect⾥⾯有RunModalLoop()。
CWnd::RunModalLoop⾥⾯有消息循环AfxPumpMessage(),这⾥⼀直进⾏消息循环!循环中还有CWnd::ContinueModal()判断
m_nFlags标志看是否需要退出循环。
当关闭对话框时,如果点“确定”就是触发CAboutDlg::OnOK(),点“X”就是触发CAboutDlg::OnCancel()。 这两个函数进去都是运⾏EndDialog()。
CDialog::EndDialog⾥⾯先运⾏EndModalLoop(),然后是运⾏::EndDialog()。
CWnd::EndModalLoop()⾥⾯有
m_nFlags &= ~WF_CONTINUEMODAL;  把标志设置成不再继续运⾏对话框
PostMessage(WM_NULL);  发送⼀个空消息以确保消息队列中有消息,这样消息循环不会因为没有消息⽽阻塞
::EndDialog()⽆法进⼊看代码,功能是把对话框关了不显⽰,然后把⽗窗激活。
把对话框关了不显⽰,这样我们就点不到这个对话框,就不会再触发窗⼝消息处理函数了。
所以清楚了:
点击关闭其中⼀个消息框时(⽐如消息框1),⽣成了⼀个消息(这个消息是关联这个消息框1的),“最后⼀个”消息框(⽐如消息框3)的消息循环DispatchMessage()这个消息后,操作系统重⼊消息框1对象的OnOK()或OnCancel(),设置m_nFlags标志成不再继续运⾏,发送⼀个消息框1的消息WM_NULL,以及⽤::EndDialog()把消息框1销毁了并把⽗窗激活。
这个时候,这个消息框1对象仍存在,它的消息循环仍阻塞在DispatchMessage()中,只有等消息框3、消息框2的消息循环退出、OnTimer()退出后,才会从DispatchMessage()返回,然后发现m_nFlags不需要继续运⾏消息框了,于是退出消息循环,然后退出消息框对象,然后退出OnTimer(),消息循环就⼜交还给MFC程序的主循环了。
四、⾮模式对话框
⾮模对话框没有⾃⼰的消息循环,也不会使⽗窗失效。
⽤Create()来显⽰⾮模对话框,函数会⽴刻返回,所以必须要⽤new,这样对话框对象就保留在内存中。
四季的形成
高通骁龙660如果⽤CAboutDlg dlgAbout;,则处理函数结束后,对象也被销毁,即对话框⼀显⽰就被关掉了。
CAboutDlg* pdlg = new CAboutDlg;
pdlg ->Create(IDD_ABOUTBOX);    //⾮模式对话框,函数⽴刻返回,⽆⾃⼰的消息循环望风而逃
pdlg->ShowWindow(SW_SHOW);
所以,关键是消息循环、消息处理函数重⼊。

本文发布于:2023-07-08 08:00:40,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1072692.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:消息   循环   对话框   函数   出来
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图