VC中的定时器与消息机制

7 篇文章 0 订阅
4 篇文章 0 订阅

     用VC编程,最重要的是要熟悉消息机制。但这一点好像并不是那么容易搞懂,至少现在我还不是完全明白,只有遇到问题时才想办法把它查清楚。

     案例:通过SetTimer设置一个定时器,在OnTimer中,设置弹出一个对话框,如MessageBox("Hello")。你会发现对话框会不断的弹出,而不是阻塞在那里?如果你对这个问题很清楚,并且不会认为这是多线程机制,那恭喜你,你一定对Windows消息机制比较熟悉,也比我知道的要多,那你就多给我挑挑毛病吧。否则,希望我的这篇文章能对你有所帮助。

     首先说明,这个结果绝对不是多线程引起的。有同学开始认为是多线程,每次OnTimer调用单独开一个线程。但我打开任务管理器跟踪发现线程并没有增加。于是我上csdn请教高手,经过一个下午的讨论,才算弄明白,其核心问题还在于消息机制。

     如果用Windows API写过程序,你应该明白在WinMain中有一个消息循环,不断的取消息,转换,重新发送消息,代码如下:

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
   if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
}

     通过GetMessage得到一个消息,如果没有消息,则会阻塞到这里。这个消息从哪里来?操作系统。操作系统为每个线程创建一个消息队列(在收到第一个消息时真正创建),而每个线程可以包括多个窗口。也就是说,这个消息队列包括了该线程中所有的窗口消息。因此,通过GetMessage获取消息时,当第二个参数为NULL时,会将同线程中其他窗口的消息也得到。然后进行消息转换,首先转换快捷键为相应的消息,然后转换你的键盘操作,通过消息转换将其解析为到底是输入字符,还是控制键。转换完成后,再通过DispatchMessage来分发消息。分发给谁?操作系统。操作系统收到消息后,调用消息所属窗口的WndProc函数,根据消息的类型进行处理。处理完成后,操作系统将控制权再转交给程序,完成Dispatch,继续进行消息循环。

     这里需要注意的就是,每个窗口的消息循环不只是处理本窗口的消息,也将同线程下其他窗口的消息也处理掉了。这就是为什么当OnTimer弹出一个对话框后还可以继续弹出对话框,是因为弹出的MessageBox本身的消息循环接替了上一个窗口循环的工作。如此递归调用,这也是为什么消息机制支持嵌套调用。这里有一个问题,DispatchMessage为什么不由程序本身来调用,而非要经过操作系统?这就是出于便捷考虑,如果直接处理,那么一个窗口必须有权限访问其他窗口的处理函数,不然怎么实现处理其他窗口的调用呢?这就是回调函数的优点。

     另外一个问题,程序在执行消息时,会不会在一条消息处理没有完毕时,就去处理下一条?比如不断的调用OnTimer?答案是不会,除非在处理函数中有一个消息循环,类似于本文的案例。否则,只可能在一条消息处理完毕后,才执行下一条。

     OnTimer的定时是不精确的,并且WM_TIMER消息的优先级非常低,总是添加到消息队列的尾部。并且同一个定时器消息只会在队列中出现一次,类似于WM_PAINT消息。你不用担心在OnTimer处理函数中执行太久后收到一堆的WM_TIMER消息,但你也要注意,你的WM_TIMER消息已经丢失了一些。

     OnTimer本身的使用这里就不说了,网上的例子很多,希望看到这篇文章能有所收获!


原文地址:http://hi.baidu.com/sangwf/blog/item/55ae90ee6c8a1c2b2cf534f6.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值