您的位置:首页 > 其它

MFC-添加背景音乐(2)-封装了mciSendCommand的简单MCI类 .

2012-01-16 13:44 489 查看
封装了mciSendCommand的简单MCI类

2006-10-22 10:08

前阵子写了篇mciSendCommand简介的文章,大家看得比较多,说明大家需要这方面的东西哈。今天有空写了个简单的MCI类给大家贴出来。这个类很简单,只实现了简单的文件打开、播放、暂停、继续、关闭几个功能,供大家学习研究哈。如果哪位高手把这个类扩展了也请给我一份哈,以备不时之需哈。

这个类必须在MFC支持下才能使用,因为用了MFC 的CString。请在编译的时候链接上winmm.lib

类的代码如下:

////////////////////////////

//CMCI.h

//////////////////////////////////////////////////////

#include <mmsystem.h>

class CMCI

{

public:

void Resume();

void Pause();

void Close();

void Play(UINT From,UINT To);

UINT m_iDeviceType;

CMCI(CString FilePath,CString DeviceType);

virtual ~CMCI();

};

////////////////////////

//cMCI.cpp

/////////////////////////////

#include "stdafx.h"

#include "CMCI.h"

#pragma comment(lib, "winmm.lib ")

CMCI::CMCI(CString FilePath,CString DeviceType="MPEGAudio")

{

MCI_OPEN_PARMS pm;

pm.dwCallback=NULL;

pm.lpstrAlias=NULL;

pm.lpstrDeviceType=DeviceType;

pm.lpstrElementName=FilePath;

pm.wDeviceID=NULL;

if(0==mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_ELEMENT,(DWORD)&pm))

{

this->m_iDeviceType=pm.wDeviceID;

}

}

CMCI::~CMCI()

{

if(this->m_iDeviceType) Close();

}

void CMCI::Play(UINT From, UINT To)

{

MCI_PLAY_PARMS pm;

pm.dwCallback=0;

pm.dwFrom=From;

pm.dwTo=To;

if(!this->m_iDeviceType) return;

mciSendCommand(this->m_iDeviceType,

MCI_PLAY,

MCI_NOTIFY,

(DWORD)&pm);

}

void CMCI::Close()

{

if(this->m_iDeviceType)

{

MCI_GENERIC_PARMS gp;

gp.dwCallback=NULL;

mciSendCommand(this->m_iDeviceType,

MCI_CLOSE,

MCI_WAIT,

(DWORD)&gp);

this->m_iDeviceType=NULL;

}

}

void CMCI::Pause()

{

if(this->m_iDeviceType )

{

MCI_GENERIC_PARMS gp;

gp.dwCallback=NULL;

mciSendCommand(this->m_iDeviceType,

MCI_PAUSE,

MCI_WAIT,

(DWORD)&gp);

}

}

void CMCI::Resume()

{

if(this->m_iDeviceType )

{

MCI_GENERIC_PARMS gp;

gp.dwCallback=NULL;

mciSendCommand(this->m_iDeviceType,

MCI_RESUME,

MCI_WAIT,

(DWORD)&gp);

}

}

这个类的用法:

1、在CXXDlg.h中加入成员变量

CMCI *mymci;

2、在某个消息中构建CMCI的实例并播放文件

CString str1="e://1.mp3";//路径

mymci=new CMCI(str1);//构建对象实例

mymci->Play();//调用方法

3、在适当的时候(通常是程序退出)关闭对象

mymci->Close();

请注意,不要在堆栈中写这样的代码:

CMCI mci;

mci.Play()

这样并不会播放某个文件,因为在这段代码结束的时候,刚才定义的对象已经释放销毁了。

成员列表:

void Resume(); //继续播放

void Pause();//暂停播放

void Close();//关闭该对象(文件)

void Play(UINT From,UINT To);//开始播放

UINT m_iDeviceType;//该文件(对象)的mciSendCommand中的MciDevice

CMCI(CString FilePath,CString DeviceType);//构造器,初始化该对象(文件)

virtual ~CMCI();//销毁该对象

源文档 <http://www.cnblogs.com/witxjp/archive/2010/5/6.html>

// Midi.h

