admin管理员组

文章数量:1530516

2023年12月12日发(作者:)

SendMessage函数完全使用手册

Windows是一个消息驱动式系统,Windows消息提供应用程序与应用程序之间,应用程序与Windows系统之间进行通信的手段。

Windows API宏,在WinUser.h中根据是否已定义Unicode被定义为SendMessageW或SendMessageA,这两个函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口

调用窗口程序,直到窗口程序处理完消息再返回。而和函数PostMessage不同,PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。

函数原型

LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)

参数

hWnd:指定要接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口

和弹出式窗口,但消息不被发送到子窗口。32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)

Msg:指定被发送的消息。这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。

wParam:指定附加的消息特定信息。通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。

IParam:指定附加的消息特定信息。通常是一个指向内存中数据的指针。

返回值:返回值指定消息处理的结果,依赖于所发送的消息。

备注:需要用HWND_BROADCAST通信的应用程序应当使用函数RegisterWindowMessage来为应用程序间的通信取得一个唯一的消息。

如果指定的窗口是由正在调用的线程创建的,则窗口程序立即作为子程序调用。如果指定的窗口是由不同线程创建的,则系统切换到该线程并调用恰当的窗口程序。间的消息只

有在线程执行消息检索代码时才被处理。发送线程被阻塞直到接收线程处理完消息为止。

消息标识符的值

   系统保留消息标识符的值在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 应用程序自定义私有消息

消息有的分类?

前缀代表英文解释

WM_

SM_

SS_

BM_

BS_

BN_

EM_

ES_

CB_

CBN_

LBM_

LBS_

LBN_

LVM_

LVS_

LVN_

TVM_

TVS_

TVN_

VK_

Window Message

Static Message

Static Style

Button Message

Button Style

Button Notify

Edit Message

Edit Style

ComboBox

ComboBox Notify

ListBox Message

ListBox Style

ListBox Notify

ListView Message

ListView Style

ListView Notify

TreeView Message

TreeView Style

TreeView Notify

Virtual Keyboard

窗口消息,一般用在SendMessage,PostMessage这样的消息函数中

静态标签消息

静态标签风格

按钮消息

按钮风格

按钮通知

编辑框消息

编辑框风格

组合框消息

组合框通知

列表框消息

列表框风格

列表框通知

超级列表框(列表视图)消息

超级列表框(列表视图)风格

超级列表框(列表视图)通知

树型框(树型视图)消息

树型框(树型视图)风格

树型框(树型视图)通知

虚拟键、键代码

其实,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开始忙自己的事情去了。线程看到自己的消息队列中有消息,就从队列中取出来,通过操作系统发送到合适的窗口过程去处理。

//有关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,则函数将消息发送给所有接收者,

并且忽略其返回值。

本文标签: 消息队列系统线程