多媒体技术教程期末实验报告题目:基于MFC的简单音乐播放器班级:软件工程专业:软件工程姓名:xxx学号:xxxxxxxxxx指导老师:xxxXxxxxxx一、课题描述音乐播放器是一种用于播放各种音乐文件的多媒体播放软件。
利用MFC应用程序、媒体控制接口MIC的基本知识,设计一个功能非常简单易于操作的MP3播放器。
要求能够播放常用Windows音频格式的文件;实现播放控制:播放、暂停、音量增减、添加歌曲等功能;实现从本地磁盘加入文件,然后对其进行播放。
本程序是基于MFC对话框的简单程序实现音乐的简单控制。
二、功能分析MFC简单音乐播放器主要对常用Windows音频格式的文件实现播放控制:播放歌曲、暂停播放、停止播放等;实现音量控制:静音、声音放大以及声音减小的功能。
利用MCI基本知识实现相关功能。
通过该程序可以实现简单的音乐播放。
核心是让音乐文件和音乐播放设备关联。
三、源代码和截图具体属性和类向导如下:实现后截图:四、实验心得:实现播放时间的控制是我在实验时遇到的难题,通过上网查询资料得以实现。
制作音乐播放器其实是个挺有趣的体验,完成了也有小小成就感。
但这个简易音乐播放器还有许多功能尚未实现,例如同步歌词显示等等,要真正做一个完善的播放器还需要很多努力。
各个控件的函数如下://浏览void CMFCDlg::Onfilechoice(){char szFileFilter[]="mp3文件(*.mp3)|*.mp3|""wma文件(*.wma)|*.wma|""wav文件(*.wav)|*.wav|""所有文件(*.*)|*.*|";CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY,szFileFilter);if(dlg.DoModal()==IDOK){CString strFilepath=dlg.GetPathName();CString strFilename=dlg.GetFileName();SetDlgItemText(IDC_filename,strFilename);Load(this->m_hWnd,strFilepath);GetDlgItem(IDC_play)->EnableWindow(true);//文件读取成功时所有按钮变可选的GetDlgItem(IDC_pause)->EnableWindow(true);GetDlgItem(IDC_stop)->EnableWindow(true);m_list.InsertString(m_list.GetCount(),strFilename);m_list.SetCurSel(m_list.GetCount()-1);}}//播放void CMFCDlg::Onplay(){CString strfilename;int index=m_list.GetCurSel();CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观dc.SetTextColor(RGB(255,255,203));//设置数字显示的颜色mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);if(index==-1){MessageBox("请添加音乐");return;}m_list.GetText(index,strfilename);SetDlgItemText(IDC_filename,strfilename);stop();Load(this->m_hWnd,strfilename);play();SetTimer(0,1000,NULL);}//暂停void CMFCDlg::Onpause(){CString strtemp;GetDlgItemText(IDC_pause,strtemp);//获取按钮状态if(pare("暂停")==0){pause();SetDlgItemText(IDC_pause,"恢复");KillTimer(0);//取消计数器的显示}if(pare("恢复")==0){resume();SetTimer(0,1000,NULL);SetDlgItemText(IDC_pause,"暂停");}}//停止void CMFCDlg::Onstop(){stop();SetDlgItemText(IDC_pause,"暂停");KillTimer(0);//取消计数器的显示CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观dc.SetTextColor(RGB(255,255,203));//设置数字显示的颜色mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);GetDlgItem(IDC_play)->EnableWindow(false);//当stop按钮按下时,播放和暂停应该均不可用GetDlgItem(IDC_pause)->EnableWindow(false);GetDlgItem(IDC_del)->EnableWindow(false);}//添加void CMFCDlg::Onfileopen(){char filefiler[]="mp3文件(*.mp3)|*.mp3|""wma文件(*.wma)|*.wma|""wav文件(*.wav)|*.wav|";CFileDialogdlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT|OFN_ENABLESIZING,filefi ler);if (dlg.DoModal()==IDOK){CString strfilepath=dlg.GetPathName();CString strfilename=dlg.GetFileName();SetDlgItemText(IDC_filename,strfilename);CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观dc.SetTextColor(RGB(255,255,203));//设置数字显示的颜色mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);Load(this->m_hWnd,strfilepath);GetDlgItem(IDC_play)->EnableWindow(true);GetDlgItem(IDC_pause)->EnableWindow(true);GetDlgItem(IDC_stop)->EnableWindow(true);GetDlgItem(IDC_del)->EnableWindow(true);m_list.InsertString(m_list.GetCount(),strfilename);//获取文件名m_list.SetCurSel(m_list.GetCount()-1);}}//删除void CMFCDlg::Ondel(){// TODO: Add your control notification handler code hereUpdateData(TRUE);int index=m_list.GetCurSel();stop();SetDlgItemText(IDC_filename,"");KillTimer(0);hour=0;minute=0;second=0;if(index!=CB_ERR){m_list.DeleteString(index);}}void CMFCDlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call defaultCString mtime;second++;CClientDC dc(this);dc.SetBkColor(RGB(124,252,0));dc.SetTextColor(RGB(255,255,203));if(second==60){minute++;second=0;}if(minute==60){hour++;minute=0;}mtime.Format("%02d:%02d:%02d",hour,minute,second);dc.TextOut(320,85,mtime);DWORD cdf=getinformation(MCI_STATUS_POSITION);DWORD cdfrom;cdfrom=MCI_MAKE_MSF(MCI_MSF_MINUTE(cdf),MCI_MSF_SECOND(cdf),MCI_MSF_FRAME(cdf));UpdateData(false);CDialog::OnTimer(nIDEvent);}//双击列表void CMFCDlg::OnDblclkList(){CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观dc.SetTextColor(RGB(255,255,203));//设置数字显示的颜色mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);CString strfilename;int index=m_list.GetCurSel();m_list.GetText(index,strfilename);SetDlgItemText(IDC_filename,strfilename);stop();Load(this->m_hWnd,strfilename);play();SetTimer(0,1000,NULL);}//上一首void CMFCDlg::Onprevious(){int index;index=m_list.GetCurSel();index-=1;if(index<0){MessageBox("亲,没有上一首了哟~");return;}m_list.SetCurSel(index);Onplay();}//下一首void CMFCDlg::Onnext(){CString filename;CString temp;int index;index=m_list.GetCurSel();index+=1;if(index==m_list.GetCount()){MessageBox("已经是最后一首了,亲^.^");return;}m_list.SetCurSel(index);Onplay();}//退出软件void CMFCDlg::Onexitbt(){CDialog::OnCancel();}==========================MFC音乐播放器Dlg.cpp================================ // MFC音乐播放器Dlg.cpp : implementation file//#include "stdafx.h"#include "MFC音乐播放器.h"#include "MFC音乐播放器Dlg.h"#include "Mmsystem.h"#include "Digitalv.h"#pragma comment(lib,"Winmm.lib")#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifHWND m_hWnd;DWORD DeviceID;MCI_OPEN_PARMS mciopenparms;int hour,minute,second;void Load(HWND hWnd,CString strFilepath){m_hWnd=hWnd;mciSendCommand(DeviceID,MCI_CLOSE,0,0);//在加载文件前先清空上一次播放的设备mciopenparms.lpstrElementName=strFilepath;//将音乐文件路径传给设备DWORD dwReturn;if(dwReturn=mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_ELEMENT|MCI_WAIT,(DWORD)(L PVOID)&mciopenparms)){//如果打开文件失败,则将出错信息储存在buffer,并显示出错警告char buffer[256];mciGetErrorString(dwReturn,buffer,256);MessageBox(hWnd,buffer,"出错警告!",MB_ICONHAND|MB_ICONERROR|MB_ICONSTOP);}DeviceID=mciopenparms.wDeviceID;//打开文件成功就关联文件到设备}DWORD getinformation(DWORD item){MCI_STATUS_PARMS mcistatusparms;mcistatusparms.dwItem=item;mcistatusparms.dwReturn=0;mciSendCommand(DeviceID,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)&mcistatusparms);return mcistatusparms.dwReturn;}void play(){MCI_PLAY_PARMS mciplayparms;mciplayparms.dwCallback=(DWORD)m_hWnd;mciplayparms.dwFrom=0;//每次播放都是从0开始播放mciSendCommand(DeviceID,MCI_PLAY,MCI_FROM|MCI_NOTIFY,(DWORD)(LPVOID)&mciplaypa rms);}void pause(){mciSendCommand(DeviceID,MCI_PAUSE,0,0);}void resume(){mciSendCommand(DeviceID,MCI_RESUME,0,0);}void stop(){mciSendCommand(DeviceID,MCI_STOP,0,0);mciSendCommand(DeviceID,MCI_CLOSE,0,0);//当点击停止按钮时,将所有的信息都清除掉}DWORD setvolume(DWORD vol){MCI_DGV_SETAUDIO_PARMS setvolume;//这是设置音量的参数数据结构setvolume.dwCallback=NULL;setvolume.dwItem=MCI_DGV_SETAUDIO_VOLUME;//动作是设置音量setvolume.dwValue=vol;//音量值是volmciSendCommand(DeviceID,MCI_SETAUDIO,MCI_DGV_SETAUDIO_ITEM|MCI_DGV_SETAUDIO _VALUE,(DWORD)(LPVOID)&setvolume);return 0;}/////////////////////////////////////////////////////////////////////////////// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CMFCDlg dialogCMFCDlg::CMFCDlg(CWnd* pParent /*=NULL*/): CDialog(CMFCDlg::IDD, pParent){//{{AFX_DATA_INIT(CMFCDlg)m_int = 0;//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);hour=0;minute=0;second=0;}void CMFCDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CMFCDlg)DDX_Control(pDX, IDC_LIST, m_list);DDX_Control(pDX, IDC_SLIDER, m_slider);DDX_Text(pDX, IDC_vol, m_int);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CMFCDlg, CDialog)//{{AFX_MSG_MAP(CMFCDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_about, Onabout)ON_BN_CLICKED(IDC_exitbt, Onexitbt)ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER, OnCustomdrawSlider)ON_BN_CLICKED(IDC_filechoice, Onfilechoice)ON_BN_CLICKED(IDC_play, Onplay)ON_BN_CLICKED(IDC_pause, Onpause)ON_BN_CLICKED(IDC_stop, Onstop)ON_BN_CLICKED(IDC_fileopen, Onfileopen)ON_BN_CLICKED(IDC_del, Ondel)ON_WM_TIMER()ON_LBN_DBLCLK(IDC_LIST, OnDblclkList)ON_BN_CLICKED(IDC_previous, Onprevious)ON_BN_CLICKED(IDC_next, Onnext)//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CMFCDlg message handlersBOOL CMFCDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE);// Set big iconSetIcon(m_hIcon, FALSE);// Set small iconm_slider.SetRange(0,1000);//滑块的移动范围0~1000m_slider.SetPos(500);//滑块指针的初始位置设为500代表初始音量为50GetDlgItem(IDC_play)->EnableWindow(false);//文件没有读取时所有按钮应该是不可选的GetDlgItem(IDC_pause)->EnableWindow(false);GetDlgItem(IDC_stop)->EnableWindow(false);return TRUE; // return TRUE unless you set the focus to a control}void CMFCDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// If you add a minimize button to your dialog, you will need the code below// to draw the icon. For MFC applications using the document/view model,// this is automatically done for you by the framework.void CMFCDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{//CDialog::OnPaint();CPaintDC dc(this);CRect rect;GetClientRect(&rect);CDC dcMem;dcMem.CreateCompatibleDC(&dc);CBitmap bmpBackground;bmpBackground.LoadBitmap(IDB_BITMAP5);BITMAP bitmap;bmpBackground.GetBitmap(&bitmap);CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground);dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeig ht,SRCCOPY);}}// The system calls this to obtain the cursor to display while the user drags// the minimized window.HCURSOR CMFCDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CMFCDlg::Onabout(){CAboutDlg dlg;dlg.DoModal();}void CMFCDlg::Onexitbt(){CDialog::OnCancel();}void CMFCDlg::OnCustomdrawSlider(NMHDR* pNMHDR, LRESULT* pResult){UpdateData(true);m_int=m_slider.GetPos()/10;setvolume(m_slider.GetPos());UpdateData(false);*pResult = 0;}void CMFCDlg::Onfilechoice(){char szFileFilter[]="mp3文件(*.mp3)|*.mp3|""wma文件(*.wma)|*.wma|""wav文件(*.wav)|*.wav|""所有文件(*.*)|*.*|";CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY,szFileFilter);if(dlg.DoModal()==IDOK){CString strFilepath=dlg.GetPathName();CString strFilename=dlg.GetFileName();SetDlgItemText(IDC_filename,strFilename);Load(this->m_hWnd,strFilepath);GetDlgItem(IDC_play)->EnableWindow(true);//文件读取成功时所有按钮变可选的GetDlgItem(IDC_pause)->EnableWindow(true);GetDlgItem(IDC_stop)->EnableWindow(true);m_list.InsertString(m_list.GetCount(),strFilename);m_list.SetCurSel(m_list.GetCount()-1);}}void CMFCDlg::Onplay(){CString strfilename;int index=m_list.GetCurSel();CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);if(index==-1){MessageBox("请添加音乐");return;}m_list.GetText(index,strfilename);SetDlgItemText(IDC_filename,strfilename);stop();Load(this->m_hWnd,strfilename);play();SetTimer(0,1000,NULL);}void CMFCDlg::Onpause(){CString strtemp;GetDlgItemText(IDC_pause,strtemp);//获取按钮状态if(pare("暂停")==0){pause();SetDlgItemText(IDC_pause,"恢复");KillTimer(0);//取消计数器的显示}if(pare("恢复")==0){resume();SetTimer(0,1000,NULL);SetDlgItemText(IDC_pause,"暂停");}}void CMFCDlg::Onstop(){stop();SetDlgItemText(IDC_pause,"暂停");KillTimer(0);//取消计数器的显示CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);GetDlgItem(IDC_play)->EnableWindow(false);//当stop按钮按下时,播放和暂停应该均不可用GetDlgItem(IDC_pause)->EnableWindow(false);GetDlgItem(IDC_del)->EnableWindow(false);}void CMFCDlg::Onfileopen(){char filefiler[]="mp3文件(*.mp3)|*.mp3|""wma文件(*.wma)|*.wma|""wav文件(*.wav)|*.wav|";CFileDialogdlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT|OFN_ENABLESIZING,filefi ler);if (dlg.DoModal()==IDOK){CString strfilepath=dlg.GetPathName();CString strfilename=dlg.GetFileName();SetDlgItemText(IDC_filename,strfilename);CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观dc.SetTextColor(RGB(255,255,203));//设置数字显示的颜色mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);Load(this->m_hWnd,strfilepath);GetDlgItem(IDC_play)->EnableWindow(true);GetDlgItem(IDC_pause)->EnableWindow(true);GetDlgItem(IDC_stop)->EnableWindow(true);GetDlgItem(IDC_del)->EnableWindow(true);m_list.InsertString(m_list.GetCount(),strfilename);//获取文件名m_list.SetCurSel(m_list.GetCount()-1);}}void CMFCDlg::Ondel(){// TODO: Add your control notification handler code hereUpdateData(TRUE);int index=m_list.GetCurSel();stop();SetDlgItemText(IDC_filename,"");KillTimer(0);hour=0;minute=0;second=0;if(index!=CB_ERR){m_list.DeleteString(index);}}void CMFCDlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call defaultCString mtime;second++;CClientDC dc(this);dc.SetBkColor(RGB(124,252,0));dc.SetTextColor(RGB(255,255,203));if(second==60){minute++;second=0;}if(minute==60){hour++;minute=0;}mtime.Format("%02d:%02d:%02d",hour,minute,second);dc.TextOut(320,85,mtime);DWORD cdf=getinformation(MCI_STATUS_POSITION);DWORD cdfrom;cdfrom=MCI_MAKE_MSF(MCI_MSF_MINUTE(cdf),MCI_MSF_SECOND(cdf),MCI_MSF_FRA ME(cdf));UpdateData(false);CDialog::OnTimer(nIDEvent);}void CMFCDlg::OnDblclkList(){CString mtime;CClientDC dc(this);hour=0;minute=0;second=0;dc.SetBkColor(RGB(124,252,0));//设置放置计数器区域的外观dc.SetTextColor(RGB(255,255,203));//设置数字显示的颜色mtime.Format("%02d:%02d:%02d",hour,minute,second);//显示时间进度dc.TextOut(320,85,mtime);CString strfilename;int index=m_list.GetCurSel();m_list.GetText(index,strfilename);SetDlgItemText(IDC_filename,strfilename);stop();Load(this->m_hWnd,strfilename);play();SetTimer(0,1000,NULL);}void CMFCDlg::Onprevious(){int index;index=m_list.GetCurSel();index-=1;if(index<0){MessageBox("亲,没有上一首了哟~");return;}m_list.SetCurSel(index);Onplay();}void CMFCDlg::Onnext(){CString filename;CString temp;int index;index=m_list.GetCurSel();index+=1;if(index==m_list.GetCount()){MessageBox("已经是最后一首了,亲^.^");return;}m_list.SetCurSel(index);Onplay();}。