你能帮我嘛?解读windows经典问题---消息循环

liuzu2016 2012-08-11 08:16:12



run这个虚函数,是消息循环所在


for循环内部有一个while循环,



while (bIdle &&
!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
// call OnIdle while in bIdle state
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}


问题1:请问 何时回跳过这个循环(即不执行,bIdle为true了。)

假设对于单线程程序, 那么怕是死活会在这个循环里了,知道 程序退出,才结束这个while循环!!!


问题2:注意这里使用的是peekmessage, 没有了我们常见的getmessage

peekmessage并没有取出消息,那么当消息产生的时候,消息队列里岂不是消息越来越多?




run的代码

// main running routine until thread exits
int CWinThread::Run()
{


// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;

// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
// call OnIdle while in bIdle state
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}

// phase2: pump messages while available
do
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())
return ExitInstance();

// reset "no idle" state after pumping "normal" message
if (IsIdleMessage(&m_msgCur))
{
bIdle = TRUE;
lIdleCount = 0;
}

} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
}

ASSERT(FALSE); // not reachable
}



问题3: windows如何判断是idle消息(idle英文是空闲,

当调用函数getmessage或者peekmessage的时候,线程内部就有很多消息了,

什么是空闲消息呢?)



BOOL CWinThread::IsIdleMessage(MSG* pMsg)
{
// Return FALSE if the message just dispatched should _not_
// cause OnIdle to be run. Messages which do not usually
// affect the state of the user interface and happen very
// often are checked for.

// redundant WM_MOUSEMOVE and WM_NCMOUSEMOVE
if (pMsg->message == WM_MOUSEMOVE || pMsg->message == WM_NCMOUSEMOVE)
{
// mouse move at same position as last mouse move?
if (m_ptCursorLast == pMsg->pt && pMsg->message == m_nMsgLast)
return FALSE;

m_ptCursorLast = pMsg->pt; // remember for next time
m_nMsgLast = pMsg->message;
return TRUE;
}

// WM_PAINT and WM_SYSTIMER (caret blink)
return pMsg->message != WM_PAINT && pMsg->message != 0x0118;
}
...全文
113 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
相信你看了前两个问题的解答,第三个问题应该很明显了
// phase1: check to see if we can do idle work
当消息队列为空的时候,我们就处理空闲,也就没必要进入下一步的真正的消息处理过程了
// phase2: pump messages while available
当消息队列不为空的时候,我们处理消息队列里的消息
  • 打赏
  • 举报
回复
问题2
// phase1: check to see if we can do idle work
PeekMessage就是为了看一下这个消息队列是否非空,有没有执行OnIdle的可能
真正的处理消息是在后面的PumpMessage里,这个和GetMessage是一个作用
  • 打赏
  • 举报
回复
先说第一个问题
lIdleCount是一个长整形计数器,当消息队列为空时,他开始自增
OnIdle是一个定义于CWinThread类的虚函数
virtual BOOL OnIdle( LONG lCount );
当lIdleCount不为0时,会有响应的执行,并返回FALSE

你可以继承CWinThread类重写OnIdle函数来创建自己的线程的空闲处理代码
或者对你目前的程序的App类的OnIdle进行重写来实现空闲时的操作
不要想的复杂了
liuzu2016 2012-08-12
  • 打赏
  • 举报
回复
// phase2: pump messages while available
do
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())
return ExitInstance();

// reset "no idle" state after pumping "normal" message
if (IsIdleMessage(&m_msgCur))
{
bIdle = TRUE;
lIdleCount = 0;
}

} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));


亲,你在吗?

你看到while里面的东西了嘛?

pm_noremove啊, 意味着只看消息,不取消息, 是否意味着 队列的中的消息只会越来越多。





[Quote=引用 3 楼 的回复:]

PeekMessage接收到exit消息就退出来了!
[/Quote]
昨夜无风 2012-08-12
  • 打赏
  • 举报
回复
PeekMessage接收到exit消息就退出来了!
傻X 2012-08-11
  • 打赏
  • 举报
回复
你这里3个问题。
1个问题就可以写一面。

看过这个了?
http://www.eefocus.com/article/07-05/4139110405376157.html

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