zoukankan      html  css  js  c++  java
  • VC中的定时器与消息机制

        用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 本身的使用这里就不说了,网上的例子很多,希望看到这篇文章能有所收获!

  • 相关阅读:
    IntelliJ Idea 常用快捷键列表
    IPv6地址存储
    一文看懂java的IO流
    AchartEngine的柱状图属性设置
    绘制图表改变其大小
    在Android上用AChartEngine轻松绘制图表
    Android 图表绘制 achartengine 示例解析
    封装一个类搞定90%安卓客户端与服务器端交互
    安卓图表引擎AChartEngine(三)
    AchartEngine 的学习
  • 原文地址:https://www.cnblogs.com/dongzhiquan/p/1994911.html
Copyright © 2011-2022 走看看