/*

CMidi类的使用方法:

1、直接把MIDI.h和MIDI.cpp文件复制到你程序目录下,工程中加入这两个

文件。

2、单击“工程-> 设置-> Link”,在“对象/库模块”中连接库winmm.lib

3、在你工程的头文件中包含头文件,#include "MIDI.H "

4、在工程中定义一个CMidi类的对象,如:CMidi m_Music;

5、在工程的初始化文件中,初始化歌曲列表路径,m_Music.InitPath(),

再打开列表,m_Misic.OpenList();下面就可以在各个对应的消息函数中处

理它了

如:

播放:m_Misic.Play();

停止:m_Misic.Stop();

上一首:m_Misic.Per();

下一首:m_Misic.Next();

打开:m_Misic.OpenFiles();

保存歌曲列表:m_Misic.SaveList();

//保存列表我没有放在打开函数中,如果打开的文件比较多,那样会在

打开过一会儿才能播放音乐,不舒服,你自己到工程的OnDestroy()中保存吧

循环播放:m_Misic.OnTimer();

//它需要在主程序中打开一个定时器,SetTimer(0,500,NULL);然后在主程序

中重载OnTimer()函数,在该函数体内,先判断是否正在播放,

m_Misic.PlayingFalg是否为真,真,则调用循环播放函数。如下:

{

if(m_Misic.PlayingFalg)

m_Misic.OnTimer();

}

*/

#ifndef __MIDI_H__

#define __MIDI_H__

#include <mmsystem.h>

class CMidi

{

public:

bool Play();//播放初始化函数(打开设备并初始化)

CMidi();

~CMidi();

public:

void OnTimer();//循环播放函数

bool InitPath();//初始化路径,取得播放曲目列表文件的全路径

bool OpenFiles();//打开文件对话框,获取歌曲列表

bool OpenList();//读取文件中的歌曲列表

bool SaveList();//保存列表

void Per();//上一首

void Next();//下一首

void Stop();//停止函数,在播放以前先停止

void Display( CString& );//显示播放列表

DWORD getinfo(DWORD item);//获取歌曲长度信息

DWORD m_count;

DWORD cdlen,cdfrom,cdto;

int m_totalFiles;//保存歌曲的首数

int fr;//当前已播放的歌曲数

CString m_FileList[256];//歌曲路径列表数组

CString m_MusicFilePath;//保存歌曲列表文件的路径

bool PlayingFalg;//正在播放标志,以便定时器判断

};

#endif

// Midi.cpp

#include "stdafx.h "

#include "Midi.h "

CMidi::CMidi()

{

m_totalFiles=0;

fr=0;

cdfrom=0;

m_MusicFilePath= " ";

PlayingFalg=false;

}

CMidi::~CMidi()

{

}

//------------播放---------------------

bool CMidi::Play()

{

if(m_FileList[fr]== " ")

{//如果读取路径为空,则弹出打开对话框

OpenFiles();

}

else

{

PlayingFalg=true;//标志为正在播放

MCI_OPEN_PARMS mciopenparms;//打开

MCI_PLAY_PARMS mciplayparms;//播放

//以下用fr做下标,能在停止再播放时恢复上次的位置

mciopenparms.lpstrElementName=m_FileList[fr];//播放路径

mciopenparms.lpstrDeviceType=NULL;//文件类型为NULL,就可以支持全部类型

mciSendCommand(0,MCI_OPEN,MCI_DEVTYPE_WAVEFORM_AUDIO,

(DWORD)(LPVOID)&mciopenparms);//向MCI设备发送命令消息

m_count=mciopenparms.wDeviceID;

mciplayparms.dwCallback=NULL;//窗口拥有者句柄

cdlen=getinfo(MCI_STATUS_LENGTH);//得到曲目长度

cdto=MCI_MAKE_HMS(MCI_HMS_HOUR(cdlen),MCI_HMS_MINUTE(cdlen),

MCI_HMS_SECOND(cdlen));//根据长度计算出时、分、秒

mciplayparms.dwFrom=MCI_MAKE_HMS(0,0,0);//表示从哪儿开始播放吧

mciplayparms.dwTo=cdto;//表示放到哪儿为止

mciSendCommand(m_count,MCI_PLAY,MCI_TO|MCI_FROM,

(DWORD)(LPVOID)& mciplayparms); //发送播放消息

}

return true;

}

//---------------获取歌曲信息(长度,已播放长度)------

DWORD CMidi::getinfo(DWORD item)

{

MCI_STATUS_PARMS mcistatusparms;

mcistatusparms.dwCallback=NULL;

/* //接受传入的命令参数,这是关键。命令参数如下:

获取歌曲长度: MCI_STATUS_LENGTH

获取当前已播放的长度:MCI_STATUS_POSITION

*/

mcistatusparms.dwItem=item;//接受命令参数的地方

mcistatusparms.dwReturn=0;//返回值

mciSendCommand(m_count,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)&mcistatusparms);

