设为首页 收藏本站
查看: 907|回复: 0

[经验分享] windows 消息队列

[复制链接]

尚未签到

发表于 2018-6-22 17:35:39 | 显示全部楼层 |阅读模式
  点击链接加入群【ゞ***闖兲ゞ】:
  许多朋友都不会使用MSDN LIBRARY(虽然MSDN 跟 MSDN LIBRARY 不是一回事,但是下文中还是简写为MSDN),其实它是非常重要的东西。
  其实所有的说明都可以在MSDN中查到。
  环境:VS2008 + SP1补丁    MSDN LIBRARY 2008 + SP1 补丁
  打开 这个版本的 MSDN 后,可以看到如图的界面
DSC0000.jpg

  在最左下角,我们可以看到  Contents 、Index 、Help Favorites 等选项卡,较为重要的就是 Contents 和 Index ,其中 Contents 是将MSDN 中的内容 以 相关性 进行 分类 ,而 Index 主要是用来进行 具体函数功能 查询的,比如 我们切换到 Index 选项卡页面,然后在上面 looking for 里输入 任意一个函数名: CreateWindow ,然后一双击 下面列举出来的 CreateWindow ,就可以看到 右侧 有了函数 的信息了。其实一个函数是可能有多种平台都对它进行了实现的,比如这个函数,WINCE平台下也可以使用,这就需要使用 上图中 左下角 的 Index Results 功能了,这里会列举出所有的相关信息。
  其实我想大家应该都会这种方法 ,关于 消息映射 ,如果想要 系统的了解一下 应该怎么办呢? 只看 GetMessage 这样的函数 是看不出什么来的,我们需要定位到 MSDN 中对 消息映射的讲解与说明的地方,系统的学习一下,然后才能了解。其实其它的功能也有,比如 关于窗口的,关于控件的,关于MFC的,关于C语言和C++语言还有C#等语言的,.NET类库,关于系统方面的,比如线程,进程,系统服务,动态链接库,其实MSDN中都可以找到说明的,只是很多人都不知道如何去找。
  下面请看下面两图,然后依次展开 图中的 节点  ,注意要选择 Contents
DSC0001.jpg

DSC0002.jpg

  好,我相信大家已经看到了消息和消息队列的部分了。打开看看吧。
DSC0003.jpg

  可以看到它大概分为 这么几个部分 : OverViews 概览,里面又有关于和使用两个小分支,关于是比较重要的部分,描述了关于 消息队列中的 常用的概念 及认识 ,使用主要是举了一些例子,再下面就 Reference了,主要包括  函数列表、函数中使用到的通知与结构体。
  下面我们就主要针对   概览中的 关于部分 做一些 介绍吧。
  与基于DOS系统的应用程序不一样,基于WINDOWS的应用程序是事件驱动的。 基于WINDOWS的应用程序不会使用显示的调用函数来获得输入(就像C语言中的SCANF似的)。取而代之的是 它们等待操作系统把输入传递给它们。
  应用程序的所有输入都会由操作系统传递给程序中的大量窗口。每个窗口都有一个函数,叫过窗口过程。操作系统会去调用这个窗口过程当窗口有输入的时候。窗口过程处理输入并返回控制权给操作系统。
  XP系统中,如果一个顶层窗口停止对消息的响应超过几秒种,系统会认为它处理未响应状态。在这种情况下,系统会将它隐藏并用一个幽灵窗口来替换它,这个幽灵窗口跟这个顶层窗口拥有相同的Z Order,位置,大小和外观。这使得用户可以移动它,修改其大小,甚至关于应用程序。但是,只有这些动作才对这个顶层窗口有效,因为这个应用程序实际上是没有响应的。当在调试模式时,系统不会产生幽灵窗口。
