Windows 是一个消息驱动的操作系统。一个消息由一个消息名称(UINT 类型)和两个参数
(WPARAM,LPARAM)构成。当用户进行了输入或是窗口的状态发生改变时,系统会发送消息到某
一个窗口。例如当菜单选中之后会有WM_COMMAND 消息发送,WPARAM 的高字中
(HIWORD(wParam))是命令的ID 号,对菜单来说就是菜单ID。当然用户也可以定义自己的消息名称,
也可以利用自定义消息来发送通知和传送数据。
一个消息必须由一个窗口接收。在窗口的消息处理函数中可以对消息进行分析,对自己感兴趣的
消息进行处理。例如希望对菜单选择进行处理,那么可以定义对WM_COMMAND 进行处理的代码,
如果希望在窗口中进行图形输出就必须对WM_PAINT 进行处理。
事实上为了应付那些没有被响应的消息,Windows 为窗口编写了默认的窗口消息处理函数,这个

窗口过程将负责处理那些程序中没有处理的消息。正因为有了这个默认窗口过程,程序员才可以利用
Windows 的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发
送,而程序员都可以不予理睬让系统自己去处理。
说到消息就不能不说窗口句柄,系统通过窗口句柄在整个操作系统中唯一标识一个窗口。发送消
息时必须指定一个窗口句柄表明该消息由哪个窗口接收。而每个窗口都会有自己的窗口消息处理函数,
所以用户的输入就会被正确的处理。
下面这段伪代码演示如何在窗口过程中处理消息:

LONG windowProc(HWND hWnd,UINT uMessageType,WPARAM w,LPARAM l)
{switch(uMessageType){//使用SWITCH 语句将各种消息分开case WM_PAINT: //处理绘制消息
        Redraw();break;case WM_TIMER: //处理定时器消息
        OnTimer();break;case WM_LBUTTONDOWN: //处理鼠标左键按下的消息
        OnLButtonDown ();break;default:defaultWndProc(); //缺省的其他消息处理函数break;}
}    

在Windows 操作系统中维护着一个或多个消息队列,所有产生的消息都被放入到队列中。系统在
队列中每次取出一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的消息循环。每一个运
行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口
过程。而在没有消息时消息循环就将控制权交给系统,从而使Windows 可以同时进行多个任务。下面
的伪代码演示了消息循环的用法:

while (1)
{id =GetMessage ();if (id == WM_QUIT)break ;DispatchMessage ();
}    

初看这段代码容易给人一种错觉,这是一个忙等待(busy waiting)的消息循环,因为采用了while(1)
的循环方式,而忙等待是个非常糟糕的东西。
而实际上绝大部分时间里这个程序是在阻塞状态, 因为当程序没有收到消息通知时
GetMessage 就不会返回,所以也就不会占用系统的CPU 时间。GetMessage 函数的阻塞调用是这
段代码的关键部分。
上面这段代码的意思是调用GetMessage 函数从消息队列中取出消息,然后调用DispatchMessage
将消息发送给窗口消息处理程序。
在16 位的系统中只有一个消息队列,所以系统必须等待当前任务处理消息后才可以发送下一消息
到相应程序,如果一个程序陷入死循环或是耗时操作时,系统就会得不到控制权。这种多任务系统也
称为协同式的多任务系统。Windows 3.X 就是这种系统。而32 位的系统中每一个运行的程序都会有一
个消息队列,所以系统可以在多个消息队列中转换而不必等待当前程序完成消息处理就可以得到控制
权。这种多任务系统就称为抢先式的多任务系统,Windows 95/NT 就是这种系统。
消息能够被分为队列化的和非队列化的。队列化的消息是由Windows 放入程序消息队列中的。在
程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化的消息在Windows 调用窗口时直
接送给窗口消息处理程序。也就是说,队列化的消息被发送给消息队列,而非队列化的消息则发送给
窗口消息处理程序。任何情况下,窗口消息处理程序都将获得窗口所有的消息——包括队列化的和非
队列化的。窗口消息处理程序是窗口的消息中心。
队列化消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN 和WM_KEYUP 消息)、
击键产生的字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)
的形式给出。队列化消息还包含时钟消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息
(WM_QUIT)。
在许多情况下,非队列化消息来自调用特定的Windows 函数。例如,当WinMain 调用CreateWindow
时,Windows 将建立窗口并在处理中给窗口消息处理程序发送一个WM_CREATE 消息。当WinMain
调用ShowWindow 时,Windows 将给窗口消息处理程序发送WM_SIZE 和WM_SHOWWINDOW消息。
虽然Windows 程序可以多线程执行,但消息队列只为窗口消息处理程序在该执行中的窗口处理消
息。换句话说,消息循环和窗口消息处理程序不是并发执行的。当一个消息循环从其消息队列中接收
一个消息,然后调用DispatchMessage 将消息发送给窗口消息处理程序时,直到窗口消息处理程序将
控制传回给Windows,DispatchMessage 才能结束执行。
当然,窗口消息处理程序能调用给窗口消息处理程序发送另一个消息的函数。这时,窗口消息处
理程序必须在函数调用传回之前完成对第二个消息的处理。那时窗口消息处理程序将处理最初的消息。
例如,当窗口过程调用UpdateWindow 时,Windows 将调用窗口消息处理程序来处理WM_PAINT 消息。
窗口消息处理程序处理WM_PAINT 消息结束以后,UpdateWindow 调用将把控制传回给窗口消息处理
程序。
在工程中经常还会有这样的需求,即要求程序在空闲的时候执行某种额外的操作或运算。实际上
在Windows 中有很多闲置时间,在这个时间内,所有消息队列为空,Windows 只停在一个小循环中等
待键盘或者鼠标输入。能否在闲置时间内获得控制,从而做某种操作或运算,并且只在有消息加入程
序的消息队列之后才释放控制呢?这就是PeekMessage 函数的目的之一。下面是PeekMessage 调用的
一个例子:

