首先来了解几个基本概念:

消息:在了解什么是消息先来了解什么是事件。事件可分为几种,由输入设备触发的,比如鼠标键盘等等。由窗体控件触发的,比如button控件,file菜单等。还有就是来自Windows内部的事件。这三种称为事件。而消息,是由事件翻译而来的。事件产生消息。

从数据结构角度来讲,消息是一种结构体。结构如下:


  1. typedef struct tagMSG
  2. {
  3. HWND hwnd; //窗口句柄。
  4. UINT message;//消息类型。
  5. WPARAM wParam;//32位附加信息。
  6. LPARAM lParam;//32位附加信息。
  7. DWORD time;//消息发送时间。
  8. POINT pt;//消息发送时,鼠标所在位置。
  9. }MSG;

消息队列消息队列有两种,分为系统消息队列和应用程序消息队列产生的消息首先由Windows系统捕获,放在系统消息队列,再拷贝到对应的应用程序消息队列。32/64位系统为每一个应用程序维护一个消息队列

消息循环:系统为每个应用程序维护一个消息循环,消息循环会不断检索自身的消息队列。每有一个消息,就用GetMessage()取出消息。


  1. while(GetMessage (&msg, NULL, 0, 0))//Windows消息循环。
  2. {
  3. TranslateMessage (&msg) ;//翻译消息,如按键消息,翻译为WM_CHAR
  4. DispatchMessage (&msg) ;//分发消息到对应窗口
  5. }

GetMessage具有阻塞机制。当消息队列中没有消息时,程序非忙等,而是让权等待。当收到WM_QUIT时,GetMessage返回false,循环停止,同时应用程序终止。

消息处理:DispatchMessage()把取出来的消息分配给相应的窗口或线程,由窗口过程处理函数DefWindowProc()处理。

=========================================================================

以上简要地介绍了消息队列,消息循环与消息处理的概念。

Windows的应用程序靠消息驱动来实现功能。而消息驱动靠消息机制来处理。消息机制就是由消息队列,消息循环,消息处理构成的。

那么,消息机制是如何运作的呢?

当用户运行一个应用程序,通过对鼠标的点击或键盘按键,产生一些特定事件。由于Windows一直监控着I/O设备,该事件首先会被翻译成消息,由系统捕获,存放于系统消息队列。经分析,Windows知道该消息应由那个应用程序处理,则拷贝到相应的应用程序消息队列。由于消息循环不断检索自身的消息队列,当发现应用程序消息队列里有消息,就用GetMessage()取出消息,封装成Msg()结构。如果该消息是由键盘按键产生的,用TranslateMessage()翻译为WM_CHAR消息,否则,用DisPatchMessage()将取出的消息分发到相应的应用程序窗口,交由窗口处理程序处理。Windows为每个窗体预留了过程窗口函数,该函数是一个回掉函数,由系统调用,应用程序不能调用。程序员可以通过重载该函数处理我们”感兴趣”的消息。对于不感兴趣的消息,则由系统默认的窗口过程处理程序做出处理。

下面看这么一张图:

这张图很好地解释了消息机制的运行原理。

当运行程序->事件操作引发消息->消息先存在系统消息队列->再存入到应用程序消息队列->用消息循环提取消息->处理消息->再返回消息队列....


  1. while(GetMessage(&Msg, NULL, 0, 0) > 0)
  2. {
  3. TranslateMessage(&Msg);
  4. DispatchMessage(&Msg);
  5. }

上面代码的执行过程为:
1. 消息循环调用GetMessage()从消息队列中查找消息进行处理,如果消息队列为空,程序将停止执行并等待(程序阻塞)。
2. 事件发生时导致一个消息加入到消息队列(例如系统注册了一个鼠标点击事件),GetMessage()将返回一个正值,这表明有消息需要被处理,并且消息已经填充到传入的MSG参数中;当传入WM_QUIT消息时返回0;如果返回值为负表明发生了错误。
3. 取出消息(在Msg变量中)并将其传递给TranslateMessage()函数,这个函数做一些额外的处理:将虚拟键值信息转换为字符信息。这一步实际上是可选的,但有些地方需要用到这一步。
4. 上面的步骤执行完后,将消息传递给DispatchMessage()函数。DispatchMessage()函数将消息分发到消息的目标窗口,并且查找目标窗口过程函数,给窗口过程函数传递窗口句柄、消息、wParam、lParam等参数然后调用该函数。
5. 在窗口过程函数中,检查消息和其他参数,你可以用它来实现你想要的操作。如果不想处理某些特殊的消息,你应该总是调用DefWindowProc()函数,系统将按按默认的方式处理这些消息(通常认为是不做任何操作)。
6. 一旦一个消息处理完成,窗口过程函数返回,DispatchMessage()函数返回,继续循环处理下一个消息。

/***************************************************************************************************

新建一个win32 Application的默认代码如下:

程序入口                                          //intWINAPI WinMain
定义窗口类                                      //typedef struct tagWNDCLASSA
注册窗口类                                      //RegisterClass(&wndclass))
生成窗口                                          //CreateWindow
更新窗口                                          //ShowWindow(hwnd,iCmdShow);
显示窗口                                          //UpdateWindow(hwnd);
消息循环                                          //while(GetMessage(&msg,NULL,0,0))
窗口消息处理(回调函数)                     //LRESULT CALLBACK WndProc

消息循环的代码如下:
while(GetMessage(&Msg, NULL, 0, 0) > 0) 

    TranslateMessage(&Msg);    //转换
    DispatchMessage(&Msg);     //分发
}

这里有几个概念,容易混淆:
1.系统:
特指windows操作系统

2.应用程序:
指一个程序,比如QQ,或者酷狗之类的都算一个应用程序

3.窗口:
每个应用程序都 可以拥有窗口,而且可以有多个,但一般会有一个主窗口。例如QQ的主窗口,但是QQ也有很多类似于设置窗口的子窗口,这些窗口都属于QQ应用程序。

4.消息:
window系统定义了很多种消息,例如,单击鼠标、改变窗口尺寸、按下键盘,这些操作都会使Windows发送一个消息给应用程序。消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息

5.消息循环:
window系统的一种消息机制

6.消息队列:
是属于线程的,是windows系统为线程创建并维护的一个队列,用于存放各类消息。 系统自身维护一个系统消息队列,然后还为每个GUI线程线程维护一个线程专门消息队列。

7.线程:
每个线程默认是没有消息队列的,线程只有在第一次调用用户接口时(比如创建窗口,或者是操作UI元素时),系统才为其创建消息队列。一个应用程序可以有多个线程,但只能有一个UI线程,默认为主线程,其他子线程是无法操作UI并创建UI元素的。这是windows规定的

windows消息循环的详细过程:

1.我们创建完win32应用程序,当用户通过对鼠标,键盘操作应用程序时,由于Windows一直监控着I/O设备,该事件首先会被转化成消息,由windows系统捕获,存放于系统消息队列。

2.Windows系统知道该消息应由哪个应用程序处理,然后拷贝到相应的应用程序消息队列。同时将该消息从系统消息队列中删除。

3.应用程序的消息循环不断在执行,此时,调用GetMessage()从消息队列中查找消息,发现了该消息,GetMessage()将返回一个正值,并获取到了该消息Msg;PS:如果消息队列为空,程序将停止执行并等待(程序阻塞)。

4. 然后取出消息(Msg)并将其传递给TranslateMessage()函数,这个函数做一些额外的处理:将虚拟键值信息转换为字符信息。这一步实际上是可选的,但有些地方需要用到这一步。

5. 上面的步骤执行完后,将消息MSG传递给DispatchMessage()函数。DispatchMessage()函数将消息再给windows系统,由windows系统找到目标窗口并分发给该窗口,调用消息对应的窗口过程函数,既窗口的WinPro函数,让WinPro函数处理。WinPro函数可以允许我们对不同的消息做特定的处理,若不处理的话,则会调用DefWindowProc函数,做默认处理,所以为什么默认代码中WinPro的类型是CallBack(回调),因为不是我们主动调用的,是系统回调的

6. 一旦一个消息处理完成,窗口过程WinPro函数返回,DispatchMessage()函数返回,应用程序的消息循环继续while循环,Window系统继续监控各类消息,重复上述步骤

Windows消息循环机制详细概述相关推荐

  1. 详谈Windows消息循环机制

    一直对windows消息循环不太清楚,今天做个详细的总结,有说错的地方,请务必指出. 用VS2017新建一个win32 Application的默认代码如下: 这里有几个概念,容易混淆: 1.系统: ...

  2. android 结束if循环_Android Handler 消息循环机制

    前言 一问起Android应用程序的入口,很多人会说是Activity中的onCreate方法,也有人说是ActivityThread中的静态main方法.因为Java虚拟机在运行的时候会自动加载指定 ...

  3. Windows消息响应机制之四:PostQuitMessage和GetMessage函数

    Windows是消息驱动的操作系统.在Windows环境下编程必须熟练掌握Windows消息响应机制.  今天在练习Win32编程时碰到一个关于GetMessage函数的问题.这个问题之前一直没有引起 ...

  4. Windows 消息循环(1) - 概览

    本文从消息循环是如何驱动程序的这个角度,对 Windows 消息循环进行概览性介绍. 使用 EN5 课件获得更好的阅读体验: [希沃白板5]课件分享 : <Windows培训 - 消息循环> ...

  5. Android的消息循环机制:Handler

    前言 Android的消息机制主要是指Handler的运行机制,对于大家来说Handler已经是轻车熟路了,可是真的掌握了Handler?本文主要通过几个问题围绕着Handler展开深入并拓展的了解. ...

  6. C++-Windows消息循环GetMessage/TranslateMessage/DispatchMessage

    1.windows消息循环 if (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg); //消息转化DispatchMessa ...

  7. 深入理解Windows消息循环

    理解消息循环和整个消息传送机制对Windows编程来说非常重要.如果对消息处理的整个过程不了解,在windows编程中会遇到很多令人困惑的地方. 什么是消息(Message) 每个消息是一个整型数值, ...

  8. android 消息循环机制--looper handler

    Looper类说明   Looper 类用来为一个线程跑一个消息循环. 线程在默认情况下是没有消息循环与之关联的,Thread类在run()方法中的内容执行完之后就退出了,即线程做完自己的工作之后就结 ...

  9. Windows消息循环理解及窗体创建步骤

    首先理解一句话:"Windows"向应用程序发送了一条消息.这里是指Windows调用了该程序内部的一个函数. 当UpdateWindow被调用后,新建的窗口在屏幕便完全可见了.此 ...

最新文章

  1. C# MoreLinq 扩展安装
  2. html设置 header,http设置header
  3. 33行代码AC——例题6-5 移动盒子(Boxes in a Line, UVa 12657)——解题报告
  4. [LeetCode]15. 3Sum
  5. netty ssl 服务器
  6. flash player 10 音频新API使用:调节音高(pitch)
  7. Java 工程师成神之路!
  8. meterpreter--收集系统信息
  9. Linux之POSTFIX邮件服务
  10. 利用图片的 onerror 事件载入默认图片
  11. 关于URL大小写问题
  12. Dialogue System for Unity文档中英对照版(简雨原创翻译)第六篇(音序器相关,语音同步)
  13. 十五届恩智浦智能车-四十天做四轮-调车日记
  14. SpringBoot整合activiti7,demo示例
  15. 烟大计算机考研二战,以坚持铺就考研之路——记经济管理学院考研优秀个人程林林...
  16. android仿微信图片上传进度,Android开发之模仿微信打开网页的进度条效果(高仿)...
  17. uniapp ios原生插件开发之component
  18. 免费打印 免费抓娃娃 多次关注微信公众号-吸粉神器 技术实现细节
  19. python3.4勾股定理代码_用于解答算法题目的Python3代码框架
  20. 定义主函数main()

热门文章

  1. matlab 小波变换_连续小波变换实现方法的总结及其程序详解
  2. java chat_使用 Java 创建聊天客户端-1
  3. 稀疏矩阵十字链表类java_稀疏矩阵的十字链表存储表示
  4. java 对象 转为繁体_Java实现将数字转化为繁体汉字表示
  5. 旋转矩阵求旋转角度_(加餐)欧拉角及矩阵旋转
  6. 最受欢迎的女友职业排行榜Top10
  7. 都说外国电工布线牛到不行?今天就看看中国电工最强布线!
  8. android监听通知消息 脚本,Bash玩转脚本4之搞一套完整的Android反编译与分包工具...
  9. 最大均值差异java_MATLAB最大均值差异(Maximum Mean Discrepancy)
  10. tornado项目搭建_Python深度学习原理及项目实战2019年3月21日上海举办