自己动手写类似酷狗播放器(2)_音乐播放模块实现

   上一章中,主要是介绍了WINDOWS消息机制和模板对话框的创建,其实学到现在感觉windows程序设计就是各种逻辑+API函数。所以MSDN很重要。由于整个代码太大了,所以下面系列文章中,我只讲思路以及一些控件的用法。源代码以后会上传。请大家多多支持...
	下面先上个 最后的效果图..

     这节主要总结下最核心的播放功能,如何实现的。只提供关键思路。
核心思路:
1.按“添加”按钮,将添加歌曲进入Listbox。具有数字标号+歌曲名字
            这里包括文件添加的操作,listBox的插入操作,字符串函数的操作
2.双击Listbox中某个歌曲将可以播放,并且可以有时间进度条和总时间
           这里包括 listbox响应双击事件,mcisendCommand和关联结构体操作

1.添加文件的操作

    在开始播放前,肯定要手动添加哪些要加入到播放列表中,就是上面按钮"添加"触发的操作。这里涉及文件的打开以及多个文件同时选中的情况。关键代码如下:

void  DoSelectFile(HWND hwnd) //选择文件
{
	
	OPENFILENAME ofn;  //定义一个文件结构体
	TCHAR szOpenFileNames[80*MAX_PATH]; //打开的文件名字
	TCHAR szPath[MAX_PATH]; //歌曲文件的路径 其实操作一个Mp3文件就是通过路径来操作的
	TCHAR szFileName[80*MAX_PATH];
	ZeroMemory(szOpenFileNames,sizeof(szOpenFileNames)/sizeof(TCHAR));
	ZeroMemory(&ofn,sizeof(ofn));
	ZeroMemory(szFileName,sizeof(szFileName));
	ZeroMemory(szPath,sizeof(szPath));  //清空 各类结构
	//配置ofn各字段
	ofn.Flags=OFN_EXPLORER|OFN_ALLOWMULTISELECT;//指定浏览功能,和允许多选功能
	ofn.hwndOwner=hwnd; //父句柄为当前对话框
	ofn.lStructSize=sizeof(ofn);//整个ofn结构体的大小   (这里以前犯了个错误&ofn)
	ofn.lpstrFile=szOpenFileNames;//打开的文件的全路径
	ofn.nMaxFile=sizeof(szOpenFileNames);//文件大小的最大值
	ofn.lpstrFile[0]='\0';//指定第一个为NULL字符
	ofn.lpstrFilter=TEXT("*.mp3\0*.mp3\0*.wav\0*.wav\0All files\0*.*\0");//文件过滤器
	if(GetOpenFileName(&ofn)) //成功返回非零 不成功为0
	{	
		TCHAR withnum_song[255];//带数字列表的 插入到listbox的歌曲名
		ZeroMemory(withnum_song,sizeof(withnum_song)/sizeof(TCHAR));
		lstrcpyn(szPath,szOpenFileNames,ofn.nFileOffset);//获取该多个文件所在的目录 单个文件不需要加‘\’,多个文件少个\
		if(szPath[lstrlen(szPath)-1]!='\\')    
		{
			lstrcat(szPath,TEXT("\\")); //这里又要犯错误了,lstrcat是连接两个字符串,\在字符串中必须是"\\"
		}
	//	MessageBox(hwnd,szPath,TEXT("szPath2"),MB_OK);
		TCHAR *p=szOpenFileNames+ofn.nFileOffset;//get the first file name
		while(*p)
		{	
			lstrcpy(fileinfo[isong].songname,p); //  保存歌曲名     歌曲复制到 全局文件信息库
			lstrcpy(szFileName,szPath);
			lstrcat(szFileName,p);
			lstrcpy(fileinfo[isong].szfiledir,szFileName); //保存歌曲完整路径
			TCHAR puresn[255]; //纯的songname=sn
			ZeroMemory(puresn,sizeof(puresn)/sizeof(TCHAR));
			TCHAR *pos=strrchr(p,'.');//从后往前查找'.' .mp3的.
			lstrcpyn(puresn,p,pos-p+1);
			ZeroMemory(withnum_song,sizeof(withnum_song)/sizeof(TCHAR));
			wsprintf(withnum_song,TEXT("%02d  %s"),isong+1,puresn);
			ListBox_InsertString(hlistbox,-1,withnum_song);
			p=p+lstrlen(p)+1; //移动到下一个文件名
			ZeroMemory(szFileName,sizeof(szFileName));
			isong++; //歌曲自加1
		}
	}
}
     上面就是文件的操作了,包括歌曲的添加和 往ListBox中插入歌曲名字。其实全部都是文件路径的操作,我们要得到歌曲的路径,存于全局变量中 我这里是存到一个全局结构体中,用来存放歌曲名字和路径 。