return mcistatusparms.dwReturn;

}

//-------------------停止-------------------

void CMidi::Stop()

{

PlayingFalg=false;//关闭正在播放标志

cdfrom=MCI_MAKE_HMS(0,0,0);//播放位置归文件开头

mciSendCommand(m_count,MCI_CLOSE,0,NULL);//发出关闭消息

m_count=0;

}

//-------------------下一首----------------

void CMidi::Next()

{

fr++;

if(fr> =m_totalFiles)

{

//让fr指向下一个音乐文件,fr是从0下标开始

//m_totalFiles为总文件数

fr=fr%m_totalFiles;

}

Stop();

Play();

}

//----------上一首------------------

void CMidi::Per()

{

fr--;

if(fr==-1)

{//指向最后一首歌,但fr是从0下标开始的,而m_totalFiles是从1开始

fr=m_totalFiles-1;

}

Stop();

Play();//播放fr指向的位置

}

//----------保存曲目列表-----------------

bool CMidi::SaveList()

{

CFile fileList;//文件对象

if(!fileList.Open(m_MusicFilePath,CFile::modeCreate|CFile::modeWrite))

return FALSE;//打开文件,不存在则创建,写文件

char fileName[256];

for(int i=0;i <m_totalFiles;i++)

{//m_totalFiles为打开对话框中获取的歌曲总数

strcpy(fileName,m_FileList[i]);//取出一条曲目路径

fileList.Write(fileName,strlen(fileName));//写入文件

fileList.Write( "/r/n ",2);//写入一行结束和换行符

}

fileList.Write( "---- ",4);//写入文件最后标志

fileList.Close();//关闭文件

return TRUE;

}

//----------读取曲目路径列表-----------------

bool CMidi::OpenList()

{

CFile fileList;

if(!fileList.Open(m_MusicFilePath,CFile::modeNoTruncate|CFile::modeRead))

return FALSE;//以只读模式打开,不覆盖原有文件,m_MusicFilePath为列表文件的路径

char ch;

while(1)

{

CString fileName;

fileList.Read(&ch,1);//读入一个字符

if(ch== '- ') break; //如文件是最后返回,-是文件最后的标志

fileName+=ch;//否则存入

while(1)

{//读入一行

fileList.Read(&ch,1);

if(ch== '/r ')

{//这儿可以判断是一行了

m_totalFiles++;//曲目首数计数

fileList.Read(&ch,1);

break;

}

fileName+=ch;

}

//下面这句把路径加入列表中,用字符串数组代替

//m_totalFiles前面已经加一了,所以这儿要少一个

m_FileList[m_totalFiles-1]=fileName;

}

fileList.Close();

return TRUE;

}

//----------打开对话框,获取曲目列表-----------------

bool CMidi::OpenFiles()

{

CFileDialog f(true);//打开对话框对象

f.m_ofn.Flags |=512;//OFN_ALLOWMULTISELECT;目录列表方式

f.m_ofn.lpstrFilter= "所有媒体类型/0*.*/0/0 ";

if(f.DoModal()!=IDOK)

return FALSE;//用户单击了“取消”

POSITION pos=f.GetStartPosition();//获取第一个文件位置

int i=0;

while(pos)

{

m_FileList[i]=f.GetNextPathName(pos);//读取文件到曲目路径列表

i++;

}

m_totalFiles=i;//保存曲目总数

Stop();

Play();//播放打开的文件

return TRUE;

}

//-------------------获得播放列表文件的路径------------

bool CMidi::InitPath()

{//初始化路径,取得播放曲目列表文件的全路径

TCHAR path[256];//保存文件路径

GetModuleFileName(NULL,path,sizeof(path)) ;//获取当前程序路径

TCHAR * p = _tcsrchr(path,_T( '// ')) ;//查找最后一个 '// '字符

if(p) lstrcpy(p,_T( "//MPlayer.mdr "));//替换成要查找的完整路径

m_MusicFilePath=path;//保存到路径变量中,以便用它来打开列表文件

return true;

}

//----------------------循环播放------------------

void CMidi::OnTimer()

{//循环播放

if(getinfo(MCI_STATUS_POSITION)==cdlen)

{//如当前播放的长度等于歌曲的长度,说明已经播放完毕

Next();//指向下一首

}

}

//----------------------循环播放------------------

void CMidi::Display( CString& output )

{

int i;

output.Empty();

for( i=0;i <m_totalFiles;++i )

{

output += m_FileList[i];

output += "/r/n ";

}

}

源文档 <http://topic.csdn.net/t/20050622/16/4099738.html>

~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: