|
首先,让我们先来了解一下MCI(Media Control Interface)媒体控制接口。MCI是MircroSoft提供的一组多媒体设备和文件的标准接口,它的好处是可以方便地控制绝大多数多媒体设备包括音频、视频、影碟、录像等多媒体设备,而不需要知道它们的内部工作状况。它所支持的媒体格式包括avi、wav、mpeg、cda等等。由于Windows内置了MP3播放引擎MCI也支持MP3,但由于某种不为我们所知的原因,Microsoft并没有公开MCI的这个访问功能。我们所要做的就是利用这一非公开的访问接口直接调用系统内置引擎实现MP3的播放。在windows的系统配置文件system.ini(C:\windows\)中有一个[MCI]配置项,该项下列出了通过MCI接口所接受的MCI设备类型与所调用引擎的对应关系,如:
mci]
cdaudio=mcicda.drv
sequencer=mciseq.drv
waveaudio=mciwave.drv
avivideo=mciavi.drv
我们只需添加条目:mp3audio=mciqtz.drv
其中mciqtz.drv即MP3播放引擎驱动。我们在通过MCI接口编程时只要显式地指明所使用的设备类型为mp3audio,即可实现播放MP3的目的。余下的工作就只是通过调用MCI接口函数实现播放器的功能了。让我们再来了解一下MCI接口函数。
一般说来,程序员使用两个函数就可以与MCI打交道了,这两个函数的声明都在mmsystem.h中:
1.MCIERROR mciSendString(LPCTSTR lpszCommand,LPTSTR lpszReturnString,UINT cchReturn,HANDLE hwndCallback);命令字符串方式,用接近于日常生活用语的方式发送控制命令,适用于RAD编程如VB。
2. MCIERROR mciSendCommand(MCIDEVICEID
wDeviceID:指定了设备标识,这个标识会在程序员打开MCI设备时由系统提供。
UINTuMsg:指定将如何控制设备,即"MCI指令",比较常用的指令有MCI_OPEN、MCI_CLOSE、MCI_PLAY、MCI_STOP、MCI_PAUSE、MCI_STATUS等等。
DWORD dwFlags:为访问标识。
DWORD dwParam):一般是一个数据结构,标识程序在访问MCI时要的一些信息。我们在实例中将通过使用数据结构MIC_OPEN_PARMS来指定设备类型的。
命令消息方式,用专业语法发送控制消息,适用于VC等语言编程,此方式直接与MCI设备打交道,我们的实例即使用此函数。
MIC_OPEN_PARMS结构如下:
typedef struct { DWORD dwCallback;
MCIDEVICEID wDeviceID; //设备ID
LPCSTR lpstrDeviceType; //设备类型名
LPCSTR lpstrElementName; //设备元素名(通常是要处理的文件名)
LPCSTR lpstrAlias;
MCI_OPEN_PARMS;
2.制作过程
下面我们就以一个实例来说明MP3播放器的具体实现方法:
1.建立一个MFC AppWizard(exe)应用工程mp3Player。
在MFC AppWizard向导的第一步中选择Single Document,在第六步将CMp3PlayerView的base Class设为CformView,再点击按键Finish->OK完成工程的建立。
2.在资源编辑器中编辑ID号为IDD_MP3PLAYER_FORM的Dialog,在其上添加两个Static Text 控件,其一命名为STATIC1,用来显示状态提示信息。如图1:
(图片统一在后面,需5点威望)
绘制工具条如图2:
(图片统一在后面,需5点威望)
设置菜单如图3:
(图片统一在后面,需5点威望)
3.通过Class Wizard创建一个新类CMciControl,代码如下:
// MciControl.h: interface for the CMciControl class.
// Copyright(c) 2003 by lilipuss
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MCICONTROL_H__D4CDBB30_01C4_11D8_BEEE_C2001FA02C0E__INCLUDED_)
#define AFX_MCICONTROL_H__D4CDBB30_01C4_11D8_BEEE_C2001FA02C0E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "mmsystem.h"
class CMciControl
{
private:
MCI_OPEN_PARMS mciOpen;
public:
CMciControl();
~CMciControl() {Close(); }
//通过描述字符串打开设备
MCIERROR Open(LPCSTR DeviceType,LPCSTR filename);
void Play(void); //播放MCI
void Close(void); //关闭设备
void Stop(void); //停止设备
void Pause(void); //暂停设备
};
#endif // !defined(AFX_MCICONTROL_H__D4CDBB30_01C4_11D8_BEEE_C2001FA02C0E__INCLUDED_)
// MciControl.cpp: implementation of the CMciControl class.
// Copyright(c) 2003 by lilipuss
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "mp3player.h"
#include "MciControl.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMciControl::CMciControl()
{
}
MCIERROR CMciControl::Open(LPCSTR DeviceType,LPCSTR filename)
{
//如果有打开的MCI设备就关闭
if (mciOpen.wDeviceID) Close();
//初始化MCI_OPEN_PARMS结构
mciOpen.lpstrDeviceType=DeviceType;
mciOpen.lpstrElementName=filename;
//除了打开设备设备代码为0,
//下面的任何mciSendCommand语句都要指定设备代码。
if ( mciSendCommand(NULL,
MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)&mciOpen))
return FALSE;
return TRUE;
}
void CMciControl::Play(void)
{
//执行MCI_PLAY操作,播放音乐
mciSendCommand(mciOpen.wDeviceID,MCI_PLAY,NULL,NULL);
}
void CMciControl::Close(void)
{
if (mciOpen.wDeviceID)
//执行MCI_CLOSE操作,关闭MCI设备
mciSendCommand(mciOpen.wDeviceID,MCI_CLOSE,NULL,NULL);
}
void CMciControl::Stop(void)
{
if (mciOpen.wDeviceID)
//执行MCI_STOP操作,停止播放音乐
mciSendCommand(mciOpen.wDeviceID,MCI_STOP,NULL,NULL);
//把播放位置设定为音乐文件的开头(使下一次播放操作从文件开头位置开始)
mciSendCommand(mciOpen.wDeviceID,MCI_SEEK,MCI_SEEK_TO_START,NULL);
}
void CMciControl::Pause(void)
{
if (mciOpen.wDeviceID)
//执行MCI_PAUSE操作,暂停播放音乐
mciSendCommand(mciOpen.wDeviceID,MCI_PAUSE,NULL,NULL);
}
4.在CMp3PlayerView类定义中添加三个私有成员变量:
private:
//MCI状态变量 default=0x1111
//播放状态:0x0001
//暂停状态:0x0010
//停止状态:0x0100
LONG m_lStatus;
//音乐文件名 default=_T("")
CString m_strFileName;
//CMciControl Object,用来控制MCI设备的操作
CMciControl m_MciCtrl;
5.在CMp3PlayerView.cpp头部加入
//API函数WritePrivateProfileString声明在windows.h中
#include "windows.h"
在CMp3PlayerView的成员函数OnInitialUpdate()中添加如下代码:
//调用API函数在system.ini的[mci]项中添加mp3audio=mciqtz.drv
WritePrivateProfileString("MCI",
"mp3audio",
"mciqtz.drv",
"C:\\windows\\system.ini");
//初始化状态提示
CString str("目前无音乐文件被选中\n[请通过菜单进行选择]");
SetDlgItemText(IDC_STATIC1,str);
6.通过Class Wizard为CMp3PlayerView类添加下列函数:
void OnFileOpen();
void OnPlay();
void OnPause();
void OnStop();
void OnUpdatePause(CCmdUI* pCmdUI);
void OnUpdatePlay(CCmdUI* pCmdUI);
void OnUpdateStop(CCmdUI* pCmdUI);
函数代码及说明如下:
void CMp3PlayerView::OnFileOpen()
{
//通过打开对话框选择mp3音乐文件
CString strFilter("MP3 Files (*.mp3)|*.mp3||");
CFileDialog OpenDlg(TRUE,
NULL,
NULL,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
strFilter);
int nFlags=OpenDlg.DoModal();
if(nFlags==IDOK){
//将文件路径名赋给成员变量m_strFileName备用
m_strFileName=OpenDlg.GetPathName();
//打开一个MCI设备,并把该设备分配给选中的文件使用
m_MciCtrl.Open("mp3audio",m_strFileName);
//播放选中的mp3音乐文件
OnPlay();
}
}
void CMp3PlayerView::OnPlay()
{
//执行播放操作
m_MciCtrl.Play();
//设置当前状态提示
CString str("当前状态:播放\n曲目:");
str+=m_strFileName;
SetDlgItemText(IDC_STATIC1,str);
//设置状态变量
m_lStatus=0x0001;
}
void CMp3PlayerView::OnPause()
{
//执行暂停操作
m_MciCtrl.Pause();
//设置当前状态提示
CString str("当前状态:暂停\n曲目:");
str+=m_strFileName;
SetDlgItemText(IDC_STATIC1,str);
//设置状态变量
m_lStatus=0x0010;
}
void CMp3PlayerView::OnStop()
{
//执行停止操作
m_MciCtrl.Stop();
//设置当前状态提示
CString str("当前状态:停止\n曲目:");
str+=m_strFileName;
SetDlgItemText(IDC_STATIC1,str);
//设置状态变量
m_lStatus=0x0100;
}
void CMp3PlayerView::OnUpdatePause(CCmdUI* pCmdUI)
{
//当前状态为暂停或播放时,暂停按钮不可用
pCmdUI->Enable(!(m_lStatus&0x0010)&&!(m_lStatus&0x0100));
}
void CMp3PlayerView::OnUpdatePlay(CCmdUI* pCmdUI)
{
//当前状态为播放时,播放按钮不可用
pCmdUI->Enable(!(m_lStatus&0x0001));
}
void CMp3PlayerView::OnUpdateStop(CCmdUI* pCmdUI)
{
//当前状态为停止时,停止按钮不可用
pCmdUI->Enable(!(m_lStatus&0x0100));
}
7.在"projoct"菜单下单击setting,弹出设置对话框,在"link"下"object/librarymodules"下加入"winmm.lib",编译并运行程序,效果图如图4:
(图片统一在后面,需5点威望)
3.结束语
上面的例子只支持mp3格式,实际上通过对MCI接口的编程我们可以实现对许多种格式的音视频文件的播放控制,无需任何专门的控件,具体的实现方法与上例类似。有兴趣的读者可以参阅MSDN,完全可以制作一个相当专业的播放器。文章中的实例在Windows98系统下以VC++6.0编译通过. |