1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 23|VS 基于MFC 做一个音乐播放器 带音量调节 切换歌曲

23|VS 基于MFC 做一个音乐播放器 带音量调节 切换歌曲

时间:2023-01-30 01:22:41

相关推荐

23|VS 基于MFC 做一个音乐播放器 带音量调节 切换歌曲

最近接到个小任务,用MFC做一个音乐播放器,不过这也是一直想尝试的,于是今天早上9点到下午16:00,总算是完成了需要的功能

开门见山,先展示一下整体界面

下面按照功能模块介绍我做这个播放器的过程

预加载歌曲

我是在一个txt文件里面记录了我的本地音乐的路径,然后程序启动的时候就读取这个txt,根据路径去查找音乐

vector<CString>preLoadMusicPath;vector<CString>preLoadMusicName;CListBox listBox;//这个变量是在自己在listctrl控件上面绑定的

BOOL CMyMusicPlayerDlg::OnInitDialog(){CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。CString strFileName = _T("musicPath.txt");if (!PathFileExists(strFileName)){return FALSE;}CStdioFile file;if (!file.Open(strFileName, CFile::modeRead)){return FALSE;}CString temp;CString strValue = _T("");while (file.ReadString(strValue)){int pos = strValue.ReverseFind(_T('\\'));preLoadMusicPath.push_back(strValue);preLoadMusicName.push_back(strValue.Mid(pos+1, strValue.GetLength()));//preLoadBook.push_back(v1);}file.Close();for (int i = 0; i < preLoadMusicPath.size(); i++){listBox.AddString(preLoadMusicName[i]);}return TRUE; // 除非将焦点设置到控件,否则返回 TRUE}

下图就是预加载的结果,

添加歌曲

首先,先来做添加歌曲的部分

第一步自然需要点击按钮然后打开文件框选项选择音乐文件

#include "stdafx.h"#include "MyMusicPlayer.h"#include "MyMusicPlayerDlg.h"#include "afxdialogex.h"#include "mmsystem.h"HWND m_hWnd;//记录当前窗口的句柄 //DWORD DeviceID;//指定播放音乐的设备 MCI_OPEN_PARMS mciopenparms;//指定打开音乐文件的参数 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框CString fullPath;MCIDEVICEID m_IDdevice;

注意我包含了头文件"mmsystem.h"

void CMyMusicPlayerDlg::OnBnClickedButton1(){// TODO: 在此添加控件通知处理程序代码CString musicName;//CString fullPath;CString m_strLilePath;CFileDialog dlgFile(TRUE, NULL, NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT | OFN_EXPLORER,_T("All files|*.mp3;*.wma;*.wav|MP3 (*.MP3)|*.mp3|WMA (*.wma)|*.wma||"),NULL);if (dlgFile.DoModal() == IDOK){//CString img_select;fullPath = dlgFile.GetPathName();musicName = dlgFile.GetFileName();preLoadMusicPath.push_back(fullPath);int pos = fullPath.ReverseFind(_T('\\'));preLoadMusicName.push_back(fullPath.Mid(pos + 1, fullPath.GetLength()));listBox.AddString(musicName);//Load(this->m_hWnd, fullPath);SetDlgItemText(IDC_EDIT1, fullPath);//img_select为选择的文件的路径,IDC_IMGSELECTEDIT为edit控件名称mciSendCommand(m_IDdevice, MCI_CLOSE, 0, 0);//打开一首歌曲MCI_OPEN_PARMS mciOpenParms;mciOpenParms.lpstrElementName = fullPath;//MessageBox(0strFilePath);curPlayPos = preLoadMusicName.size() + 1;//当前的播放位置,播放第几首歌曲,这的意思就是播放刚添加的歌曲mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_WAIT, (DWORD)&mciOpenParms);m_IDdevice = mciOpenParms.wDeviceID;}}

这里会报错

这是因为mciSendCommand这个函数需要一个lib来链接,这个lib就是winmm.lib

所以我们还需要如下代码放在最前面

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

当然,你也可以找到这个lib文件,然后 ,在 项目->属性->VC++目录->库目录

我把winmm.lib放在下面的文件夹的,所以我在库目录包含了这个文件夹

之后我们需要在 链接器->输入->附加依赖项加上这个lib的名字

播放歌曲

void CMyMusicPlayerDlg::OnBnClickedButton2(){SetDlgItemText(IDC_EDIT2,preLoadMusicName[curPlayPos]);MCI_PLAY_PARMS mciPlayParms;mciPlayParms.dwCallback = NULL;mciPlayParms.dwFrom = 0;mciSendCommand(m_IDdevice, MCI_PLAY, MCI_FROM | MCI_NOTIFY, (DWORD)&mciPlayParms);}

暂停播放

void CMyMusicPlayerDlg::OnBnClickedButton3(){// TODO: 在此添加控件通知处理程序代码CString str;GetDlgItemText(IDC_BUTTON3, str);if (str == _T("暂停")){mciSendCommand(m_IDdevice, MCI_PAUSE, 0, 0);SetDlgItemText(IDC_BUTTON3, _T("继续"));}else {mciSendCommand(m_IDdevice, MCI_RESUME, 0, 0);SetDlgItemText(IDC_BUTTON3, _T("暂停"));}}

停止播放

void CMyMusicPlayerDlg::OnBnClickedButton4(){// TODO: 在此添加控件通知处理程序代码//SetDlgItemText(IDC_EDIT2, "");mciSendCommand(m_IDdevice, MCI_STOP, 0, 0);mciSendCommand(m_IDdevice, MCI_CLOSE, 0, 0);}

删除歌曲

大概思路就是先获取Listbox上光标的位置,然后去定位选择的需要删除的歌曲在preloadMusicName中的位置,去vector容器里面先把这首歌删了,然后重新写入listBox展示,最后退出软件时,也会把操作后的结果写入txt保存,以便重新打开软件时进行预加载

void CMyMusicPlayerDlg::OnBnClickedButton7(){// TODO: 在此添加控件通知处理程序代码curPlayPos = 0;int pos = listBox.GetCurSel();listBox.ResetContent();int count = 0;for (vector<CString>::iterator iter = preLoadMusicPath.begin(); iter != preLoadMusicPath.end(); iter++){if (count == pos){preLoadMusicPath.erase(iter);break;}count++;}int count2 = 0;for (vector<CString>::iterator iter = preLoadMusicName.begin(); iter != preLoadMusicName.end(); iter++){//std::cout << iter->a << iter->b << iter->c << std::endl;if (count2 == pos){preLoadMusicName.erase(iter);break;}count2++;}for (int i = 0; i < preLoadMusicName.size(); i++){listBox.AddString(preLoadMusicName[i]);}}

上一曲

void CMyMusicPlayerDlg::OnBnClickedButton5(){// TODO: 在此添加控件通知处理程序代码if (curPlayPos ==0){MessageBox(_T("已经到达第一首歌曲"));}if (curPlayPos > 0){curPlayPos = curPlayPos - 1;listBox.SetCurSel(curPlayPos);mciSendCommand(m_IDdevice, MCI_CLOSE, 0, 0);//打开一首歌曲MCI_OPEN_PARMS mciOpenParms;mciOpenParms.lpstrElementName = preLoadMusicPath[curPlayPos];//MessageBox(preLoadMusicPath[pos]);mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_WAIT, (DWORD)&mciOpenParms);m_IDdevice = mciOpenParms.wDeviceID;OnBnClickedButton2();//就是调用播放函数}}

下一曲

void CMyMusicPlayerDlg::OnBnClickedButton6(){// TODO: 在此添加控件通知处理程序代码if (curPlayPos == preLoadMusicName.size()-1){MessageBox(_T("已经到达最后一首歌曲"));}if (curPlayPos < preLoadMusicName.size() - 1){curPlayPos = curPlayPos + 1;listBox.SetCurSel(curPlayPos);mciSendCommand(m_IDdevice, MCI_CLOSE, 0, 0);//打开一首歌曲MCI_OPEN_PARMS mciOpenParms;mciOpenParms.lpstrElementName = preLoadMusicPath[curPlayPos];//MessageBox(preLoadMusicPath[pos]);mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_WAIT, (DWORD)&mciOpenParms);m_IDdevice = mciOpenParms.wDeviceID;OnBnClickedButton2();}}

音量调节

这一部分是耗我时间最久的了,主要参考别人的,别人的可以,放在我的程序上面就不行了

音量调节的思路是通过滑块调节系统声音

找到 类视图->属性

会生成下面的函数

void CMyMusicPlayerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar){UpdateData(TRUE);volume = slide.GetPos();CoInitialize(0);nVolume = SetVolum(volume);CoUninitialize();CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);UpdateData(FALSE);}

然后我们看看SetVolum函数的定义

#include <Digitalv.h>#include <mmdeviceapi.h> #include <endpointvolume.h>#include <audioclient.h>

bool SetVolum(int volume){HRESULT hr;IMMDeviceEnumerator* pDeviceEnumerator = 0;IMMDevice* pDevice = 0;IAudioEndpointVolume* pAudioEndpointVolume = 0;IAudioClient* pAudioClient = 0;try {hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pDeviceEnumerator);if (FAILED(hr)) throw "CoCreateInstance";hr = pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice);if (FAILED(hr)) throw "GetDefaultAudioEndpoint";hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioEndpointVolume);if (FAILED(hr)) throw "pDevice->Active";hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient);if (FAILED(hr)) throw "pDevice->Active";float fVolume;fVolume = volume / 100.0f;hr = pAudioEndpointVolume->SetMasterVolumeLevelScalar(fVolume, &GUID_NULL);if (FAILED(hr)) throw "SetMasterVolumeLevelScalar";pAudioClient->Release();pAudioEndpointVolume->Release();pDevice->Release();pDeviceEnumerator->Release();return true;}catch (...) {if (pAudioClient) pAudioClient->Release();if (pAudioEndpointVolume) pAudioEndpointVolume->Release();if (pDevice) pDevice->Release();if (pDeviceEnumerator) pDeviceEnumerator->Release();throw;}return false;}

同时我们需要在OnInitDialog()函数进行初始化

slide.SetRange(0, 100);//设置滑动范围为1到20slide.SetTicFreq(1);//每1个单位画一刻度CoInitialize(0);nVolume = GetVolume();CoUninitialize();slide.SetPos(nVolume);//设置滑块初始位置为1volume = nVolume;UpdateData(FALSE);

int GetVolume(){HRESULT hr;IMMDeviceEnumerator* pDeviceEnumerator = 0;IMMDevice* pDevice = 0;IAudioEndpointVolume* pAudioEndpointVolume = 0;IAudioClient* pAudioClient = 0;try {hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pDeviceEnumerator);if (FAILED(hr)) throw "CoCreateInstance";hr = pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice);if (FAILED(hr)) throw "GetDefaultAudioEndpoint";hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioEndpointVolume);if (FAILED(hr)) throw "pDevice->Active";hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient);if (FAILED(hr)) throw "pDevice->Active";float fVolume;hr = pAudioEndpointVolume->GetMasterVolumeLevelScalar(&fVolume);if (FAILED(hr)) throw "SetMasterVolumeLevelScalar";pAudioClient->Release();pAudioEndpointVolume->Release();pDevice->Release();pDeviceEnumerator->Release();int intVolume = fVolume * 100;if (fVolume > 100){fVolume = 100;}return intVolume;}catch (...) {if (pAudioClient) pAudioClient->Release();if (pAudioEndpointVolume) pAudioEndpointVolume->Release();if (pDevice) pDevice->Release();if (pDeviceEnumerator) pDeviceEnumerator->Release();throw;}}

