`
wo_deqing
  • 浏览: 64226 次
文章分类
社区版块
存档分类
最新评论

vc++消息处理机制

 
阅读更多
摘要:Windows编程和Dos编程,一个很大的区别就是,Windows编程是事件驱动,消息传递的。所以,要学好Windows编程,必须对消息机制有一个清楚的认识,本文希望能够对消息的传递做一个全面的分析。
   什么是消息?

   消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉。一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向Windows发出一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。

   消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做MSG,MSG含有来自windows应用程序消息队列的消息信息,它在Windows中声明如下:

typedef struct tagMsg
{
HWND hwnd; 接受该消息的窗口句柄
UINT message; 消息常量标识符,也就是我们通常所说的消息号
WPARAM wParam; 32位消息的特定附加信息,确切含义依赖于消息值
LPARAM lParam; 32位消息的特定附加信息,确切含义依赖于消息值
DWORD time; 消息创建时的时间
POINT pt; 消息创建时的鼠标/光标在屏幕坐标系中的位置
}MSG;

   消息可以由系统或者应用程序产生。系统在发生输入事件时产生消息。举个例子, 当用户敲键, 移动鼠标或者单击控件。系统也产生消息以响应由应用程序带来的变化, 比如应用程序改变系统字体改变窗体大小。应用程序可以产生消息使窗体执行任务,或者与其他应用程序中的窗口通讯。

   消息中有什么?

   我们给出了上面的注释,是不是会对消息结构有了一个比较清楚的认识?如果还没有,那么我们再试着给出下面的解释:

   hwnd 32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。

   message用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。消息标识符以常量命名的方式指出消息的含义。当窗口过程接收到消息之后,他就会使用消息标识符来决定如何处理消息。例如、WM_PAINT告诉窗口过程窗体客户区被改变了需要重绘。符号常量指定系统消息属于的类别,其前缀指明了处理解释消息的窗体的类型。

   wParam 通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。

   lParam 通常是一个指向内存中数据的指针。由于WParam、lParam和Pointer都是32位的,因此,它们之间可以相互转换。

消息标识符的值

   系统保留消息标识符的值在0x0000在0x03ff(WM_USER-1)范围。这些值被系统定义消息使用。 应用程序不能使用这些值给自己的消息。应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,我们顺便说一下具有标志性的消息值:

WM_NULL---0x0000 空消息。
0x0001----0x0087 主要是窗口消息。
0x00A0----0x00A9 非客户区消息
0x0100----0x0108 键盘消息
0x0111----0x0126 菜单消息
0x0132----0x0138 颜色控制消息
0x0200----0x020A 鼠标消息
0x0211----0x0213 菜单循环消息
0x0220----0x0230 多文档消息
0x03E0----0x03E8 DDE消息
0x0400 WM_USER
0x8000 WM_APP
0x0400----0x7FFF 应用程序自定义私有消息

   消息有的分类?

   其实,windows中的消息虽然很多,但是种类并不繁杂,大体上有3种:窗口消息、命令消息和控件通知消息。

   窗口消息大概是系统中最为常见的消息,它是指由操作系统和控制其他窗口的窗口所使用的消息。例如CreateWindow、DestroyWindow和MoveWindow等都会激发窗口消息,还有我们在上面谈到的单击鼠标所产生的消息也是一种窗口消息。
个按钮,他就会向主窗口发送一个命令消息。

   控件通知消息,是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows公共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的滚动条都会产生通知消息。 她类似于命令消息,当用户与控件窗口交互时,那么控件通知消息就会从控件窗口发送到它的主窗口。但是这种消息的存在并不是为了处理用户命令,而是为了让主窗口能够改变控件,例如加载、显示数据。例如按下一个按钮,他向父窗口发送的消息也可以看作是一个控件通知消息;单击鼠标所产生的消息可以由主窗口直接处理,然后交给控件窗口处理。

   其中窗口消息及控件通知消息主要由窗口类即直接或间接由CWND类派生类处理。相对窗口消息及控件通知消息而言,命令消息的处理对象范围就广得多,它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。

   由于控件通知消息很重要的,人们用的也比较多,但是具体的含义往往令初学者晕头转向,所以我决定把常见的几个列出来供大家参考:

   按扭控件

BN_CLICKED 用户单击了按钮
BN_DISABLE 按钮被禁止
BN_DOUBLECLICKED 用户双击了按钮
BN_HILITE 用/户加亮了按钮
BN_PAINT 按钮应当重画
BN_UNHILITE 加亮应当去掉

   组合框控件

CBN_CLOSEUP 组合框的列表框被关闭
CBN_DBLCLK 用户双击了一个字符串
CBN_DROPDOWN 组合框的列表框被拉出
CBN_EDITCHANGE 用户修改了编辑框中的文本
CBN_EDITUPDATE 编辑框内的文本即将更新
CBN_ERRSPACE 组合框内存不足
CBN_KILLFOCUS 组合框失去输入焦点
CBN_SELCHANGE 在组合框中选择了一项
CBN_SELENDCANCEL 用户的选择应当被取消
CBN_SELENDOK 用户的选择是合法的
CBN_SETFOCUS 组合框获得输入焦点

   编辑框控件

EN_CHANGE 编辑框中的文本己更新
EN_ERRSPACE 编辑框内存不足
EN_HSCROLL 用户点击了水平滚动条
EN_KILLFOCUS 编辑框正在失去输入焦点
EN_MAXTEXT 插入的内容被截断
EN_SETFOCUS 编辑框获得输入焦点
EN_UPDATE 编辑框中的文本将要更新
EN_VSCROLL 用户点击了垂直滚动条消息含义

   列表框控件

LBN_DBLCLK 用户双击了一项
LBN_ERRSPACE 列表框内存不够
LBN_KILLFOCUS 列表框正在失去输入焦点
LBN_SELCANCEL 选择被取消
LBN_SELCHANGE 选择了另一项
LBN_SETFOCUS 列表框获得输入焦点

队列消息和非队列消息

   从消息的发送途径来看,消息可以分成2种:队列消息和非队列消息。消息队列由可以分成系统消息队列和线程消息队列。系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护,为避免给non-GUI现成创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数数系统给线程创建一个消息队列。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。

   对于队列消息,最常见的是鼠标和键盘触发的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,还有一些其它的消息,例如:WM_PAINT、WM_TIMER和WM_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动程序就会把这些事件转换成相应的消息,然后输送到系统消息队列,由Windows系统去进行处理。Windows系统则在适当的时机,从系统消息队列中取出一个消息,根据前面我们所说的MSG消息结构确定消息是要被送往那个窗口,然后把取出的消息送往创建窗口的线程的相应队列,下面的事情就该由线程消息队列操心了,Windows开始忙自己的事情去了。线程看到自己的消息队列中有消息,就从队列中取出来,通过操作系统发送到合适的窗口过程去处理。
一般来讲,系统总是将消息Post在消息队列的末尾。这样保证窗口以先进先出的顺序接受消息。然而,WM_PAINT是一个例外,同一个窗口的多个 WM_PAINT被合并成一个 WM_PAINT 消息, 合并所有的无效区域到一个无效区域。合并WM_PAIN的目的是为了减少刷新窗口的次数。

   非队列消息将会绕过系统队列和消息队列,直接将消息发送到窗口过程,。系统发送非队列消息通知窗口,系统发送消息通知窗口。 例如,当用户激活一个窗口系统发送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。这些消息通知窗口它被激活了。非队列消息也可以由当应用程序调用系统函数产生。例如,当程序调用SetWindowPos系统发送WM_WINDOWPOSCHANGED消息。一些函数也发送非队列消息,例如下面我们要谈到的函数。

   消息的发送

   了解了上面的这些基础理论之后,我们就可以进行一下简单的消息发送与接收。

   把一个消息发送到窗口有3种方式:发送、寄送和广播。

   发送消息的函数有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;寄送消息的函数主要有PostMessage、PostThreadMessage、PostQuitMessage;广播消息的函数我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。

   SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),这个函数主要是向一个或多个窗口发送一条消息,一直等到消息被处理之后才会返回。不过需要注意的是,如果接收消息的窗口是同一个应用程序的一部分,那么这个窗口的窗口函数就被作为一个子程序马上被调用;如果接收消息的窗口是被另外的线程所创建的,那么窗口系统就切换到相应的线程并且调用相应的窗口函数,这条消息不会被放进目标应用程序队列中。函数的返回值是由接收消息的窗口的窗口函数返回,返回的值取决于被发送的消息。

   PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),该函数把一条消息放置到创建hWnd窗口的线程的消息队列中,该函数不等消息被处理就马上将控制返回。需要注意的是,如果hWnd参数为HWND_BROADCAST,那么,消息将被寄送给系统中的所有的重叠窗口和弹出窗口,但是子窗口不会收到该消息;如果hWnd参数为NULL,则该函数类似于将dwThreadID参数设置成当前线程的标志来调用PostThreadMEssage函数。

   从上面的这2个具有代表性的函数,我们可以看出消息的发送方式和寄送方式的区别所在:被发送的消息是否会被立即处理,函数是否立即返回。被发送的消息会被立即处理,处理完毕后函数才会返回;被寄送的消息不会被立即处理,他被放到一个先进先出的队列中,一直等到应用程序空线的时候才会被处理,不过函数放置消息后立即返回。

   实际上,发送消息到一个窗口处理过程和直接调用窗口处理过程之间并没有太大的区别,他们直接的唯一区别就在于你可以要求操作系统截获所有被发送的消息,但是不能够截获对窗口处理过程的直接调用。

   以寄送方式发送的消息通常是与用户输入事件相对应的,因为这些事件不是十分紧迫,可以进行缓慢的缓冲处理,例如鼠标、键盘消息会被寄送,而按钮等消息则会被发送。

   广播消息用得比较少,BroadcastSystemMessage函数原型如下:

long BroadcastSystemMessage(DWORD dwFlags,LPDWORD lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM lParam);

   该函数可以向指定的接收者发送一条消息,这些接收者可以是应用程序、可安装的驱动程序、网络驱动程序、系统级别的设备驱动消息和他们的任意组合。需要注意的是,如果dwFlags参数是BSF_QUERY并且至少一个接收者返回了BROADCAST_QUERY_DENY,则返回值为0,如果没有指定BSF_QUERY,则函数将消息发送给所有接收者,并且忽略其返回值 .
分享到:
评论

相关推荐

    VC++图像处理软件

    在VS2005中,可以使用资源编辑器来创建和编辑对话框模板,然后在C++代码中定义相应的对话框类,通过消息映射机制响应用户的操作。比如,可以添加控件(如按钮、滑块等)来让用户调整图像尺寸和质量,或者设置图片的...

    VC++利用消息机制在两个EXE程序间通信

    本主题探讨的是如何利用VC++(Visual C++)的Windows消息机制来实现在两个独立的EXE程序之间进行通信。这种方法既简单又实用,尤其适用于简单的数据传递。 首先,理解Windows消息机制是关键。在Windows系统中,所有...

    VC++ 消息映射与处理

    在VC++编程中,消息映射与处理是构建用户界面应用程序的核心部分,它涉及到Windows操作系统中的消息机制。本文将深入探讨这一主题,并结合...通过深入学习和实践,开发者可以更好地理解和掌握VC++中的消息处理机制。

    VC++ 消息映射与处理\向其他应用程序(记事本)中发送键盘消息

    消息映射是定义这些消息如何被处理的机制。在MFC(Microsoft Foundation Classes)库中,我们通过在CWinApp或CWnd派生类的头文件中定义消息映射宏来实现这一功能。例如,`ON_MESSAGE` 宏用于处理自定义消息,而 `ON_...

    杨淑莹VC++图像处理程序设计代码

    7. **编程技巧**:多线程处理大图像以提高效率,内存管理和错误处理机制,以及如何优化图像处理程序以减少计算时间和内存消耗。 8. **调试与测试**:在VC++环境中使用调试器来查找和修复代码问题,以及创建测试用例...

    消息处理的做法详解

    ### 消息处理在VC++中的实践与理解 #### 标题解读:消息处理...从基本概念到具体的实现细节,再到实际操作中可能遇到的问题及其解决方案,文章内容丰富且实用性强,非常适合想要深入了解VC++消息处理机制的读者阅读。

    VC++消息映射与处理\使用程序模拟键盘输入

    总结一下,VC++的消息映射是MFC框架中处理用户交互的关键机制,而通过`SendInput`函数可以模拟键盘输入。在“实例025——使用程序模拟键盘输入”中,我们可以学习如何结合这两者,创建一个能够响应用户键盘操作并且...

    vc++消息和事件大全

    消息循环是VC++应用程序中的关键部分,它不断地从消息队列中取出消息,然后分发给相应的窗口过程进行处理。窗口过程(WndProc)是一个回调函数,负责解析接收到的消息并执行适当的响应。 消息映射(Message Map)是...

    VC++基本图像处理例程

    同时,掌握VC++的图像处理不仅有助于理解底层机制,还有利于与其他编程语言和库的交互,比如Python的OpenCV库。总之,这是一个非常有价值的学习资源,对于想要深入研究图像处理和计算机视觉的开发者来说,不容错过。

    VC++消息映射与处理\限制鼠标的作用区域在客户窗口

    总的来说,VC++的消息映射和处理机制为我们提供了一种灵活的方式,来定制应用程序对用户输入的响应。通过理解和熟练运用这些技术,开发者可以创建出符合特定需求的用户界面,比如本例中限制鼠标作用区域在客户窗口的...

    VC++消息映射与处理\在对话框中实现键盘消息响应

    VC++中的消息映射机制就是用来定义这些消息应该如何被程序处理的。 首先,我们需要在对话框类的头文件中定义消息映射。在`.h`文件的`BEGIN_MESSAGE_MAP`和`END_MESSAGE_MAP`之间添加对应的消息处理函数声明,例如...

    VC++消息映射与处理\使用定时器显示毫秒级的时间

    在VC++编程中,消息映射与处理是核心机制之一,它使得程序能够响应各种用户交互和系统事件。本文将详细探讨如何利用消息映射和处理来创建一个使用定时器显示毫秒级时间的程序。 首先,理解消息映射(Message ...

    VC++消息映射与处理\使用定时器实时显示当前时间

    本文将深入探讨如何在VC++中利用消息映射和处理机制,特别是结合定时器来实时显示当前时间。 首先,让我们理解消息映射(Message Map)。消息映射是MFC(Microsoft Foundation Classes)框架中的一个重要组成部分,...

    VC++音频处理希望大家指点

    8. **事件驱动编程**:Windows消息机制是音频处理中的常见模式,通过处理WM_APP、WM_TIMER等消息来响应用户交互或定时任务。 9. **调试与性能优化**:调试工具如Visual Studio Debugger是必不可少的,而性能优化则...

    VC++深入详解+FC消息响应机制.7z

    《VC++深入详解+FC消息响应机制》是一个包含深度学习VC++编程技术和MFC消息处理机制的资源包。其中,MFC(Microsoft Foundation Classes)是微软提供的一个C++类库,用于简化Windows应用程序的开发,而消息响应机制...

    简单的vc++图像处理程序

    7. **Windows编程**:VC++开发的程序通常运行在Windows平台上,因此需要了解Windows消息机制、窗口类、事件处理等基础知识。 8. **调试技巧**:VC++提供了强大的调试工具,如断点、单步执行、变量观察等,用于找出...

    VC++源码—消息循环重载实例

    消息循环重载实例是一个具体的应用场景,旨在演示如何在VC++程序中自定义和扩展标准的消息处理机制。这个实例可能包含了一系列源代码文件,用于展示如何在不同情况下处理消息,从而提供更灵活的控制或实现特定功能。...

    vc++ 文件夹处理程序

    使用异常处理机制(如C++的`try-catch`)可以帮助程序优雅地处理这些问题。 总的来说,"vc++ 文件夹处理程序"可能涵盖了以上提到的多种功能,实现了对文件夹的全面管理。通过理解和掌握这些知识点,开发者能够构建...

    VC++图像处理的源码

    4. **错误处理**:查看代码中的错误处理机制,了解如何处理可能出现的问题。 5. **性能优化**:观察代码是否进行了性能优化,例如使用多线程、内存管理等。 通过深入研究这些源码,开发者不仅可以提升自己的VC++...

    VC++图像处理程序设计特效显示

    此外,为了实现交互式特效显示,我们还需要了解窗口消息处理机制,如WM_PAINT消息的处理,以及如何在C++中使用定时器来实现动态特效。 总的来说,VC++图像处理程序设计中的特效显示是一门综合性的技术,涉及图像...

Global site tag (gtag.js) - Google Analytics