SendMessage和PostMessage及Windows消息机制简介
SendMessage:
The SendMessage function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.
SendMessage函数将指定的消息发到窗口。它调用特定窗口的窗口处理函数,并且不会立即返回,直到窗口处理函数处理了这个消息。SendMessage只是调用我们的消息处理函数
LRESULT WINAPI SendMessage(
_In_ HWND hWnd,_In_ UINT Msg,_In_ WPARAM wParam,_In_ LPARAM lParam );
Parameters
- hWnd [in]
-
Type: HWND
A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of lesser or equal integrity level.消息发送属于UIPI(User Interface Privilege Isolation(用户界面特权隔离)
UIPI保护了高权限进程的界面和用户对象(User Object)不受到低权限恶意进程的更改。通常,一个进程权限的高低取决于它的Integrity Level (IL)。)要更加详细了解UIPI可去http://wenku.baidu.com/link?url=YpkH1-XZzr435JrgrZyDcP4kfNIJJYKSLN7drGIr9OgiPfL2p1bN83Ue-AakfU_fB1hB-w8WK52c2xnOutTWzE2WfDVbTtE2vvHhVV2PbFu 或者http://blog.csdn.net/chris820313/article/details/6706034)一个进程的线程能发送消息到进程中唯一的线程的消息队列
Msg [in]
Type: UINT
The message to be sent.被发送的消息。
For lists of the system-provided messages, see System-Defined Messages.系统提供的消息列表可参见System-Defined Messages
wParam [in]
Type: WPARAM
Additional message-specific information.指定附加的消息特定的信息。
lParam [in]
Type: LPARAM
Additional message-specific information.
Return value
Type:
Type: LRESULT
The return value specifies the result of the message processing; it depends on the message sent.
返回值指定消息处理的结果,依赖于所发送的消息。
PostMessage:
The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.
PostMessage函数将一个消息放入与创建这个窗口的消息队列相关的线程中,并立刻返回不等待线程处理消息。PostMessage只是将消息放到消息队列中
Parameters
- hWnd [in, optional]
-
Type: HWND
A handle to the window whose window procedure is to receive the message. The following values have special meanings.
其窗口程序接收消息的窗口的句柄。以下值具有特殊意义:
Value Meaning - HWND_BROADCAST ((HWND)0xffff)
The message is posted to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows. The message is not posted to child windows.
消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、 被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口
- NULL
The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.
此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样
Starting with Windows Vista, message posting is subject to UIPI. The thread of a process can post messages only to message queues of threads in processes of lesser or equal integrity level.
- Msg [in]
-
Type: UINT
The message to be posted.
For lists of the system-provided messages, see System-Defined Messages.
- wParam [in]
-
Type: WPARAM
Additional message-specific information.
- lParam [in]
-
Type: LPARAM
Additional message-specific information.
Return value
Type:
Type: BOOL
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.GetLastError returns ERROR_NOT_ENOUGH_QUOTA when the limit is hit.
如果函数调用成功,返回非零值:如果函数调用失败,返回值是零。若想获得更多的错误信息,请调用GetLastError函数。GetLastError 当达到上限时返回ERROR_NOT_ENOUGH_QUOTA 。
Requirements
Minimum supported client |
Windows 2000 Professional [desktop apps only] |
---|---|
Minimum supported server |
Windows 2000 Server [desktop apps only] |
Header |
|
Library |
|
DLL |
|
Unicode and ANSI names |
PostMessageW (Unicode) and PostMessageA (ANSI) |
针对wParam和lParam参数说明:
wParam表示是何种Windows消息,表示此次的消息类型是什么?是键盘?是鼠标?键盘里又分按下还是抬起,鼠标里又分是单击还是双击,等等
lParam表示某条Windows消息的具体内容的指针,它实际指向存储那个内容的内存地址,这个地址存放的东西是很灵活的,比如鼠标消息,那么这里可能存放的是各键的状态或者光标的X,Y座标。换成键盘消息,则是键码等等。
下面再简单了解下Windows消息机制:
消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做MSG,MSG含有来自windows应用程序消息队列的消息信息。消息可以由系统或者应用程序产生。系统在发生输入事件时产生消息。举个例子, 当用户敲键, 移动鼠标或者单击控件。系统也产生消息以响应由应用程序带来的变化, 比如应用程序改变系统字体改变窗体大小。应用程序可以产生消息使窗体执行任务,或者与其他应用程序中的窗口通讯。
typedef struct tagMsg
{
HWND hwnd; 接受该消息的窗口句柄
UINT message; 消息常量标识符,也就是我们通常所说的消息号
WPARAM wParam; 32位消息的特定附加信息,确切含义依赖于消息值
LPARAM lParam; 32位消息的特定附加信息,确切含义依赖于消息值
DWORD time; 消息创建时的时间
POINT pt; 消息创建时的鼠标/光标在屏幕坐标系中的位置,
}MSG;
发送消息的函数有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;
寄送消息的函数主要有PostMessage、PostThreadMessage、PostQuitMessage;
广播消息的函数我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。二者区别在于BroadcastSystemMessageEx 可以从消息接收器返回更多的信息(http://blog.csdn.net/yumuhu/article/details/6232063)
当我们要把外界的输入通过驱动程序转化成消息,然后Windows系统将该消息发送到指定的窗口函数,那么,此时将存在两种消息发送方式:把消息投递到一个先进先出的消息队列中,或者把消息直接发送给窗口函数。因此,我们便有了队列消息和非队列消息。
消息队列又分为系统消息队列和线程消息队列。系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护。
对于队列消息,最常见的是鼠标和键盘触发的消息,例如
WM_CHAR,WM_MOUSERMOVE等消息,还有一些其它的消息,例如:
WM_PAINT、WM_TIMER和WM_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动程序就会把这些事件转换成相应的消息,然后输送到系统消息队列,由Windows系统去进行处理。Windows系统则在适当的时机,从系统消息队列中取出一个消息,根据前面我们所说的MSG消息结构确定消息是要被送往那个窗口,然后把取出的消息送往创建窗口的线程的相应队列,下面的事情就该由线程消息队列操心了,Windows开始忙自己的事情去了。线程看到自己的消息队列中有消息,就从队列中取出来,通过操作系统发送到合适的窗口函数去处理。
事件->驱动程序->系统消息队列->对应的线程队列->通过操作系统->调用对应的窗口函数
对于非队列消息,非队列消息将会绕过系统队列和消息队列,直接将消息发送到窗口函数。系统发送非队列消息通知窗口。例如,当用户激活一个窗口系统发送WM_ACTIVATE,WM_SETFOCUS,WM_SETCURSOR。这些消息通知窗口它被激活了。非队列消息也可以由当应用程序调用系统函数产生。例如,当程序调用SetWindowPos系统发送WM_WINDOWPOSCHANGED消息
1、什么是消息以及消息的产生:一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向Windows发出一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。
2、消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。它在Windows中声明如下:"
3、谁将收到消息:一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。
4、怎么给窗口发消息:一个消息发送到窗口有3种方式:发送、寄送和广播。
5、未处理的消息到那里去了:M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。
6、队列消息非队列消息
7、窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二
BroadcastSystemMessage 、BroadcastSystemMessageEx
功能说明
广播特定消息给特定的接收器,接收器可以是应用程序、或者是安装的驱动器、网络驱动器、系统级设备驱动器、或这些系统组件的任何组合。常见于系统将一条系统级消息广播给系统中所有的活动窗口,例如:系统检测到有USB 盘插拔、有光盘放入光驱、或者检测出新硬件等,系统就使用BroadcastSystemMessage 将该消息广播到系统中去,使跟这些设备相关联的程序去处理对应事件。一般用到的情况是使用它给一组应用程序(该组应用程序能够接收到同一个消息)广播统一的消息,例如关闭当前系统所有打开的窗口等。
二者区别在于BroadcastSystemMessageEx 可以从消息接收器返回更多的信息。
函数形式
long BroadcastSystemMessage (
DWORD dwFlags, // 发送消息的方式
LPDWORD lpdwRecipients, // 消息接受器 的信息,消息发送的目标
UINT uiMessage, // 系统消息标识符
WPARAM wParam, // 消息参数
LPARAM lParam // 消息参数
);
long BroadcastSystemMessageEx (
DWORD dwFlags, // 发送消息的方式
LPDWORD lpdwRecipients, // 消息接受器 的信息,消息发送的目标
UINT uiMessage, // 系统消息标识符
WPARAM wParam, // 消息参数
LPARAM lParam // 消息参数
PBSMINFO pBSMInfo // 接收到的附加信息
);
参数说明
1 〉、dwFlags ,【in 】
发送消息的方式,可取下列值的组合:
BSF_FLUSHDISK :消息接收器处理消息之后清理磁盘。
BSF_FORCEIFHUNG :继续广播消息,即使超时周期结束或一个目标已挂起。
BSF_IGNORECURRENTTASK :不发送消息给属于当前任务的窗口,这样,应用程序就不会接收自己的消息。
BSF_NOHANG :强制无反应的应用程序超时,如果一个接收器超时,就不再继续广播消息。
BSF_NOTIMEOUTIFNOTHUNG :只要接收器没挂起,一直等待对消息的响应,且不会出现超时。
BSF_POSTMESSAGE :发送消息,不能跟BSF_QUERY 混合使用。
BSF_QUERY :每次发送消息给一个接受器,只有当前接受器返回TRUE 后,才能发送给下一个接受器。
BSF_SENDNOTIFYMESSAGE :在Windows 2000/XP 中,以SendNotifyMessage 替代,不能跟BSF_QUERY 混合使用。
2 〉、lpdwRecipients
指向变量的指针,该变量包含接收消息的 消息接受器 的信息,或者叫做消息发送的目标。此变量可为下列值的组合:
【in 】,<BroadcastSystemMessage> 取值如下:
BSM_ALLCOMPONENTS :广播到所有的系统组件。
BSM_ALLDESKTOPS :Windows NT 下,广播到所有的桌面。要求SE_TCB_NAME 特权。
BSM_APPLICATIONS :广播到应用程序。
BSM_INSTALLABLEDRIVERS :Windows 95/98/ME 下,广播到安装驱动器。
BSM_INTDRIVER :Windows 95/98/ME 下,广播到网络驱动器。
BSM_VXDS :Windows 95/98/ME 下,广播到所有系统级设备驱动器。
【in, out 】,<BroadcastSystemMessageEx> 取值如下:
BSM_ALLCOMPONENTS :广播到所有的系统组件。
BSM_ALLDESKTOPS :Windows NT 下,广播到所有的桌面。要求SE_TCB_NAME 特权。
BSM_APPLICATIONS :广播到应用程序。
当函数返回时,此变量接受上述值的组合,用于表示哪个接受器真正地接到了消息。如果此参数为NULL ,则将消息广播到所有的组件。
3 〉、uiMessage ,【in 】
系统消息标识符,也就是所谓的消息ID ,例如WM_LBUTTON 、WM_RBUTTON 、WM_KEY 等,都属于消息ID
4 〉、Wparam ,【in 】
消息参数之一,属于字消息,是对 uiMessage 指定的字信息,其意义取决于具体的 uiMessage 的值。
5 〉、Iparam ,【in 】
消息参数之一,属于值消息,是对 uiMessage 指定的值信息,其意义取决于具体的 uiMessage 的值,有时也称LPARAM为事件。
6> 、pBSMInfo, 【out 】
针对函数BroadcastSystemMessageEx 的参数,是 BSMINFO 类型的指针,如果请求被拒绝或者传入的参数dwFlags 被设置为BSF_QUERY 时,函数所能接收到的附加信息。
返回值
函数调用成功,返回值为正;
如果函数不能广播消息,返回值是-1 ;
如果参数dwFlags 为BSF_QUERY 且至少一个接受器返回BROADCAST_QUERY_DENY 给对应的消息,则返回值是零。若想获得更多的错误信息,请调用GetLastError 函数。
备注
如果dwFlags 没有包含BSF_QUERY ,则函数向所有请求的接受器发送指定的消息,并忽略这些接受器返回的值。
适用
Windows NT :4.0 及以上版本:Windows :95 及以上版本;Windows CE :不支持;头文件:winuser.h ;输入库:user32.lib ;Unicode :在Windows NT 环境下以Unicode 和ANSI 方式实现。
应用举例
当设备被热插拔的时候(例如U 盘),WINDOWS 会向系统广播WM_DEVICECHANGE 消息。如果字消息(wParam )的值为 DBT_DEVICEARRIVAL ,则表示设备插入并且已经可用;如果字消息(wParam )的值为DBT_DEVICEREMOVECOMPLETE ,则表示设备已经移出。它们值消息(lParam )的值 为一个DEV_BROADCAST_HDR 类型的指针,DEV_BROADCAST_HDR 定义如下:
typedef struct _DEV_BROADCAST_HDR
{
DWORD dbch_size;
DWORD dbch_devicetype;
DWORD dbch_reserved;
} DEV_BROADCAST_HDR, *PDEV_BROADCAST_HDR;
成员含义:
dbch_size 结构体大小,以字节数衡量;如果所传递的事件属于用户自定义事件,则dbch_size 的值等于该结构体大小,再加上_DEV_BROADCAST_USERDEFINED 中其它变量的总长度。
dbch_devicetype 设备类型,其值跟设备数据相关联,该关联具体如下:
VALUE |
含义 |
DBT_DEVTYP_DEVICEINTERFACE |
设备类,lParam 为一个指向DEV_BROADCAST_DEVICEINTERFACE 数据结构的指针 |
DBT_DEVTYP_HANDLE |
文件系统处理,lParam 为一个指向DEV_BROADCAST_HANDLE 数据结构的指针 |
DBT_DEVTYP_OEM |
OEM 或者IHV 定义的设备类型,lParam为一个指向DEV_BROADCAST_OEM 数据结构的指针 |
DBT_DEVTYP_PORT |
端口设备(串口或者并口),lParam 为一指向DEV_BROADCAST_PORT 数据结构的指针 |
DBT_DEVTYP_VOLUME |
逻辑驱动器,lParam 为一指向DEV_BROADCAST_VOLUME 数据结构的指针 |
例一,这段代码用于检测CD-ROM 中光盘的状态
#include <windows.h>
#include <dbt.h>
#include <strsafe.h>
// 函数声明
void Main_OnDeviceChange(HWND hwnd, WPARAM wParam, LPARAM lParam);
// 函数声明
char FirstDriveFromMask(ULONG unitmask);
// 功能说明 Handles WM_DEVICECHANGE messages sent to the application's top-level window.
void Main_OnDeviceChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
char szMsg[80];
switch (wParam)
{
case DBT_DEVICEARRIVAL:
// Check whether a CD or DVD was inserted into a drive.
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
if (lpdbv -> dbcv_flags & DBTF_MEDIA)
{
StringCchPrintf(szMsg, 80, _T("Drive %c: Media has arrived./n" ),
FirstDriveFromMask(lpdbv ->dbcv_unitmask));
MessageBox (hwnd, szMsg, _T("WM_DEVICECHANGE" ), MB_OK);
}
}
break ;
case DBT_DEVICEREMOVECOMPLETE:
// Check whether a CD or DVD was removed from a drive.
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
if (lpdbv -> dbcv_flags & DBTF_MEDIA)
{
StringCchPrintf(szMsg, 80, _T("Drive %c: Media was removed./n" ),
FirstDriveFromMask(lpdbv ->dbcv_unitmask));
MessageBox (hwnd, szMsg, _T("WM_DEVICECHANGE" ), MB_OK);
}
}
break ;
default : // 处理其余WM_DEVICECHANGE 事件
break ;
}
}
// 功能说明 Finds the first valid drive letter from a mask of drive letters. The mask must be in the
// format bit 0 = A, bit 1 = B, bit 3 = C, etc. A valid drive letter is defined when the corresponding
// bit is set to 1.
// Returns the first drive letter that was found.
char FirstDriveFromMask (ULONG unitmask)
{
char i;
for (i = 0; i < 26; ++i)
{
if (unitmask & 0x1) break ;
unitmask = unitmask >> 1;
}
return (i + 'A' );
}
例二,关闭IE 及其它应用程序
// 关闭IE 及其它应用程序
void CloseAllApplication()
{
int app = BSM_APPLICATIONS;
unsigned long bsm_app = (unsigned long)app;
BroadcastSystemMessage (BSF_POSTMESSAGE, &bsm_app, WM_CLOSE, NULL, NULL);
}
SendMessage和PostMessage及Windows消息机制简介相关推荐
- Windows消息机制学习笔记(三)—— 消息的接收与分发
Windows消息机制学习笔记(三)-- 消息的接收与分发 要点回顾 消息循环 消息队列 消息的接收 GetMessage 实验1:理解GetMessage 第一步:编译并运行程序A 第二步:编译并运 ...
- Windows消息机制(MFC)
消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据 ...
- Windows消息机制-PreTranslateMessage
PreTranslateMessage作用和使用方法 Windows消息机制的流程: A. 操作系统接收应用程序的窗口消息,将消息投递到该应用程序的消息队列中 B. 应用程序在消息循环中调用GetMe ...
- windows消息机制-4(MFC)
消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据 ...
- windows消息机制详解-3
1. 引言 Windows 在操作系统平台占有绝对统治地位,基于Windows 的编程和开发越来越广泛. Dos 是过程驱动的,而Windows 是事件驱动的[6],这种差别的存在使得很多Dos 程序 ...
- 【转】深入理解Windows消息机制
转自:https://blog.csdn.net/liulianglin/article/details/14449577 今天我们来学一学Windows消息机制,我们知道在传统的C语音程序中,当我们 ...
- Windows 消息机制浅析
Windows 消息机制浅析 1. Windows 的历史 中国人喜欢以史为鉴,而事实也确实是,如果你能知道一件事情的来龙去脉,往往可以更容易地理解事物为什么会表现为当前这样的现状.所以, ...
- Windows消息机制MFC编程(一)
一.消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型,而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数 ...
- Windows消息机制学习笔记(二)—— 窗口与线程
Windows消息机制学习笔记(二)-- 窗口与线程 要点回顾 消息从哪里来? 实验一:Spy++捕获消息 实验二:消息捕获 消息到哪里去? 窗口在哪? 实验:分析CreateWindowExW 窗口 ...
最新文章
- python中中括号中的负数
- android如何让service不被杀死-提高进程优先级
- sw二次开发 python_基于C#的SolidWorks二次开发.doc
- oracle12c 删除pdb用户,oracle 12c pdb测试:创建、开关、删除
- Z-Stack通过按键中断实现长按功能
- Codeforces Round #564 (Div. 2) C. Nauuo and Cards
- python地图包_Python交互地图-folium包
- latex 引用公式_写论文如何快速引用他人文章中的公式
- 微信占用空间太大,删除又担心工作相关聊天记录,有啥好办法没?
- 【lucene】入门级
- 别等找工作时才明白:程序员只会敲代码是不行的!不看后悔!
- python管道pipe_Python multiprocessing模块中的Pipe管道
- Dos系统功能调用表9号功能
- 高通QCA9531 2.4GHz电梯监控无线CPE
- ie tab chrome_将IE Tab集成添加到Google Chrome
- 乱谈那些个著名的科技互联网公司和产品名字
- 华硕笔记本触控板设置 Smart Gesture
- 超文本传输协议http详解
- leetcode总结
- Broadcast Receiver(一)
热门文章
- 解决Failed to load resource: net::ERR_CONNECTION_TIMED_OUT
- JS toFixed(2) 返回 -0.00
- php点击切换图片的底部导航,如何优雅地使用BottomNavigationView实现底部导航栏+fragment切换效果...
- 小王梦游记五---最美丽的湖
- 使用bert将中文文本转化成词向量的方法
- 输入一个字符串,将其逆序输出。
- thinkphp6 使用PhpOffice导入Excel表格(上传文件)
- 软件与哲学(2)——对不同世界的抽象
- Linux下curses函数库的详细介绍
- DRV8872直流电机驱动芯片简要的使用说明