Windows Messages   窗口消息
  系统是以消息的形式将输入传递给窗口过程的。消息是由系统自身和应用程序自身产生的。每个输入事件都会让操作系统自身产生一个消息,例如,当用户按下键盘、移动鼠标或点击了一个滚动条控件时,系统都会产生相应的消息。当有应用程序做了系统方面的修改后,系统也会产生消息,比如当用户修改了系统颜色(不会修改吧,右击桌面空白区域,属性,外观,高级,就在这里面可以设置)时,系统就会产生
WM_SYSCOLORCHANGE 消息。
  应用程序也可以产生消息来指引它自己的窗口去执行任务或者是跟其它应用程序中的窗口通信。
  系统在发一个消息给窗口过程时,消息是带有四个参数的,窗口句柄、消息标识符、两个参数。窗口句柄标识着这个消息是属于哪个窗口的,系统使用它来决定 哪个窗口过程应该 接收这个消息。消息标识符是一个常量 ,当窗口过程接收到一个消息时,它使用消息标识符来决定怎么处理这个消息。例如,消息标识符 WM_PAINT 告诉窗口过程 窗口的客户区已经发生了变化,需要进行重画。消息参数指定数据或数据存在的位置,这些数据可以被窗口过程使用。至于两个参数是什么意思,这是要取决于具体的消息的,它可以是一个整数,也可以是一个指向某种结构体对象的指针等等。当消息不需要使用参数时,通常将消息参数置为NULL,窗口过程必须检验消息标识符来决定怎么解释消息的参数。
Message Types    消息类型
  消息有两种类型:   系统定义好的消息 和 应用程序自定义的消息
  当操作系统与应用程序通信时,操作系统会向应用程序发送或投递系统定义的消息。操作系统使用这些消息来控制 应用程序的操作,并且 向应用程序提供输入和其它信息 以供 应用程序处理。应用程序也可以发送或投递系统定义的消息。应用程序通常使用这些消息来控制控件窗口的操作,控件窗口就是使用操作系统预先注册好的窗口类来创建的窗口,比如常见的 BUTTON ,EDIT 等。
  每个系统定义的消息都有一个独一无二的标识符和用来描述其功能的符号常量,例如,WM_PAINT 这个常量 要求窗口重画它的内容。
  符号常量指定了一些集合 ,这些都是系统预先定义好的,很多消息都是前缀:
PrefixMessage categoryABMApplication desktop toolbarBMButton controlCBCombo box controlCBEMExtended combo box controlCDMCommon dialog boxDBTDeviceDLDrag list boxDMDefault push button controlDTMDate and time picker controlEMEdit controlHDMHeader controlHKMHot key controlIPMIP address controlLBList box controlLVMList view controlMCMMonth calendar controlPBMProgress barPGMPager controlPSMProperty sheetRBRebar controlSBStatus bar windowSBMScroll bar controlSTMStatic controlTBToolbarTBMTrackbarTCMTab controlTTMTooltip controlTVMTree-view controlUDMUp-down controlWMGeneral window  General window 消息覆盖了一个很大的范围,包括鼠标和键盘消息,菜单和对话框输入,窗口创建和管理,动态数据交换。
  应用程序自定义的消息:应用程序可以创建消息 以便它自己的窗口使用 或者 与其它进程中的窗口通信。如果应用程序创建了它自己的消息,那么它的窗口过程函数一定要接收这个消息 ,还要解释它们并对它们做出正确的处理。
  用户自定义消息细节 部分请参考MSDN 。
  下面是本文章中 较为重要的 内容:
Message Routing    消息路由
  一个操作系统中 有 多个 进程 ,每个进程最少有一个主线程 ,当然也可以有其它线程,每个线程都可以创建N个窗口,我们首先要搞清这个对象关系 。
  操作系统使用两种方法来将消息路由给窗口过程:
  1、投递消息到一个 先进先出的 数据结构,这就是消息队列,它是操作系统定义的一个内存块,用来临时存储消息。
  2、将消息直接发送到窗口过程。
  被投递到消息队列中的消息叫做 队列消息。队列消息主要是 鼠标消息、键盘消息、字符消息。其它的队列消息还有  计时器消息(WM_TIMER)、绘画消息(WM_PAINT)、退出消息(WM_QUIT) 。大多数的其它的消息都是 直接 发送到 窗口过程的,它们叫做 非队列消息。
  上面我们介绍了 队列消息 与 非队列消息的 概念。下面具体来看看它们的含意
