MCI函数与命令
Microsoft提供的MMSYSTEM.H文件中定义了调用MCI功能的数据类型和函数原型。在使用MCI功能的任何源模块中都应包含该文件。
1. MCI函数
所有的MCI函数名都以mci为前缀。对应于MCI命令消息和命令字符串接口方式,MCI函数也分为两类,即命令消息函数和命令字符串函数。在MMSYSTEM.H中定义了这些函数的原型。MCI函数如表3-1所示:
表3-1 MCI函数
函 数 名 |
功 能 |
类 型 |
mciSendCommand |
发送命令消息 |
命令消息接口函数 |
mciGetDeviceID |
获取MCI设备的ID |
|
mciSetYieldProc |
设定一个回调函数,在结束带wait标志的命令时调用 |
|
mciGetYieldProc |
获取当前的回调函数 |
|
mciSendString |
发送命令字符串 |
命令字符串接口函数 |
mciGetErrorString |
获取当前MCI错误的字符串描述 |
公用函数 |
2. MCI命令
MCI命令可以分为4类,如下所述:
a) 系统命令:直接由MCI解释并由系统处理,是不传送到MCI设备的命令。
b) 通用命令:所有的MCI设备都支持的MCI命令。
c) 可选命令:MCI设备可选择使用的MCI命令。
d) 专用命令:针对某类MCI设备或集合的专有MCI命令。
MCI定义了两种接口方式,即命令消息方式和命令字符串方式。相应地,MCI命令可分为命令消息和命令字符串。主要的MCI命令及分类如表3-2所示,这些命令可能具有其相应的扩展形式。
表3-2 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 |
停止播放或记录 |
3. MCI命令接口方式
MCI命令消息接口方式利用消息和数据结构来给多媒体设备发送命令和接收MCI设备传来的的信息。这种方式的接口函数主要有3个,即mciSendCommand,mciGetDeviceID和mciGetErrorString。它们的函数原型如下:
MCIERROR mciSendCommand(
MCIDEVICEID wDevice, // 设备ID
UINT uMsg, // 命令消息
DWORD fdwCommand, // 命令消息标志
DWORDdwParam // 命令消息使用的结构参数地址
);
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 命令消息时可使用的命令消息标志如表3-3所示。MCI_OPEN_PARMS结构定义如下:
typedef struct
{
DWORD dwCallback; // 回调窗口句柄
MCIDEVICEID wDeviceID; // 设备打开成功,返回的设备号
LPCSTR lpstrDeviceType; // 设备类型
LPCSTR lpstrElementName; // 复合设备的设备元素,通常为
// 文件名
LPCSTR lpstrAlias; // 指定的设备别名
} MCI_OPEN_PARMS;
表3-3 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种方式可供选择:
a)为确定MCI设备的性能,可以只指定设备的类型来打开MCI设备。这时,只允许确定MCI设备的性能,然后关闭设备,一般不能进行其他的操作。
b) 为使一个设备元素与指定设备相联系,应同时指定设备元素(数据文件名)和设备类型。这时可对设备进行相应的各种操作。
c)在使用隐含的MCI设备时,可只指定MCI设备元素(数据文件名),而把设备类型指定为NULL;MCI将根据设备元素的扩展名从系统定义中选择隐含约定的MCI设备。
应用程序在使用完一个MCI设备后应明确地关闭该MCI设备。MCI_CLOSE命令消息用于关闭并释放MCI设备,即取消应用程序对MCI设备或设备元素的访问权。
当用MCI_SYSINFO命令消息获取MCI设备系统信息时,需要在mciSendCommand的 dwParam参数中指定MCI_SYSINFO_PARMS结构的地址,系统信息将通过该结构返回。与MCI_SYSINFO 命令消息相关的消息标志如表3-4所示。 MCI_SYSINFO_PARMS结构定义如下:
typedef struct
{
DWORD dwCallback; // 回调窗口句柄
LPSTR lpstrReturn; // 返回信息缓冲区地址
DWORD dwRetSize; // 返回信息大小
DWORD dwNumber; // 索引号
UINT wDeviceType; // 设备类型
} MCI_SYSINFO_PARMS;
表3-4 MCI_SYSINFO 命令消息标志
消 息 标 志 |
意 义 |
MCI_SYSINFO_QUANTITY |
返回指定的设备类型的数目,如与MCI_SYSINFO_OPEN一起使用,则仅返回已打开设备的数目 |
MCI_SYSINFO_NAME |
返回设备名,如与MCI_SYSINFO_OPEN一起使用,则仅返回已打开设备的名称 |
MCI_SYSINFO_OPEN |
仅返回已打开设备的信息 |
MCI_SYSINFO_INSTALLNAME |
指定设备的安装名称 |
在使用MCI设备时,还应注意共享、等待与通告等标志的使用。由于本次设计共享等的应用很少,因此在此另作说明。
4. 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的系统、通用和可选命令字符串列表于表3-1中,每一个命令字符串都对应着相应的命令消息。同样,这些命令也可具有其相应的扩展形式。
4. 示例
(1)下例定义的函数GetNumberOfDevices利用MCI接口函数获取当前系统已打开的MCI设备的数量。
////////////////////////////////////////////////////////////
// GetNumberOfDevices
// 获取当前系统已打开的MCI设备数量
// 参数:无
// 返回值: 当前系统已打开的MCI设备数量
////////////////////////////////////////////////////////////
int GetNumberOfDevices (void)
{
MCI_SYSINFO_PARMSsysinfo;
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)
return0; // 出错
else
return(int)dwDevices;
}
(2)下例说明了播放CD音频的方法。
/////////////////////////////////////////////////////////////////////////
// PlayCDTrack
//
// 使用MCI_OPEN, MCI_PLAY播放指定的CD音频音轨,开始播放即
// 返回,当播放结束时,将通知回调窗口
//
// 参数:hWndNotify —— 接收通知消息的回调窗口句柄
// bTrack —— 指定的音轨
//
// 返回值:0 —— 成功
// 非0 —— 失败,返回值为MCI错误码
////////////////////////////////////////////////////////////////////////
DWORD PlayCDTrack(HWND hWndNotify, BYTE bTrack)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_SET_PARMS mciSetParms;
MCI_PLAY_PARMS mciPlayParms;
// 打开CD音频设备
mciOpenParms.lpstrDeviceType ="cdaudio";
if (dwReturn = mciSendCommand(NULL,MCI_OPEN,
MCI_OPEN_TYPE, (DWORD)(LPVOID) &mciOpenParms))
{
// 打开设备失败,返回错误码
return (dwReturn);
}
// 打开设备成功,获取设备ID
wDeviceID = mciOpenParms.wDeviceID;
// 设置时间格式为TMSF
mciSetParms.dwTimeFormat =MCI_FORMAT_TMSF;
if (dwReturn =mciSendCommand(wDeviceID, MCI_SET,
MCI_SET_TIME_FORMAT, (DWORD)(LPVOID)&mciSetParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
// 开始播放指定音轨,当音轨播放完毕时,用MM_MCINOTIFY 通知
// 消息通知父窗口。如设备出错,关闭设备
mciPlayParms.dwFrom = 0L;
mciPlayParms.dwTo = 0L;
mciPlayParms.dwFrom = MCI_MAKE_TMSF(bTrack, 0, 0, 0);
mciPlayParms.dwTo = MCI_MAKE_TMSF(bTrack + 1, 0, 0, 0);
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY,
MCI_FROM | MCI_TO | MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
return (0L);
}
(3)下例将播放指定的MIDI文件。
/////////////////////////////////////////////////////////////////////////
// PlayMIDIFile
//
// 使用MCI_OPEN和MCI_PLAY播放指定的MIDI文件,开始播放即返回,
// 当播放结束时,将通知回调窗口
//
// 参数:hWndNotify —— 接收通知消息的回调窗口句柄
// lpszMIDIFileName —— 指定的MIDI文件名
//
// 返回值:0 —— 成功
// 非0 —— 失败,返回值为MCI错误码
/////////////////////////////////////////////////////////////////////////
DWORD PlayMIDIFile(HWND hWndNotify, LPSTRlpszMIDIFileName)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
MCI_STATUS_PARMS mciStatusParms;
MCI_SEQ_SET_PARMS mciSeqSetParms;
// 用指定的文件名打开设备
// MCI将试图选取MIDI映射器作为输出端口
mciOpenParms.lpstrDeviceType ="sequencer";
mciOpenParms.lpstrElementName =lpszMIDIFileName;
if (dwReturn = mciSendCommand(NULL,MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID) &mciOpenParms))
{
// 打开设备失败,返回错误码
return (dwReturn);
}
// 打开设备成功,获取设备ID
wDeviceID = mciOpenParms.wDeviceID;
// 检查输出端口是否为MIDI映射器
mciStatusParms.dwItem =MCI_SEQ_STATUS_PORT;
if (dwReturn =mciSendCommand(wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD)(LPVOID) &mciStatusParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
// 输出端口不是MIDI映射器
// 询问用户是否继续
if (LOWORD(mciStatusParms.dwReturn) !=MIDI_MAPPER)
{
if (MessageBox(hMainWnd,
"MIDI映射器不存在,继续吗 ?",
"", MB_YESNO) == IDNO)
{
// 不继续,关闭设备并返回
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (0L);
}
}
// 开始播放,当播放完毕时,用MM_MCINOTIFY 通知
// 消息通知父窗口。如设备出错,关闭设备
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn =mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return(dwReturn);
}
return (0L);
}
(4)下例说明了录制并存储数字化波形声音的方法。
/////////////////////////////////////////////////////////////////////////
// RecordWAVEFile
// 使用 MCI_OPEN, MCI_RECORD和MCI_SAVE命令消息录制并存储数字
// 化波形声音
// 参数:dwMilliSeconds —— 录音的时间(ms)
// lpszFileName —— 指定的存盘文件名
//
// 返回值:0 —— 成功
// 非0 —— 失败,返回值为MCI错误码
/////////////////////////////////////////////////////////////////////////
DWORD RecordWAVEFile(DWORD dwMilliSeconds, LPSTRlpszFileName)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_RECORD_PARMS mciRecordParms;
MCI_SAVE_PARMS mciSaveParms;
MCI_PLAY_PARMS mciPlayParms;
// 用新文件打开波形声音,以进行录音
mciOpenParms.lpstrDeviceType ="waveaudio";
mciOpenParms.lpstrElementName ="";
if (dwReturn = mciSendCommand(0,MCI_OPEN,
MCI_OPEN_ELEMENT | MCI_OPEN_TYPE,
(DWORD)(LPVOID) &mciOpenParms))
{
// 打开设备失败,返回错误码
return (dwReturn);
}
// 打开设备成功,获取设备ID
wDeviceID = mciOpenParms.wDeviceID;
// 按指定的时间(ms)长度开始录音,等待录音结束再继续执行程序
// 设备的时间格式应设为ms
mciRecordParms.dwTo = dwMilliSeconds;
if (dwReturn =mciSendCommand(wDeviceID, MCI_RECORD,
MCI_TO |MCI_WAIT, (DWORD)(LPVOID) &mciRecordParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return(dwReturn);
}
// 播放录音,并提示用户存盘
mciPlayParms.dwFrom = 0L;
if (dwReturn =mciSendCommand(wDeviceID, MCI_PLAY,
MCI_FROM | MCI_WAIT, (DWORD)(LPVOID)&mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
if (MessageBox(hMainWnd, "将录音存盘吗 ?",
"", MB_YESNO) == IDNO)
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (0L);
}
// 将录音存为lpszFileName文件, 等待存盘结束再继续执行程序
mciSaveParms.lpfilename =lpszFileName;
if (dwReturn =mciSendCommand(wDeviceID, MCI_SAVE,
MCI_SAVE_FILE | MCI_WAIT, (DWORD)(LPVOID)&mciSaveParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
return (0L);
}
(5)下例说明了播放数字化视频AVI的方法。
/////////////////////////////////////////////////////////////////////////
// PlayMovie
// 使用 MCI_OPEN和MCI_PLAY命令消息打开并播放数字化视频AVI
// 参数:lpszFileName 指定的AVI文件名
// dwFrom —— 开始播放位置
// dwTo —— 结束播放位置
//
// 返回值:0 —— 成功
// 非0 —— 失败,返回值为MCI错误码
/////////////////////////////////////////////////////////////////////////
DWORD PlayMovie(LPSTR lpszFileName, DWORD dwFrom, DWORDdwTo)
{
DWORD dwReturn;
// 打开AVI
MCI_DGV_OPEN_PARMS mciOpen;
mciOpen.dwCallback = 0L;
mciOpen.wDeviceID = 0;
mciOpen.lpstrDeviceType = AVI_VIDEO;
mciOpen.lpstrElementName =lpszFileName;
mciOpen.lpstrAlias = NULL;
mciOpen.dwStyle = 0;
mciOpen.hWndParent = NULL;
if (dwReturn=mciSendCommand(0,MCI_OPEN,
(DWORD)(MCI_OPEN_TYPE),
(DWORD)(LPMCI_DGV_OPEN_PARMS)&mciOpen) )
{
// 打开设备失败,返回错误码
return dwReturn;
}
// 播放AVI
MCI_DGV_PLAY_PARMSmciPlay; // play parameters
DWORD dwFlags = 0;
// 打开设备成功,获取设备ID
WORD wDevID = mciOpen.wDeviceID;
// 检查开始播放位置,如不等于0,则进行设置
if (dwFrom)
{
mciPlay.dwFrom = dwFrom; // 设置参数
dwFlags |= MCI_FROM; // 设置标志
}
// 检查结束播放位置,如不等于0,则进行设置
if (dwTo)
{
mciPlay.dwTo =dwTo; // 设置参数
dwFlags |=MCI_TO; // 设置标志
}
// 用MCI_PLAY 命令播放并返回结果
return mciSendCommand(wDevID,MCI_PLAY, dwFlags,
(DWORD)(LPVOID)&mciPlay);
上文来自:http://blog.csdn.net/killmice/article/details/8674552