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

封装了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>  
~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值