Queued Messages  : 队列消息
  操作系统在同一时间 可以显示 任意多个窗口。要把鼠标和键盘等输入事件路由到合适的窗口,操作系统使用了消息队列。
  操作系统维护一个 独立的 系统消息队列 并且 为每个界面线程 维护 一个线程特有的消息队列。
  为了避免对非界面线程创建消息队列带来的开销,所有的线程在被初始化后是没有消息队列的,只有在这个线程第一次调用用户函数或GDI函数时 系统才会为这个线程创建 消息队列。
  现在我们基本上可以明白一件事,消息队列是跟线程相关的,一个GUI线程只有一个消息队列,但是它却可以创建很多个窗口。
  当用户移动鼠标、点击鼠标或者按键盘时,键盘或鼠标驱动程序会将输入事件转换成消息,然后将它设置到系统的消息队列中,系统会移除系统消息队列中的消息,一次只移除一个,然后检查他们的目标窗口,然后将消息投递给 创建了 目标窗口的 线程的消息队列。线程消息队列接收所有由他创建的窗口的鼠标和键盘消息。线程移除消息从它的消息队列中然后指示操作系统把它们发送到合适的窗口过程以便处理。
  除了WM_PAINT WM_TIMER WM_QUIT 三个消息之外,操作系统总是把消息投递到消息队列的最后,这保证窗口以队列的顺序接收输入消息。这三个消息 只有在 线程的消息队列中没有 其它消息时 才会被派发给窗口过程。除此之外,发送给同一个窗口的 多个WM_PAINT 消息最终会被合并成一个WM_PAINT消息,这个过程会将所有无效区域进行合并,这样做主要是为了提高效率。
  队列消息常用函数就是POSTMESSAGE
Nonqueued Messages   非队列消息
  非队列消息是直接发送到窗口过程的消息,它绕过了系统消息队列和线程消息队列。常用函数就是SENDMESSAGE。
  好,我只是拣了一些重要的部分进行了 直译,没有仔细思量。
  下面来总结一下:
  1、一个操作系统中会存在多个进程
  2、每个进程最少有一个主线程,当然也可以拥有其它线程
  3、每个线程都可以创建多个窗口。
  4、一个操作系统只有一个系统消息队列
  5、每个GUI线程也只有一个线程消息队列
  6、操作系统会记录所有的信息,比如哪个线程属于哪个进程,哪个窗口属于哪个线程。
  7、消息分为队列消息和非队列消息
  8、队列消息就是 硬件驱动会将输入事件封装成消息 添加到 系统消息队列,然后操作系统会一个接一个的根据消息中的窗口句柄,找到这个窗口所属于的线程,然后将消息 POST给 线程消息队列,然后线程消息队列是由 一些函数 去获取的,如 GETMESSAGE PEEKMESSAGE,这函数获取一个消息,线程消息队列就移除一个消息,然后程序获取了消息后,需要调用 DispatchMessage ,这个函数会将这个消息发送到窗口的窗口过程函数,然后窗口过程函数负责处理这个消息。
  9、非队列消息主要是指 操作系统或应用程序调用 SENDMESSAGE 将消息 直接 发送到 窗口过程处理函数中,不会经过两个队列的处理。
  OK啦。有了这些基础后,大家再把MSDN 中的 内容 读上一遍,我估计就差不多了。还有一些细节问题我也没有说,比如 一些其它常用的函数,消息过滤等,大家自己读读。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-529227-1-1.html 上篇帖子: Windows Server 2003支持的动态卷类型 下篇帖子: 使用SCDPM 2012备份与恢复企业数据(一)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表