PeekMessage (&msg, NULL, 0, 0, PM_REMOVE) ;

前面的4 个参数(一个指向MSG 结构的指针、一个窗口句柄、两个值指示消息范围)与GetMessage
的参数相同。将第二、三、四个参数设定为NULL 或0 时,表明想让PeekMessage 传回程序中所有窗
口的所有消息。如果要将消息从消息队列中删除,则将PeekMessage 的最后一个参数设定为
PM_REMOVE。如果不希望删除消息,那么可以将这个参数设定为PM_NOREMOVE。
GetMessage 不将控制传回给程序,它一直处于阻塞状态,直到从程序的消息队列中取得消息,但
是PeekMessage 总是立刻传回,而不论一个消息是否出现。当消息队列中有一个消息时,PeekMessage
的传回值为TRUE,并且将按通常方式处理消息。当队列中没有消息时,PeekMessage 传回FALSE。
可以将如下所示的消息循环:

while (1)
{id =GetMessage ();if (id == WM_QUIT)break ;DispatchMessage ();
}    

替换为下面的循环:

while (TRUE)
{if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)){TranslateMessage (&msg) ;DispatchMessage (&msg) ;}else{// 完成其他额外的工作
    }
}
return msg.wParam ;    

如果PeekMessage 的传回值为TRUE,则消息按通常方式进行处理。如果传回值为FALSE,则在
将控制传回给Windows 之前,还可以做一点工作。
需要注意的是,不能用PeekMessage 从消息队列中删除WM_PAINT 消息,实际上GetMessage 并
不从消息队列中删除WM_PAINT 消息。从队列中删除WM_PAINT 消息的唯一方法是令窗口显示区域
的失效区域变得有效,这可以用ValidateRect 和ValidateRgn 或者BeginPaint 和EndPaint 对来完成。如
果在使用PeekMessage 从队列中取出WM_PAINT 消息后,同平常一样处理它,那么就不会有问题了。
所不能作的是使用如下所示的程序代码来清除消息队列中的所有消息:

while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) ;

这行代码从消息队列中删除WM_PAINT 之外的所有消息。如果队列中有一个WM_PAINT 消息,
程序就会永远地陷在while 循环中。