退出软件时把最新结果写入txt文件

需要注意的是,由于txt中有中文,所以需要把项目的字符集改成多字节字符集

同时需要包含头文件

#include <locale>//为了使用setlocale(LC_CTYPE, "chs");便于输入中文到txt中

void CMyMusicPlayerDlg::OnBnClickedCancel(){// TODO: 在此添加控件通知处理程序代码CString filename = _T("musicPath.txt");CString strWriteData;//strWriteData.Format(_T("测试写入中文和Endlish¥\n"));CStdioFile csFile;CFileException cfException;if (csFile.Open(filename, CFile::typeText | CFile::modeCreate | CFile::modeReadWrite, &cfException))//以txt方式读取|若没有文件则创建该文件|文件打开时不清除{csFile.SeekToEnd();setlocale(LC_CTYPE, "chs");//为了能用csFile.WriteString(strWriteData)写入中文for (int i = 0; i < preLoadMusicPath.size(); i++){strWriteData = preLoadMusicPath[i]+_T("\n");csFile.WriteString(strWriteData);}}csFile.Close();CDialogEx::OnCancel();}

注意事项

这个播放器某些mp3音乐是不能播放的,我也不知道为什么,但是大部分还是可以播放的,比较抱歉的是代码不是很规范,比如控件的名字没改,导致生成的响应函数可读性比较差

好了,终于介绍完了,有很多细节是需要自己探索,百度的

附件

完整源代码及参考资料

/download/ningmengshuxiawo/19224419

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。