01、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);
}