Windows 消息机制相关推荐

  1. Windows消息机制学习笔记(三)—— 消息的接收与分发

    Windows消息机制学习笔记(三)-- 消息的接收与分发 要点回顾 消息循环 消息队列 消息的接收 GetMessage 实验1:理解GetMessage 第一步:编译并运行程序A 第二步:编译并运 ...

  2. Windows消息机制学习笔记(二)—— 窗口与线程

    Windows消息机制学习笔记(二)-- 窗口与线程 要点回顾 消息从哪里来? 实验一:Spy++捕获消息 实验二:消息捕获 消息到哪里去? 窗口在哪? 实验:分析CreateWindowExW 窗口 ...

  3. Windows消息机制学习笔记(一)—— 消息队列

    Windows消息机制学习笔记(一)-- 消息队列 基本概念 实验一:使用代码画出最简单窗口 第一步:编译并运行以下代码 第二步:查看运行结果 第三步:使用其它窗口对其进行覆盖,观察效果 总结 消息队 ...

  4. windows消息机制和Linux,Windows消息机制初谈 (转)

    Windows消息机制初谈 (转)[@more@]是一个消息的OS,什么是消息呢?我很难说得清楚,也很难下一个定义(谁在嘘我),我下面从不同的几个方面讲解一下,希望大家看了后有一点了解. 1.消息的组 ...

  5. Windows消息机制-PreTranslateMessage

    PreTranslateMessage作用和使用方法 Windows消息机制的流程: A. 操作系统接收应用程序的窗口消息,将消息投递到该应用程序的消息队列中 B. 应用程序在消息循环中调用GetMe ...

  6. Windows消息机制详解-5

    一. 什么是消息 在解释什么是消息之前,我们先讨论一下程序的执行机制问题.大体上说,程序按照执行机制可以分为两类: 第一类是过程驱动.比如我们最早接触编程时写的C程序,又或者单片机程序.这类程序往往预 ...

  7. windows消息机制详解-3

    1. 引言 Windows 在操作系统平台占有绝对统治地位,基于Windows 的编程和开发越来越广泛. Dos 是过程驱动的,而Windows 是事件驱动的[6],这种差别的存在使得很多Dos 程序 ...

  8. 【转】深入理解Windows消息机制

    转自:https://blog.csdn.net/liulianglin/article/details/14449577 今天我们来学一学Windows消息机制,我们知道在传统的C语音程序中,当我们 ...

  9. SendMessage和PostMessage及Windows消息机制简介

    SendMessage: The SendMessage function sends the specified message to a window or windows. It calls t ...

  10. Windows 消息机制浅析

    Windows 消息机制浅析 1.       Windows 的历史 中国人喜欢以史为鉴,而事实也确实是,如果你能知道一件事情的来龙去脉,往往可以更容易地理解事物为什么会表现为当前这样的现状.所以, ...

最新文章

  1. 简历写的好,就赢了90%的人了
  2. 文治者必有武备不然长大了挨欺负_“有文事者必有武备,有武备者必有文事。”出自司马迁的《史记》。...
  3. 5.cocos2dx中关于draw绘图,声音和音效,预加载,播放与停止Vs暂停和恢复,音量控制
  4. 【PAT甲级 环最短距离】1046 Shortest Distance (20 分) Java、C++
  5. 方法的重载(overload)和重写(override)的区别
  6. django 默认查询条件_Python之Django系列-创建第一个应用-4
  7. c语言中字符数字加'0',C语言中的NULL与转义字符'\0'以及数值0的关系
  8. IDEA中Spring MVC实现图片上传并显示
  9. dorado7-发布
  10. mysql innodb_file_format_innodb_file_format设置
  11. ML--HMM(隐马尔可夫模型及python的实现1)
  12. 华为USG防火墙配置命令
  13. 相机成像时间与曝光时间的关系
  14. Interproscan linux版本详细安装教程及运行报错解决方案
  15. php后门检测工具,phpStudy后门如何检测和修复
  16. 制作自己的docker镜像
  17. sw转cad映射文件_SolidWorks转CAD映射文件使用教程(附下载)
  18. SW2021软件安装教程
  19. iPad 3.2.1越狱成功!
  20. Windows 10 RTM版已正式结束官方支持

热门文章

  1. SQL按字段分组取最大(小)值记录(重复记录)
  2. Android 通过软引用实现图片缓存,防止内存溢出
  3. ASP.NET URL重写浅析
  4. Tensorflow随笔——命令行参数
  5. std::thread的使用
  6. html 星空效果,html5 canvas炫酷旋转银河系星空背景特效
  7. python随机森林变量重要性_随机森林如何评估特征重要性【机器学习面试题详解】...
  8. openim php sdk,imsdk_restapi-php-sdk
  9. Python-Matplotlib可视化(8)——图形的输出与保存
  10. 2018年度报告单_2018年度最佳在线IT课程