typedef struct   //defined a information struct for song
{
	TCHAR songname[50];     //注意这个值过小 可能导致 输入的信息有误,要保证有绝对空间  查了半天的错
	TCHAR szfiledir[100];
}FileInfo;
FileInfo fileinfo[255];   //文件信息 只能存255首歌曲
     歌曲的名字,我们希望有标号,并且希望歌曲名字不带.mp3的字样,这里就是截取的方法,利用字符串函数的操作,来获取我们想要的文件名字。当我们同时选取了多个文件时,实际上在内存中存在的形式就是该文件的目录+各个文件名字,每个文件名字以一个'\0'隔开。在调用完(GetOpenFileName(&ofn)这个函数成功后,会将你选择的文件名全部存于该 ofn.lpstrFile=szOpenFileNames.也就是存于szOpenFileNames的数组中。

所以剩下要做两件事: 1.获取每首歌曲完整路径    2.拼写出每个歌曲的名字 
将获取的名字 格式化 加上数字,就插入到Listbox中即可。具体的参见工程中的代码。

2.播放音乐

      在上面我们大概了解了这么添加文件和修改文件名,剩下的就是要播放了,其实要播放一首歌曲很简单,只需要条用mciSendCommand().函数即可,比如下面代码就可以播放一首歌曲
	mciSendCommand(DeviceId,MCI_PLAY,MCI_FROM|MCI_NOTIFY,(DWORD)(LPVOID)&mciplay);
参数1:是要播放的设备号 参数2:是要播放的命令,参数3:是从哪里播放和播放完发送给主窗口一个通知
参数4:是结构体。每个mcisendcommand 都要关联一个结构体,这要关联播放mciplay
MCIDEVICEID DeviceId=0;		//打开的设备ID号
MCI_OPEN_PARMS mciopen;  //打开结构体
MCI_PLAY_PARMS mciplay;	 //播放结构体
MCI_SET_PARMS  mciset;   //设置时间格式
MCI_SEEK_PARMS mciseek;	// 设置跳转到
MCI_STATUS_PARMS mcistatus; //播放状态 获得歌曲总长度
具体的意思 和怎么使用查找 MSDN手册。
      思路:就是先配置 mciopen。指定打开的路径(就是音乐文件的路径)成功打开后,得到一个设备号,然后用该设备号来操作,比如播放,暂停,关闭..附加的功能 比如获取 歌曲状态,得到歌曲的总时间。
下面代码演示了怎么打开设备和获取歌曲总时间长度
BOOL DoPlay(HWND hwnd,INT index)  
{	
	mciopen.lpstrElementName=fileinfo[index].szfiledir;	//给打开设备指定路径
	mciSendCommand(DeviceId,MCI_STOP,0,0); 
	mciSendCommand(DeviceId,MCI_CLOSE,0,0);	//先关闭全部变量的设备
	if(0==mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciopen))  //成功返回为0
	{	
	//	MessageBox(hwnd,TEXT("MCIOPEN打开设备成功"),TEXT(""),MB_OK);
		DeviceId=mciopen.wDeviceID;//成功打开后将ID号保留下来。
		mciset.dwTimeFormat=MCI_FORMAT_MILLISECONDS; //config mciset time format
		mciSendCommand(DeviceId,MCI_SET,MCI_WAIT|MCI_FORMAT_MILLISECONDS,(DWORD)(LPMCI_SET_PARMS)&mciset);//设置歌曲的长度以Ms度量	
		mcistatus.dwItem=MCI_STATUS_LENGTH; 
		mciSendCommand(DeviceId,MCI_STATUS,MCI_WAIT|MCI_STATUS_ITEM,(DWORD)(LPMCI_STATUS_PARMS)&mcistatus);
		DWORD dwsonglen=mcistatus.dwReturn/1000; //返回歌曲的总长度 ms级别的 dwsonglen单位是秒
		SendDlgItemMessage(hwnd,IDC_SLIDER_SONG,TBM_SETRANGE,TRUE,MAKELPARAM(0,dwsonglen));//设置Silder的两端范围

		mciplay.dwFrom=0;//从0开始播放
		mciplay.dwCallback=(DWORD)hwnd;//播放完毕后,通该窗口处理函数
		mciSendCommand(DeviceId,MCI_PLAY,MCI_FROM|MCI_NOTIFY,(DWORD)(LPVOID)&mciplay);//开始播放
		ListBox_SetCurSel(hlistbox,iIndex);  //设置当前选中宏
		return TRUE;
	}
	else 
		MessageBox(hwnd,TEXT("打开歌曲错误"),TEXT("errror!"),MB_OK);
		return FALSE;
}
 下个模块继续...              							
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值