赵薇的事情:MCI函数与命令
Microsoft提供的MMSYSTEM.H文件中定义了调用MCI功能的数据类型和函数原型。在使用MCI功能的任何源模块中都应包含该文件。
应用程序通过向MCI设备发送命令(命令消息或命令字符串)来控制MCI设备。MCI命令可以分为4类,如下所述。
1)系统命令:直接由MCI解释并由系统处理,是不传送到MCI设备的命令。
2)通用命令:所有的MCI设备都支持的MCI命令。
3)可选命令:MCI设备可选择使用的MCI命令。
4)专用命令:针对某类MCI设备或集合的专有MCI命令。
MCI定义了两种接口方式,即命令消息方式和命令字符串方式。相应地,MCI命令可分为命令消息和命令字符串。主要的MCI命令及分类如表4-3所示,这些命令可能具有其相应的扩展形式。
表4-3 MCI命令列表
MCI命令消息
MCI命令字符串
MCI命令说明
MCI命令类型
MCI_SYSINFO
SYSINFO
返回有关MCI设备的信息
系统命令
MCI_BREAK
BREAK
为一个指定的MCI设备设置一个终止键
MCI_SOUND
SOUND
播放一段Windows指定的系统声音
MCI_CLOSE
CLOSE
关闭一个MCI设备
通用命令
MCI_GETDEVCAPS
GETDEVCAPS
获得一个MCI设备的性能参数
MCI_INFO
INFO
从一个MCI设备得到有关的信息
MCI_OPEN
OPEN
初始化一个MCI设备
MCI_STATUS
STATUS
从一个MCI设备返回有关的状态信息
MCI_LOAD
LOAD
从一个磁盘文件中加载数据
可选命令
MCI_PAUSE
PAUSE
暂停播放或记录
MCI_PLAY
PLAY
开始播放数据
MCI_RECORD
RECORD
开始记录数据
MCI_RESUME
RESUME
重新开始播放或记录
MCI_SAVE
SAVE
将数据存储到磁盘文件中
MCI_SEEK
SEEK
向前或向后检索
MCI_SET
SET
设置设备信息
MCI_STOP
STOP
停止播放或记录
MCI命令都可以带两个标志命令来控制命令的执行方式,即“wait”和“notify”。它们在命令消息和命令字符串接口中的形式和意义如表4-4所示。
表4-4 MCI标志命令
命 令 消 息
命令字符串
功 能
MCI_WAIT
wait
通知MCI设备等,MCI命令执行完后,才能将控制权还给应用程序
MCI_NOTIFY
notify
通知MCI设备等,立刻将控制权交给应用程序,但当命令执行完后,向应用程序发送MM_MCINOTIFY消息
所有的MCI函数名都以mci为前缀。对应于MCI命令消息和命令字符串接口方式,MCI函数也分为两类,即命令消息函数和命令字符串函数。在MMSYSTEM.H中定义了这些函数的原型。MCI函数如表4-5所示。
表4-5 MCI函数
函 数 名
功 能
类 型
mciSendCommand
发送命令消息
命令消息接口函数
mciGetDeviceID
获取MCI设备的ID
mciSetYieldProc
设定一个回调函数,在结束带wait标志的命令时调用
mciGetYieldProc
获取当前的回调函数
mciSendString
发送命令字符串
命令字符串接口函数
mciGetErrorString
获取当前MCI错误的字符串描述
公用函数
(1)MCI命令消息接口方式
MCI命令消息接口方式利用消息和数据结构来给多媒体设备发送命令和接收MCI设备传来的的信息。这种方式的接口函数主要有3个,即mciSendCommand,mciGetDeviceID和mciGetErrorString。它们的函数原型如下:
MCIERROR mciSendCommand(
MCIDEVICEID wDevice, // 设备ID
UINT uMsg, // 命令消息
DWORD fdwCommand, // 命令消息标志
DWORD dwParam // 命令消息使用的结构参数地址
);
MCIDEVICEID mciGetDeviceID( LPCTSTR lpszDevice ); // 设备类型
BOOL mciGetErrorString(
DWORD fdwError, // 错误代码
LPTSTR lpszErrorText, // 错误描述
UINT cchErrorText // 错误描述长度
);
mciGetDeviceID通过传送MCI设备名lpszDevice来获取用于MCI_OPEN命令消息打开MCI设备的标识号wDeviceID,其值可用于mciSendCommand的参数wDeviceID。mciSendCommand用于向标识号为wDeviceID的MCI设备发送命令消息uMsg。当用mciSendCommand发送MCI_OPEN命令消息打开一个设备时,将自动创建一个设备标识号。如果设备打开成功,可以从MCI_OPEN_PARMS结构的wDeviceID数据域中取得该设备的标识号,该值将保存以供后续的MCI命令使用。如果mciSendCommand调用成功,则返回值为0;否则表示设备驱动出错,这时可用mciGetErrorString来取得错误信息的文字描述。
MCI提供一个名为MCI_ALL_DEVICE_ID的特殊设备标识号。当前所有已打开的MCI设备都将接收到对MCI_ALL_DEVICE_ID发送的任何MCI命令。
使用任何一个MCI设备前都应先用MCI_OPEN打开它。打开MCI设备时,要求指定相应的MCI_OPEN_PARMS结构。如果打开设备成功,则该结构的wDeviceID域返回MCI设备的标识号ID。
使用MCI_OPEN 命令消息时可使用的命令消息标志如表4-6所示。MCI_OPEN_PARMS结构定义如下:
typedef struct
{
DWORD dwCallback; // 回调窗口句柄
MCIDEVICEID wDeviceID; // 设备打开成功,返回的设备号
LPCSTR lpstrDeviceType; // 设备类型
LPCSTR lpstrElementName; // 复合设备的设备元素,通常为
// 文件名
LPCSTR lpstrAlias; // 指定的设备别名
} MCI_OPEN_PARMS;
表4-6 MCI_OPEN 命令消息标志
消 息 标 志
意 义
MC_OPEN_ALIAS
MCI_OPEN_PARMS结构的lpstrAlias域中指定了设备别名
MC_OPEN_ELEMENT
MCI_OPEN_PARMS结构的lpstrElementName域中指定了设备元素
MC_OPEN_SHAREABLE
按共享设备方式打开设备
MC_OPEN_TYPE
MCI_OPEN_PARMS结构的lpstrDeviceType域中指定了设备类型
MC_OPEN_TYPE_ID
MCI_OPEN_PARMS结构的lpstrDeviceType域中指定了设备类型ID
打开一个简单的MCI设备不需要指定设备元素,即不需要指定一个数据文件,所以可以仅仅指定MCI_OPEN_PARMS结构中的wDeviceID和lpstrDeviceType两个数据域。要打开一个复合的MCI设备,必须指定设备元素数据域lpstrElementName和设备类型数据域lpstrDeviceType。对于打开复合MCI设备,有以下3种方式可供选择:
1)为确定MCI设备的性能,可以只指定设备的类型来打开MCI设备。这时,只允许确定MCI设备的性能,然后关闭设备,一般不能进行其他的操作。
2) 为使一个设备元素与指定设备相联系,应同时指定设备元素(数据文件名)和设备类型。这时可对设备进行相应的各种操作。
3)在使用隐含的MCI设备时,可只指定MCI设备元素(数据文件名),而把设备类型指定为NULL;MCI将根据设备元素的扩展名从系统定义中选择隐含约定的MCI设备。
应用程序在使用完一个MCI设备后应明确地关闭该MCI设备。MCI_CLOSE命令消息用于关闭并释放MCI设备,即取消应用程序对MCI设备或设备元素的访问权。
当用MCI_SYSINFO命令消息获取MCI设备系统信息时,需要在mciSendCommand的dwParam参数中指定MCI_SYSINFO_PARMS结构的地址,系统信息将通过该结构返回。与MCI_SYSINFO 命令消息相关的消息标志如表4-7所示。 MCI_SYSINFO_PARMS结构定义如下:
typedef struct
{
DWORD dwCallback; // 回调窗口句柄
LPSTR lpstrReturn; // 返回信息缓冲区地址
DWORD dwRetSize; // 返回信息大小
DWORD dwNumber; // 索引号
UINT wDeviceType; // 设备类型
} MCI_SYSINFO_PARMS;
表4-7 MCI_SYSINFO 命令消息标志
消 息 标 志
意 义
MCI_SYSINFO_QUANTITY
返回指定的设备类型的数目,如与MCI_SYSINFO_OPEN一起使用,则仅返回已打开设备的数目
MCI_SYSINFO_NAME
返回设备名,如与MCI_SYSINFO_OPEN一起使用,则仅返回已打开设备的名称
MCI_SYSINFO_OPEN
仅返回已打开设备的信息
MCI_SYSINFO_INSTALLNAME
指定设备的安装名称
在使用MCI设备时,还应注意共享、等待与通告等标志的使用。
下例说明了用命令消息接口播放数字化波形声音的方法:
// 其他代码
……………
// 打开设备
MCI_OPEN_PARMS OpenParams;
OpenParams.lpstrDeviceType = "waveaudio";
OpenParams.lpstrElementName = "c:\\windows\\tada.wav";
MCIERROR ErrorID = mciSendCommand(NULL,
MCI_OPEN,
MCI_OPEN_ELEMENT|MCI_OPEN_TYPE,
(DWORD)(LPMCI_OPEN_PARMS)&OpenParams);
if (ErrorID != 0)
{
// 错误处理
……………
}
else
{
// 播放操作
WORD wDeviceID = OpenParams.wDeviceID;
MCI_PLAY_PARMS PlayParams;
ErrorID = mciSendCommand(wDeviceID,
MCI_PLAY,
MCI_NOTIFY,
(DWORD)(LPMCI_PLAY_PARMS)&PlayParams);
if (ErrorID != 0)
{
// 播放出错,需关闭设备
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return ErrorID;
}
}
// 其他代码
……………
(2)MCI命令字符串接口方式
MCI命令字符串方式使用ASCII字符串来发送驱动MCI设备的命令,这种方式采用的接口函数有mciSendString、mciGetErrorString。
mciSendString 用于向MCI设备发送命令字符串,其函数原型如下:
MCIERROR mciSendString(
LPCTSTR lpszCommand,
LPTSTR lpszReturnString,
UINT cchReturn,
HANDLE hwndCallback
);
第一个参数是远程指针lpszCommand,指向一个以NULL结尾的MCI命令字符串,该字符串的语法格式如下所示:
command device_name argument
其第二个参数lpszReturnString指向一个用于存储MCI命令执行后返回的字符串信息的缓冲区。第三个参数cchReturn用于指定该字符串缓冲区的大小。MCI命令执行后,返回的信息将存放在lpszReturnString中,如果返回信息的长度大于cchReturn声明的长度,MCI将返回一个错误代码。如设置lpszReturnString为NULL,则将忽略返回信息。
其第四个参数hwndCallback指定一个接受MM_MCINOTIFY的窗口的句柄,除非MCI命令中包含了notify标志,否则该参数可忽略。如该函数返回非0值,则说明调用失败,可用mciGetErrorString 取得包含错误信息的字符串。
MCI的系统、通用和可选命令字符串列表于表4-3中,每一个命令字符串都对应着相应的命令消息。同样,这些命令也可具有其相应的扩展形式。
下例说明了用命令字符串接口播放数字化波形声音的方法:
// 其他代码
……………
// 打开设备
char szReturn[256];
MCIERROR ErrorID =
mciSendString("open c:\\windows\\tada.wav type waveaudio alias wave"
szReturn,
sizeof(szReturn),
hWnd); // hWnd已定义,或设为NULL
if (ErrorID != 0)
{
// 错误处理
……………
}
else
{
// 播放操作
ErrorID = mciSendString("play wave",
szReturn,
sizeof(szReturn),
hWnd); // hWnd已定义,或设为NULL
if (ErrorID != 0)
{
// 播放出错,需关闭设备
mciSendString("close wave", NULL, 0, NULL);
return ErrorID;
}
}
// 其他代码
……………
(3)示例
1)下例定义的函数GetNumberOfDevices利用MCI接口函数获取当前系统已打开的MCI设备的数量。
/////////////////////////////////////////////////////////////////////////
// GetNumberOfDevices
// 获取当前系统已打开的MCI设备数量
// 参数:无
// 返回值: 当前系统已打开的MCI设备数量
/////////////////////////////////////////////////////////////////////////
int GetNumberOfDevices (void)
{
MCI_SYSINFO_PARMS sysinfo;
DWORD dwDevices;
sysinfo.lpstrReturn = (LPSTR)(LPDWORD)&dwDevices;
sysinfo.dwRetSize = sizeof(DWORD);
if (mciSendCommand(MCI_ALL_DEVICE_ID,
MCI_SYSINFO,
MCI_SYSINFO_OPEN | MCI_SYSINFO_QUANTITY,
(DWORD)(LPMCI_SYSINFO_PARMS)&sysinfo)
!= 0)
return 0; // 出错
else
return (int)dwDevices;
}