VC++ 繁星音乐播放器
繁星音乐播放器是本人第二次使用VC++编写的小应用。主要实现音乐的导入,删除和现实歌词,另外有一些特效
一、功能需求:
1.实现基本的音乐播放器的播放、暂停、继续、停止、上一首、下一首。
2.实现音乐播放器的音乐的快进、快退。
3.实现声音的增大和减小。
4.实现歌词的显示。
5.界面设计与美化。
二、总体设计
1.系统模块功能图
2.系统业务处理流程图
(1)、添加、删除、播放模式流程图
(2)、播放音乐流程图
三、程序详细设计
一、CPlayMusic类的编写
1、音乐播放器的播放、暂停、继续、停止、上一首、下一首
编写一个自定义类用来控制音乐的播放、暂停等功能实现。
类的定义:
class CPlayMusic
{
public:
CPlayMusic();
virtual ~CPlayMusic();
bool OpenFiles(); //打开CFileDialog,获取歌曲列表
CString Play(); //播放(打开设备并初始化)
void Pause(); //暂停
void Continue(); //继续
void Stop(); //停止
void Previous(); //上一首
void Next(); //下一首
voidSpeedForward(); //上一首
voidSpeedBackward(); //下一首
void OnTimer(); //循环播放
DWORD Getinfo(DWORDitem); //获取媒体文件信息(播放时间,已播放时间等)
DWORD m_count; //当前播放的媒体在列表中的位置
DWORDItemLength,ItemFrom,ItemTo,ItemNow; //播放总时间,起始时间,结束时间,当前已播放时间
DWORD SetVolumn(DWORDvol); //设置音量
bool GetLrc();
CString Lrc[100]; //歌词
CString MusicLrc; //当前歌词
int TotleLine; //歌词总行数
int iPlayed; //当前已播放的媒体文件数
bool PlayingFalg; //标志,是否正在播放
CStringstrFileName; //增加的文件路径
};
初始化参数:
iPlayed=0;
ItemFrom=0;
PlayingFalg=false;
MusicLrc="";
(1)、添加音乐的文件打开: bool OpenFiles();
//每次只能添加一首音乐
bool CPlayMusic::OpenFiles()
{
char szFileFilter[]="mp3文件(*.mp3)|*.mp3|"//设置文件播放格式
"wma文件(*.wma)|*.wma|"
"wav文件(*.wav)|*.wav|"
"所有文件(*.*)|*.*|";
CFileDialogfdlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,szFileFilter);
if(fdlg.DoModal()==IDOK)
{
strFileName=fdlg.GetPathName();
m_MusicList.Add(strFileName);
MusicNumber++;
iPlayed=MusicNumber-1;
Stop();
Play();
}
return TRUE;
}
(2)、播放音乐 CString Play()
CString CPlayMusic::Play()
{
PlayingFalg=TRUE; //置播放标志
MCI_OPEN_PARMSmciopenparms; //打开
MCI_PLAY_PARMSmciplayparms; //播放
mciopenparms.lpstrElementName=m_MusicList.GetAt(iPlayed); //播放路径
CurMusic=m_MusicList.GetAt(iPlayed);
//CurMusic 当前播放歌曲名, m_FileList[]保存所有的歌曲路径
int n=CurMusic.ReverseFind('\\');//得到歌曲名在字符中的位置
CurMusic=CurMusic.Mid(n+1); //只保存歌曲名
mciopenparms.lpstrDeviceType=NULL; //NULL为各种类型
mciSendCommand(0,MCI_OPEN,MCI_DEVTYPE_WAVEFORM_AUDIO,
(DWORD)(LPVOID)&mciopenparms); //向MCI设备发送命令消息
m_count=mciopenparms.wDeviceID;
mciplayparms.dwCallback=NULL; //窗口拥有者句柄
ItemLength=Getinfo(MCI_STATUS_LENGTH); //得到播放长度
ItemTo=MCI_MAKE_HMS(MCI_HMS_HOUR(ItemLength),
MCI_HMS_MINUTE(ItemLength),
MCI_HMS_SECOND(ItemLength)); //根据长度计算出时、分、秒
mciplayparms.dwFrom=MCI_MAKE_HMS(0,0,0); //播放起点
mciplayparms.dwTo=ItemTo; //播放终点
mciSendCommand(m_count,MCI_PLAY,MCI_TO|MCI_FROM,
(DWORD)(LPVOID)& mciplayparms);
IsPlaying=TRUE;//发送播放命令消息
returnm_FileList[iPlayed];
}
(3)、停止播放void Stop()
void CPlayMusic::Stop()
{
PlayingFalg=false; //关闭正在播放标志
ItemFrom=MCI_MAKE_HMS(0,0,0); //播放位置归文件开头
mciSendCommand(m_count,MCI_CLOSE,0,NULL); //发出关闭消息
}
(4)、暂停 void Pasue()
void CPlayMusic::Pause()
{
PlayingFalg=false;
mciSendCommand(m_count,MCI_PAUSE,0,NULL); //发送暂停命令消息
}
(5)、继续 void Continue()
void CPlayMusic::Continue()
{
PlayingFalg=true;
mciSendCommand(m_count,MCI_RESUME,0,NULL); //发送播放命令消息
}
(6)、上一首 void Previous()
void CPlayMusic::Previous()
{
iPlayed--;
if(iPlayed==-1) //若以后退到头,则指向最后一个,iPlayed是从0开始,iSelected从1开始
iPlayed=MusicNumber-1; //MusicNumber 为歌曲总数,是一个全局变量
Stop();
Play(); //播放
}
(7)、下一首 void Next();
void CPlayMusic::Next()
{
iPlayed++;
if(iPlayed>=MusicNumber)
iPlayed=iPlayed%MusicNumber;
Stop();
Play();
}
2、音乐快进,快退
(1)、void SpeedForward()
void CPlayMusic::SpeedForward()
{
MCI_PLAY_PARMSmciplayparms; //播放
ItemNow=Getinfo(MCI_STATUS_POSITION); //获取当前播放位置
if(ItemNow+ItemLength/15< ItemTo)
mciplayparms.dwFrom=ItemNow + ItemLength/15; //改变播放起点
else
mciplayparms.dwFrom=ItemTo;
mciplayparms.dwTo=ItemTo; //播放终点
mciSendCommand(m_count,MCI_PLAY,MCI_TO|MCI_FROM,(DWORD)(LPVOID)&mciplayparms); //发送播放消息
}
(2)、快退 void SpeedBackward()
void CPlayMusic::SpeedBackward()
{
MCI_PLAY_PARMSmciplayparms; //播放
ItemNow=Getinfo(MCI_STATUS_POSITION); //获取当前播放位置
longpos=ItemNow-ItemLength/15;
if(pos>(long)ItemFrom)
mciplayparms.dwFrom=pos; //改变播放起点
else
mciplayparms.dwFrom=ItemFrom;
mciplayparms.dwTo=ItemTo; //播放终点
mciSendCommand(m_count,MCI_PLAY,MCI_TO|MCI_FROM,(DWORD)(LPVOID)&mciplayparms); //发送播放消息
}
3、改变音量
在CPlayMusic.cpp中增加库
#include "Digitalv.h"//音量控制时会用到
DWORD CPlayMusic::SetVolumn(DWORD vol) //设置音量
{
MCI_DGV_SETAUDIO_PARMSSetVolumn;
SetVolumn.dwCallback=NULL;
SetVolumn.dwItem=MCI_DGV_SETAUDIO_VOLUME;
SetVolumn.dwValue=vol;
mciSendCommand(m_count,MCI_SETAUDIO,MCI_DGV_SETAUDIO_VALUE|MCI_DGV_SETAUDIO_ITEM,(DWORD)(LPVOID)&SetVolumn);
return 0;
}
4、得到歌词
bool CPlayMusic::GetLrc()
{
CFile file;
CStdioFile file1;
CString str;
str=m_FileList[iPlayed];
str.Replace("mp3","lrc");
int n=0;
int i=0;
int temp;
if(file1.Open(str,CFile::modeRead))
{
while(file1.ReadString(str))
{
n=str.Find(']',0);
temp=n;
while(str.Find(']',temp+1)!=-1)
temp=str.Find(']',temp+1);
if(temp!=-1)
n=temp;
str.Delete(0,n+1);
if(str!="")
{
Lrc[i]=str+"\r\n";
MusicLrc+=Lrc[i];
i++;
}
}
TotleLine=i;
return 1;
}
return 0;
}
整个CPlayMusic类编写基本完成。
二、音乐播放器的主要实现
1、为了使得对话框中的按钮控件好看,并有其他功能。重写CButton类
自定义MyButton类从Cbutton继承而来,增加功能有:用图片来替换按钮控件,鼠标移动在控件时自动改变控件的图片并显示按钮功能提示
(1)、实现鼠标移动到按钮处时改变按钮图片
添加变量
Public:
UINT m_nMouseOverID; //鼠标在按钮上之后按钮的图片ID
UINT m_nNormalID; //按钮之前的图片ID
CWnd* pWndParent;
HCURSOR m_hCursor;
BOOL m_bMouseOver; //判断鼠标是否在按钮上FALSE不在按钮上,TURE在按钮上
添加函数
Public:
void InitButtons(UINTnNormalID, UINT nMouseOverID,CString strTipText);//按钮初始化函数 三个参数(默认的按钮图片,鼠标经过时的图片,按钮功能提示语)
BOOL SetBitmap(UINT nNormalID,UINT nMouseOverID);
private:
void AdjustPosition();
void SetDefaultCursor();
另外添加DrawItem函数和WM_TIME、WM_SETCURSOR、WM_MOUSEMOVE消息响应函数
void CMyButton::InitButtons(UINT nNormalID, UINTnMouseOverID,CString strTipText)
{
m_nNormalID=nNormalID;
m_nMouseOverID=nMouseOverID;
m_hCursor=LoadCursor(NULL,MAKEINTRESOURCE(32649));
pWndParent=this->GetParent();
AdjustPosition();
m_bMouseOver=FALSE;
Invalidate();
}
void CMyButton::AdjustPosition()
{
CBitmap bitmap;
BITMAP m_Bitmap;
CRect rect;
bitmap.LoadBitmap(m_nNormalID);
bitmap.GetBitmap(&m_Bitmap);
GetWindowRect(&rect);//根据图象的大小调整按钮大小
pWndParent->ScreenToClient(&rect);
rect.right=rect.left+m_Bitmap.bmWidth;
rect.bottom=rect.top+m_Bitmap.bmHeight;
MoveWindow(&rect,TRUE);
}
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your codeto draw the specified item
UINT nID;
CDC*pDC;
pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
UINTnState=lpDrawItemStruct->itemState;
if(m_bMouseOver&&(!(nState & ODS_SELECTED)))
nID=m_nMouseOverID;
else
nID=m_nNormalID;
CBitmap bitmap;
BITMAP m_Bitmap;
CDC MemDC;
bitmap.LoadBitmap(nID);
MemDC.CreateCompatibleDC(pDC);
MemDC.SelectObject(&bitmap);
bitmap.GetBitmap(&m_Bitmap);
pDC->BitBlt(0,0,m_Bitmap.bmWidth,m_Bitmap.bmHeight,&MemDC,0,0,SRCCOPY);
bitmap.DeleteObject();
MemDC.DeleteDC();
}
BOOL CMyButton::SetBitmap(UINT nNormalID, UINT nMouseOverID)
{
m_nNormalID=nNormalID;
m_nMouseOverID=nMouseOverID;
AdjustPosition();
Invalidate();
return TRUE;
}
void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add yourmessage handler code here and/or call default
m_bMouseOver=TRUE;
SetTimer(1,100,NULL);
Invalidate();
CButton::OnMouseMove(nFlags,point);
}
void CMyButton::OnTimer(UINT nIDEvent)
{
// TODO: Add yourmessage handler code here and/or call default
if (nIDEvent==1)
{
POINT point;
GetCursorPos(&point);
ScreenToClient(&point);
CRect rect;
GetClientRect(&rect);
if(!rect.PtInRect(point)){
KillTimer(1);
m_bMouseOver=FALSE;
Invalidate();
}
}
CButton::OnTimer(nIDEvent);
}
BOOL CMyButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)//更换光标
{
// TODO: Add yourmessage handler code here and/or call default
if (m_hCursor) //如果设置了光标,就使用新设置的光标
{
::SetCursor(m_hCursor);
return TRUE;
}
returnCButton::OnSetCursor(pWnd, nHitTest, message);
}
(2)、添加按钮功能提示
自定义 BOOLSetBitmap(UINT nNormalID,UINT nMouseOverID);
CToolTipCtrl m_ToolTip;//提示按钮作用
添加系统函数:PreTranslateMessage(MSG*pMsg);和PreSubclassWindow()函数
在按钮初始化自定义函数InitButtons(UINTnNormalID, UINT nMouseOverID,CString strTipText)中添加代码:
m_ToolTip.UpdateTipText(strTipText,this,TIP_ID);//#define TIP_ID 1
为PreSubclassWindow()添加代码
void CMyButton::PreSubclassWindow()
{
// TODO: Add yourspecialized code here and/or call the base class
CRect rect;
GetClientRect(&rect);
m_ToolTip.Create(this);
m_ToolTip.SetDelayTime(100);
m_ToolTip.SetMaxTipWidth(200);
m_ToolTip.AddTool(this,"",rect,TIP_ID);
CButton::PreSubclassWindow();
}
为PreTranslateMessage()添加代码
BOOL CMyButton::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add yourspecialized code here and/or call the base class
m_ToolTip.RelayEvent(pMsg);
returnCButton::PreTranslateMessage(pMsg);
}
以上CMyButton已基本完成
2、音乐播放器的真正实现部分
(1)、设计主对话框(在主对话框中主要有停止、上一首、播放(暂停,继续)、下一首, 窗口最小化、关闭、音乐播放器的设置、添加音乐、删除、播放模式)等按钮控件
另外这里还应用的改变对话框大小技术
动态改变对话大小
自定义函数::ChangeDlgSize()
void CMusicDlg::ChangeDlgSize()
{
CRect rect;
CString str;
if(pSize)
{
str = "";
rect = pFull;
}
else
{
str = "";
rect = pHalf;
CRect dlgRect;
GetWindowRect(dlgRect);
CRect desktopRect;
}
SetWindowPos(NULL,0,0,rect.Width(), rect.Height(), SWP_NOMOVE);//显示对话框
m_btnMenuList.SetWindowText(str);//设置按钮文本
pSize = !pSize;
}
在对话框初始化函数增加代码
GetWindowRect(&pFull);
pHalf = pFull;
//确定小尺寸对话框范围
CRect rect;
m_btnMenuList.GetWindowRect(&rect);//m_btnMenuList为添加控件的成员变量
pHalf.bottom =rect.bottom +5; //显示的对话框高度到按钮下方+5的距离处
pSize = false;//初始设置为小对话框
//调用改变尺寸函数
ChangeDlgSize();
初始化的对话框大小如图:
当点击歌曲,即变量成员是m_btnMenuList的控件,消息响应函数为:
void CMusicDlg::OnMenulist()
{
//TODO: Add your control notification handler code here
ChangeDlgSize();
}
对话框大小有如图:
重复点击会变小变大。
(2)、按钮控件的初始化;
为各个按钮控件添加相应的控件变量
修改控件的定义将CButton改为CMyButton;
设置按钮控件的位置
CRect rect1;
rect1.right=1000; //按钮后边最大距离
rect1.bottom=1000;//按钮底边最大距离
rect1.left=215;
rect1.top=128;
m_btnMenuList.MoveWindow(&rect1,TRUE);
m_btnMenuList.InitButtons(IDB_MENU2,IDB_MENU,"歌曲列表"); //默认位图,鼠标经过时的位图,控件作用提示
//
rect1.left=240;
rect1.top=4;
m_btnClose.MoveWindow(&rect1,TRUE);
m_btnClose.InitButtons(IDB_CLOSE2,IDB_CLOSE,"关闭");
//
rect1.left=220;
rect1.top=4;
m_btnHide.InitButtons(IDB_HIDE2,IDB_HIDE,"");
//
rect1.left=80;
rect1.top=130;
m_btnNext.InitButtons(IDB_NEXT2,IDB_NEXT,"下一首");
//
rect1.left=53;
rect1.top=130;
m_btnPlay.MoveWindow(&rect1,TRUE);
m_btnPlay.InitButtons(IDB_PLAY2,IDB_PLAY,"播放");
//
rect1.left=28;
rect1.top=130;
m_btnPrev.InitButtons(IDB_PREV2,IDB_PREV,"上一首");
//
rect1.left=200;
rect1.top=4;
m_btnSet.InitButtons(IDB_SET2,IDB_SET,"设置");
//
rect1.left=5;
rect1.top=130;
m_btnStop.InitButtons(IDB_STOP2,IDB_STOP,"停止");
//增加
rect1.left=5;
rect1.top=477;
m_btnAdd.InitButtons(IDB_ADD2,IDB_ADD,"");
//删除
rect1.left=110;
rect1.top=480;
m_btnDel.InitButtons(IDB_DELETE2,IDB_DELETE,"");
// 播放模式
rect1.left=190;
rect1.top=480;
m_btnPlayMode.InitButtons(IDB_SHUNXU2,IDB_SHUNXU,"");
(3)、Silder properties控件初始化(音乐播放进度,音量控制)
A、声音控件
m_btnVolume.SetRange(0,1000);//滑块的移动范围
m_btnVolume.SetPos(500);//滑块中点
B、音乐播放进度
m_btnProgress.SetRange(0,100,TRUE);
m_btnProgress.SetTic(0);
m_btnProgress.SetTicFreq(10);
SetTimer(3,1000,NULL); //播放进度条设置定时器
(4)、控件消息响应函数:
A、停止控件stop
voidCMusicDlg::OnStop()
{
//TODO: Add your control notification handler code here
IsPlaying= FALSE;
PlayMusic.Stop();//停止播放音乐
m_btnProgress.SetPos(0); //设置进度条位置为0
CRectrect1;
rect1.right=1000;
rect1.bottom=1000;
rect1.left=53;
rect1.top=129;
m_btnPlay.MoveWindow(&rect1,TRUE);
m_btnPlay.InitButtons(IDB_PLAY2,IDB_PLAY,""); //控件更改图片
IsPause=FALSE;
CurMusic="繁星音乐播放器 欢迎您"; //CurMusic用来在对话框中显示当前播放歌曲名;当无歌曲播放时显示“繁星音乐播放器 欢迎您”
}
B、播放控件(暂停,继续)
voidCMusicDlg::OnPlay()
{
//TODO: Add your control notification handler code here
CRectrect1;
rect1.right=1000;
rect1.bottom=1000;
rect1.left=53;
rect1.top=129;
m_btnPlay.MoveWindow(&rect1,TRUE);
if(MusicNumber==0) //当无歌曲则返回
return ;
else{
if (IsPlaying) //有歌曲正在播放点击按钮之后则暂停
{
IsPlaying=FALSE;
m_btnPlay.InitButtons(IDB_PLAY2,IDB_PLAY,"继续"); //这时控件的提示语应为继续
PlayMusic.Pause(); //暂停歌曲
MusicLrcDlg->KillTimer(1);
IsPause=TRUE;
}
else{ //如果没有播放则播放
IsPlaying=TRUE;
m_btnPlay.InitButtons(IDB_PASUE2,IDB_PASUE,"暂停");
if(IsPause) //如果没有播放是暂停的
{PlayMusic.Continue();则继续播放
MusicLrcDlg->SetTimer(1,5000,NULL);
IsPause=FALSE;
}
Else //如果没有播放并不是暂停的,则播放一首新的歌曲
{
PlayMusic.Play();
ShowMusicLrc(); //显示歌词
}
}
}
Invalidate();
}
C、上一首
voidCMusicDlg::OnPrev()
{
//TODO: Add your control notification handler code here
if(IsPlaying)
{ PlayMusic.Previous();
ShowMusicLrc();
}
UpdateData(FALSE);
}
D、下一首
voidCMusicDlg::OnNext()
{
//TODO: Add your control notification handler code here
if(IsPlaying)
{ PlayMusic.Next();
ShowMusicLrc();
}
UpdateData(FALSE);
}
E、改变音量控件(通过ClassVizard 添加声音控件的NM_CUSTOMDRAW消息响应函数)
voidCMusicDlg::OnCustomdrawVolum(NMHDR* pNMHDR, LRESULT* pResult)
{
//TODO: Add your control notification handler code here
UpdateData(true);//更新数据
PlayMusic.SetVolumn(m_btnVolume.GetPos());//当前滑块位置
UpdateData(FALSE);
*pResult= 0;
}
F、播放进度控件(通过ClassVizard 添加WM_HSCROLL消息响应函数)
voidCMusicDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//TODO: Add your message handler code here and/or call default
if(IsPlaying)
{
int percent =m_btnProgress.GetPos(); //获取进度条比例
int ratio =m_ItemPosition*100/m_ItemLength; //计算已播放的比例
while(percent>ratio) //若滑块超前,则快进,直到播放比例与进度条指示相同
{
PlayMusic.SpeedForward();
ratio=PlayMusic.Getinfo(MCI_STATUS_POSITION)*100/PlayMusic.Getinfo(MCI_STATUS_LENGTH); //得到曲目长度
};
while(percent<ratio)
{
PlayMusic.SpeedBackward(); //若滑块滞后,则快进,直到播放比例与进度条指示相同
ratio=PlayMusic.Getinfo(MCI_STATUS_POSITION)*100/PlayMusic.Getinfo(MCI_STATUS_LENGTH); //得到曲目长度 DWORD w1 = m_Media.Getinfo(MCI_STATUS_LENGTH); //得到曲目长度
};
}
CDialog::OnHScroll(nSBCode,nPos, pScrollBar);
}
另外在OnTimer函数中添加:
if(nIDEvent==3)
{
if(IsPlaying)
{
m_ItemLength = PlayMusic.Getinfo(MCI_STATUS_LENGTH); //得到曲目长度 DWORD w1 = m_Media.Getinfo(MCI_STATUS_LENGTH); //得到曲目长度
m_ItemPosition= PlayMusic.Getinfo(MCI_STATUS_POSITION); //得到曲目长度 DWORDw1 = m_Media.Getinfo(MCI_STATUS_LENGTH); //得到曲目长度
intpercent = m_ItemPosition*100 / m_ItemLength; //计算播放比例
m_btnProgress.SetPos(percent); //更新进度条位置
PlayMusic.OnTimer();
}
Invalidate(FALSE);
UpdateData(FALSE);
}
G、添加音乐控件消息响应函数(添加控件原本相有个添加文件和添加文件夹两种方式,这里由于添加音乐文件夹方式没有学会,这里只有添加文件)添加控件要有两种添加方式则需要新建个Menu
添加控件的消息响应函数:
void CMusicDlg::OnAdd()
{
//TODO: Add your control notification handler code here
//与Menu连接使用
CRectrect;
GetDlgItem(IDC_ADD)->GetWindowRect(&rect);//控件ID
CMenum_Menu;
m_Menu.LoadMenu(IDR_MENU_ADD); //载入Menu,MenuID
m_Menu.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTBUTTON,
rect.left, rect.bottom,this,NULL);
}
添加文件消息响应函数:
voidCMusicDlg::OnAddFile()
{
//TODO: Add your command handler code here
Invalidate(FALSE);
PlayMusic.OpenFiles(); //打开增加文件对话框并将选择歌曲目录保存
CRectrect1;
rect1.right=1000;
rect1.bottom=1000;
rect1.left=53;
rect1.top=129;
m_btnPlay.MoveWindow(&rect1,TRUE);
m_btnPlay.InitButtons(IDB_PASUE2,IDB_PASUE,"");
UpdateData(FALSE);
intn;
//截取歌曲目录文件之后的音乐文件名
CStringstrFormat;
CString str =m_MusicList.GetAt(MusicNumber-1); n=str.ReverseFind('\\'); str=str.Mid(n+1);
//将音乐文件名添加在list box控件中
if(MusicNumber<10)
strFormat.Format("0%d %s",MusicNumber,str);
else
strFormat.Format("%d %s",MusicNumber,str);
m_menulist.AddString(strFormat); //m_menulist为list box的相关变量
if(MusicNumber!=0)
IsPlaying = TRUE;
m_menulist.SetCurSel(PlayMusic.iPlayed);//选中最后增加的歌曲
ShowMusicLrc();
UpdateData(FALSE);
}
H、删除控件
删除选中音乐
void CMusicDlg::OnDelSelect()
{
//TODO: Add your command handler code here
intn=m_menulist.GetCurSel();//得到list box中选中的歌曲
if(n<0)
return;
m_MusicList.RemoveAt(n,1);//m_MusicList是CStringArray类型的变量用来保存所有添加的歌曲,RemoveAt删除指定位置的歌曲
MusicNumber--; //歌曲数减一
CStringstrGet;
CStringstrFileTitle;
CStringstrFormat;
intnPos;
for(inti=n;i<m_menulist.GetCount()-1;i++){
m_menulist.GetText(i+1,strGet);
nPos=strGet.Find(" ",0);
strFileTitle=strGet.Right(strGet.GetLength()-nPos);
if(i+1<10)
strFormat.Format("0%d%s",i+1,strFileTitle);
else
strFormat.Format("%d%s",i+1,strFileTitle);
m_menulist.InsertString(i,strFormat);
m_menulist.DeleteString(i+1);
}
m_menulist.DeleteString(i);//播放列表中同样删除选中歌曲
}
删除所有歌曲
void CMusicDlg::OnDelAll()
{
// TODO: Add yourcommand handler code here
MusicNumber=0;
m_MusicList.RemoveAll();
m_menulist.ResetContent();
}
I、List box控件消息响应(鼠标双击选中歌曲,让其播放)为list box 控件添加LBN_DBLCLK消息响应函数
voidCMusicDlg::OnDblclkMusiclist() //双击list box中选择的一行 消息响应函数
{
// TODO: Add yourcontrol notification handler code here
intn=m_menulist.GetCurSel(); //得到鼠标点击处为行数
PlayMusic.Stop();
PlayMusic.iPlayed=n;
PlayMusic.Play();
m_btnProgress.SetPos(0); //重新设置播放进度调的位置
SetTimer(3,1000,NULL); //播放进度 设置定时器
ShowMusicLrc(); //显示歌词
UpdateData(FALSE);
}
3、为了使得音乐播发器更加完美,下面添加一些额外的代码
(1)、因为音乐播放器去掉了原本对话框中的Title bar导致对话框不能够拖到
这里使用鼠标左键按下拖动对话框,添加WM_LBUTTONDOWN消息响应函数
在鼠标左键按下中添加代码:
PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));//允许点击任意处拖动
(2)、设置对话框透明
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
HINSTANCE hInst = LoadLibrary("User32.DLL");
if(hInst)
{
typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNC fun = NULL;
//取得SetLayeredWindowAttributes函数指针
fun=(MYFUNC)GetProcAddress(hInst,"SetLayeredWindowAttributes");
if(fun)fun(this->GetSafeHwnd(),0,100,2); //更改100可改变对话框透明效果 数字越小,透明度越大。
FreeLibrary(hInst);
}
注:该方法不足,设置对话框的透明度同时,对话框中的字同样透明(变暗)。
(3)、由于本程序添加list box导致lisx box处的背景没有对话框的图片背景。解决方法
添加消息响应函数:WM_CTLCOLOR消息响应函数
添加代码:
HBRUSH hbrush= (HBRUSH)::GetStockObject(NULL_BRUSH);
pDC->SetTextColor(RGB(255,255,255));//设置字体颜色
pDC->SetBkMode(TRANSPARENT);
更改返回值为 return hbrush;
(4)、为了在对话框中显示当前播放歌曲名,不借助任何控件,即在对话框上写字
添加WM_PAINT消息响应函数;
CFont font;
LOGFONT logFont;
dc.GetCurrentFont()->GetLogFont(&logFont);
logFont.lfCharSet=134;
logFont.lfWidth=8;
logFont.lfHeight=18;
logFont.lfWeight=1000;
lstrcpy(logFont.lfFaceName,"楷体");
font.CreateFontIndirect(&logFont);
dc.SelectObject(&font);
dc.SetTextColor(RGB(119,190,232));//设置文本颜色
dc.SetBkMode(TRANSPARENT);//设置透明背景
dc.TextOut(WidthX,40,CurMusic);//字幕初始位置
四、程序测试与实现
1、添加音乐
添加后并自动播放:
2、删除选中音乐
3、迷你模式
4、透明对话框
五、程序优缺点、个人心得
优点:已经基本上实现了音乐播放器的基本功能,另外增加了透明对话框,迷你模式,显示播放时间,音量控制,快进,快退。显示歌曲名。
缺点:删除功能还不够理想,播放模式也没有怎么真正实现,播放时间不够精确,显示歌词方面还有待于实现。声音控件和播放进度控件可视化效果不够好。
增加文件夹没有实现,程序中设有的全局变量有点多。
个人心得:通过音乐播放器程序的编写,最初的问题时对MFC中的控件使用不够清楚导致重写了好几回,学会了如何重写一个类。在编写音乐播放器时参考了不少资料,总感觉编写有点乱。如何更改静态文本框的字体和颜色。两个或多个类之间的相会调用。还没有真正的弄懂MCI;
参考文献:
1、MSDN VC++ 6.0
2、深入浅出MFC第二版侯杰 华中科技大学出版社
3、Visual C++从入门到实践葛亮 清华大学出版社
4、Visual C++程序开发案例分析 杨国富 清华大学出版社
源代码: http://download.csdn.net/detail/fangxin205/7287719
VC++ 繁星音乐播放器相关推荐
- 100个vc小项目开发:二、一步一点设计音乐播放器 [I]
100个vc小项目开发:二.一步一点设计音乐播放器 [源码解读] 文章作者: July 软件来源:开源 ================== 1.有不正之处,恳请指正. 2.本文贴出的是关键实现代码部 ...
- 【180609】超酷界面的VC++音乐播放器
超酷界面的VC++音乐播放器,推荐给大家,源码爱好者在VC++6.0下顺利编译,它的界面非常 酷,编译中也没有发现用到第三方的界面控件,而且播放器的窗口还具有像千千静听一样的自动吸附功能,也就是拖动窗 ...
- 【190302】VC 仿千千静听音乐播放器源码源代码
源码下载简介 超酷界面的VC++音乐播放器,推荐给大家, 在VC++6.0下顺利编译,它的界面非常 酷,编译中也没有发现用到第三方的界面控件,而且播放器的窗口还具有像千千静听一样的自动吸附功能,也就是 ...
- 一个VC写的音乐播放器
以前,一直想写一个音乐播放器,但VC还没有完全学完,有些东西还练的很少,实力还不够,这是学完VC后,练习了很多东西,看了不少VC的知识,所以才决定写的. 这是2013年3月份写的,当时没有写在博客中, ...
- 单片AT89C2051 + SD卡 + 3310LCD = 音乐播放器
http://www.amobbs.com/thread-4503884-1-1.html 这个小玩意,采用 ATMEL 的传统51MCU作主控制芯片,加上SD卡和显示屏,就可以作简单的音乐播放器了, ...
- C/C++简单音乐播放器系统
C/C++简单音乐播放器系统 程序设计题 1:简单音乐播放器系统 出题人:吴敏 面向专业:计算机科学与技术 难度等级:4 1 问题描述 编写一个简单音乐播放器软件,实现歌单文件的浏览,点歌,加入收藏夹 ...
- SE Springer小组之《Spring音乐播放器》可行性研究报告一、二(转载)
此文转载自组员小明处~~ 1 引言 1.1编写目的 <软件工程>课程,我们团队计划开发一个音乐播放器.本文档是基于网络上现有的音乐播放器的特点,团队计划实现的音乐播放器功能和团 ...
- 仿酷狗音乐播放器开发日志二十四 选项设置窗体的实现(附328行xml布局源码)
转载请说明原出处,谢谢~~ 花了两天时间把仿酷狗的选项设置窗体做出来了,当然了只是做了外观.现在开学了,写代码的时间减少,所以整个仿酷狗的工程开发速度减慢了.今天把仿酷狗的选项设置窗体的布局代码分享出 ...
- 仿酷狗音乐播放器开发日志二十四 选项设置窗体的实现(附328行xml布局源码)...
转载请说明原出处,谢谢~~ 花了两天时间把仿酷狗的选项设置窗体做出来了,当然了只是做了外观.现在开学了,写代码的时间减少,所以整个仿酷狗的工程开发速度减慢了.今天把仿酷狗的选项设置窗体的布局代码分享出 ...
最新文章
- 参加第一届宇宙 JavaScript 大会是怎样的体验
- 汇智清华,医道生机 | 第四届清华校友三创大赛医疗健康行业论坛圆满召开
- js如何通过变量调用函数,函数名在变量里面
- windows下安装virtual box(ubuntu)
- Linux常用命令总结之(五)alias
- HDU2159(完全背包)
- 多伦多大学密西莎加计算机科学,解析加国名校多伦多大学密西沙加校区
- jQuery(九):节点遍历
- 数据挖掘肿瘤预测_给你一个基因,利用数据挖掘能做什么?
- 【色空win7动漫美女诱惑主题】
- FTP、FTPS 与 SFTP 简介
- html中qq号码怎么写,根据QQ头像hash分析QQ号(html版)
- 小游戏正在毁灭微信群聊(文中有福利)
- 傻孩子菜单框架(转)
- 计算机网络实验报告哈工大_哈工大计算机网络实验报告之二
- 哈工大计算机考研复试指南
- 腾讯滑块JS破解/本地识别DLL
- 一周疫情对行业影响观察 | 对香港IPO冲击大于内地,纺织服装新增企业同比下滑超五成...
- xingtai - 学习九九乘法表和皇帝的米粒
- gcc/g++ 编译C/C++代码