一个支持所有媒体类型和循环播放的类[精华]


       这篇文章是我第一次在VC在线发表,我应该是只VC的菜鸟。为了找个能循环播放mp3VC源程序,我搜遍了网上的资源(差点气得要砸电脑),好不容易找到一个,却只有程序中的调用,关键的类的生成文件却没有,有什么用?(主要是自己没有MCI函数的具体的参数资料,不知道怎么调用,如果你有,请发一份给我,字符串的我已经有了,命令方式的没有。)

        后来找到一个,非常感谢他,作者叫:黄利龙。但他没有单独把类分离出来,且没有保存列表到文件。

        我把他的程序打印出来,仔细分析了程序语句,然后进行了修改和优化。

大家可以从下面的程序看出来,我们菜鸟的人基础不够,很希望了解每一句的确切意思,有些地方我带有猜测的,如果有错的地方,请大家指出,也欢迎大家来信和我交流,我向您学习。我的Email:[email protected]

        我修改的程序特点如下:

        1、把它分离出来单独构成一个类,便于以后所有程序的使用。

        2、提供了接口函数。

        3、支持所有的媒体类型

        4、能循环播放音乐

        5、能保存上次打开的文件。

        难免会有错,请大家可以不断完善它,然后把它贴出来,这样,以后有类似遭遇的不用这么辛苦了!

   

        CMidi类的使用方法:

          1、直接把MIDI.hMIDI.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();

  }

 

/ /Midi.h

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

#ifndef __MIDI_H__

#define __MIDI_H__

 

#include

 

class CMidi

{

 

public:

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

 CMidi();

 ~CMidi();

public:

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

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

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

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

 bool SaveList();//保存列表

 void Per();//上一首

 void Next();//下一首

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

 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文件

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

// 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为打开对话框中获取的歌曲总数

  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();//指向下一首

 }

}

 

  附:类的源文件

----------------------------------------摘自http://www.web521.com/vc/548068/T637432.shtml

你可能感兴趣的:(一个支持所有媒体类型和循环播放的类[精华])