100个vc小项目开发:二、一步一点设计音乐播放器 [源码解读]
文章作者: July
软件来源:开源
==================
1.有不正之处,恳请指正。
2.本文贴出的是关键实现代码部分,只做粗略展示。
3.转载,请注明出处。谢谢。
---------
一、先画对话框,IDD_MYPLAYER_DIALOG,界面如图:
二、然后,对话框相关处理完成后,在CMyPlayerApp里头,编写如下代码:
设置几个全局变量:
CMyPlayerApp theApp;CStringArray m_strPlayListArray;int m_nPlayOrder[2000];int m_nNowPlaying;UINT m_nPlayMode;HWND hAudio;FILELIST fileList[10];int nCurrentList;CString strCurrentDir;
而后,编写InitInstance()的代码:
BOOL CMyPlayerApp::InitInstance(){ AfxEnableControlContainer(); m_hMutex=CreateMutex(NULL,FALSE,"星空物语");
if (GetLastError()==ERROR_ALREADY_EXISTS ) { HWND hwnd=FindWindow(NULL,"星空物语"); if(hwnd!=NULL);{ if(IsWindowVisible(hwnd)) return FALSE; SendMessage(hwnd,MYWM_NOTIFYICON,NULL,(LPARAM)WM_LBUTTONDOWN); } return FALSE ; }
hAudio=NULL; TCHAR szCurDir[MAX_PATH]; GetCurrentDirectory(MAX_PATH,szCurDir); strCurrentDir=szCurDir; m_nPlayMode=MODE_RAND;
CMyPlayerDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) {
} else if (nResponse == IDCANCEL) {
}
return FALSE;}
三、// MyPlayerDlg.h : header file 头文件里头:
class CMyPlayerDlg : public CDialog{// Constructionpublic: CString m_strLyricPath; void DeleteNotifyIcon(); void CreateNotifyIcon(); BOOL fPlay; void DestroyMenuDlg(); CMenuDlg* m_pMenuDlg; int m_nVolume; void WriteConfig(); BOOL ReadConfig(); BOOL IsFileExist(CString strFileName); BOOL GetFileList(CString strLine,int nIndex); void InitFileList(); int nRollTextCounter; void CirculatePlay(); void DropFilesInPlayList(HDROP hDrop); void DropFilesInMain(HDROP hDrop); BOOL IsSupportFile(CString strFileName); void GetDropFiles(HDROP hDrop); void FormatTitle(CString strFile); BOOL fPlaying; UINT m_nTime; void Play(int nIndex); CString GetFileTitle(CString strFileName); BOOL IsLyricDlgAttach(); BOOL IsPlayListAttach(); void MoveLyricWindow(); void MovePlayListWindow(); BOOL fInited; void CreateLyric(); CLyricDlg* m_pLyricDlg; void CreatePlayList(); CPlayListDlg* m_pPlayListDlg; void InitSize(); void ExitPlayer(); void MoveSlide(); void InitText(); void CountTime(); CString strTime; void InitRect(); CRect rectTitle; CRect rectTime; void DrawTime(CDC*pDC); void RollText(); CString strOutText; CString strTitle; void DrawText(CDC*pDC); void DrawMainPicture(CDC*pDC); void InitButtons(); CMyPlayerDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data //{{AFX_DATA(CMyPlayerDlg) enum { IDD = IDD_MYPLAYER_DIALOG }; CSkinButton m_btnShowMenu; CSkinButton m_btnLyric; CVolumeButton m_volume; CSlideButton m_slide; CTransparentStatic m_stcMode; CTransparentStatic m_stcPlay; CSkinButton m_btnStop; CSkinButton m_btnPrev; CSkinButton m_btnPLShow; CSkinButton m_btnPlay; CSkinButton m_btnOpen; CSkinButton m_btnNext; CSkinButton m_btnMin; CSkinButton m_btnHide; CSkinButton m_btnExit; CButton m_buttonOK; //}}AFX_DATA
// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMyPlayerDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); //}}AFX_VIRTUAL
// Implementationprotected: HICON m_hIcon;
// Generated message map functions //{{AFX_MSG(CMyPlayerDlg) virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnBtnExit(); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnStaticMode(); afx_msg void OnStaticPlay(); afx_msg void OnBtnVolume(); afx_msg void OnBtnSlide(); virtual void OnCancel(); virtual void OnOK(); afx_msg void OnBtnPlaylistShow(); afx_msg void OnMove(int x, int y); afx_msg void OnBtnLyric(); afx_msg void OnBtnOpen(); afx_msg void OnBtnNext(); afx_msg void OnBtnPlay(); afx_msg void OnBtnPrev(); afx_msg void OnBtnStop(); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); afx_msg void OnBtnShowmenu(); afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnMenuNext(); afx_msg void OnMenuOpen(); afx_msg void OnMenuPlay(); afx_msg void OnMenuPrev(); afx_msg void OnMenuRand(); afx_msg void OnMenuSeq(); afx_msg void OnMenuSingle(); afx_msg void OnMenuStop(); afx_msg void OnMenuVoldown(); afx_msg void OnMenuPause(); afx_msg void OnMenuVolslc(); afx_msg void OnMenuVolup(); afx_msg void OnAboutStar(); afx_msg void OnNotifyIcon(WPARAM wParam,LPARAM lParam); afx_msg void OnBtnHide(); afx_msg void OnBtnMin(); afx_msg void OnSetLyricpath(); afx_msg void OnMenuOpenLyricpath(); //}}AFX_MSG DECLARE_MESSAGE_MAP()};
四、对应的// MyPlayerDlg.cpp : implementation file 实现文件里头:
void CMyPlayerDlg::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMyPlayerDlg) DDX_Control(pDX, IDC_BTN_SHOWMENU, m_btnShowMenu); DDX_Control(pDX, IDC_BTN_LYRIC, m_btnLyric); DDX_Control(pDX, IDC_BTN_VOLUME, m_volume); DDX_Control(pDX, IDC_BTN_SLIDE, m_slide); DDX_Control(pDX, IDC_STATIC_MODE, m_stcMode); DDX_Control(pDX, IDC_STATIC_PLAY, m_stcPlay); DDX_Control(pDX, IDC_BTN_STOP, m_btnStop); DDX_Control(pDX, IDC_BTN_PREV, m_btnPrev); DDX_Control(pDX, IDC_BTN_PLAYLIST_SHOW, m_btnPLShow); DDX_Control(pDX, IDC_BTN_PLAY, m_btnPlay); DDX_Control(pDX, IDC_BTN_OPEN, m_btnOpen); DDX_Control(pDX, IDC_BTN_NEXT, m_btnNext); DDX_Control(pDX, IDC_BTN_MIN, m_btnMin); DDX_Control(pDX, IDC_BTN_HIDE, m_btnHide); DDX_Control(pDX, IDC_BTN_EXIT, m_btnExit); //}}AFX_DATA_MAP}
BEGIN_MESSAGE_MAP(CMyPlayerDlg, CDialog) //{{AFX_MSG_MAP(CMyPlayerDlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_LBUTTONDOWN() ON_BN_CLICKED(IDC_BTN_EXIT, OnBtnExit) ON_WM_CREATE() ON_WM_TIMER() ON_BN_CLICKED(IDC_STATIC_MODE, OnStaticMode) ON_BN_CLICKED(IDC_STATIC_PLAY, OnStaticPlay) ON_BN_CLICKED(IDC_BTN_VOLUME, OnBtnVolume) ON_BN_CLICKED(IDC_BTN_SLIDE, OnBtnSlide) ON_BN_CLICKED(IDC_BTN_PLAYLIST_SHOW, OnBtnPlaylistShow) ON_WM_MOVE() ON_BN_CLICKED(IDC_BTN_LYRIC, OnBtnLyric) ON_BN_CLICKED(IDC_BTN_OPEN, OnBtnOpen) ON_BN_CLICKED(IDC_BTN_NEXT, OnBtnNext) ON_BN_CLICKED(IDC_BTN_PLAY, OnBtnPlay) ON_BN_CLICKED(IDC_BTN_PREV, OnBtnPrev) ON_BN_CLICKED(IDC_BTN_STOP, OnBtnStop) ON_WM_RBUTTONDOWN() ON_BN_CLICKED(IDC_BTN_SHOWMENU, OnBtnShowmenu) ON_WM_KILLFOCUS() ON_COMMAND(IDC_MENU_NEXT, OnMenuNext) ON_COMMAND(IDC_MENU_OPEN, OnMenuOpen) ON_COMMAND(IDC_MENU_PLAY, OnMenuPlay) ON_COMMAND(IDC_MENU_PREV, OnMenuPrev) ON_COMMAND(IDC_MENU_RAND, OnMenuRand) ON_COMMAND(IDC_MENU_SEQ, OnMenuSeq) ON_COMMAND(IDC_MENU_SINGLE, OnMenuSingle) ON_COMMAND(IDC_MENU_STOP, OnMenuStop) ON_COMMAND(IDC_MENU_VOLDOWN, OnMenuVoldown) ON_COMMAND(IDC_MENU_PAUSE, OnMenuPause) ON_COMMAND(IDC_MENU_VOLSLC, OnMenuVolslc) ON_COMMAND(IDC_MENU_VOLUP, OnMenuVolup) ON_COMMAND(IDC_ABOUT_STAR, OnAboutStar) ON_MESSAGE(MYWM_NOTIFYICON,OnNotifyIcon) ON_BN_CLICKED(IDC_BTN_HIDE, OnBtnHide) ON_BN_CLICKED(IDC_BTN_MIN, OnBtnMin) ON_COMMAND(IDC_SET_LYRICPATH, OnSetLyricpath) ON_COMMAND(IDC_MENU_OPEN_LYRICPATH, OnMenuOpenLyricpath) //}}AFX_MSG_MAPEND_MESSAGE_MAP()
五、以下是MyPlayerDlg对话框的初始化代码:
BOOL CMyPlayerDlg::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 dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here InitButtons(); InitRect(); InitText(); InitSize(); CreateLyric(); CreatePlayList(); m_pMenuDlg=NULL; InitFileList();
strTitle=" 星空物语 "; strTime="00:00"; m_nTime=0; fInited=TRUE; fPlaying=FALSE; fPlay=TRUE; nRollTextCounter=0; SetWindowText("星空物语");
m_strLyricPath="";
if(ReadConfig()){ m_pPlayListDlg->OpenList(nCurrentList); m_volume.SetPos(m_nVolume); if(m_nPlayMode==MODE_SEQ) OnStaticMode(); if(m_nPlayMode==MODE_SINGLE){ OnStaticMode(); OnStaticMode(); } }else{ m_nPlayMode=MODE_RAND; nCurrentList=0; m_pPlayListDlg->OpenList(nCurrentList); m_nVolume=8; m_volume.SetPos(m_nVolume); }
CreateNotifyIcon(); SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); m_pLyricDlg->SetPlayListWnd(m_pPlayListDlg); return TRUE; // return TRUE unless you set the focus to a control}
//字幕的画法
void CMyPlayerDlg::DrawText(CDC *pDC){ pDC->SetBkMode(TRANSPARENT);
CFont font,*pOldFont; LOGFONT logFont; pDC->GetCurrentFont()->GetLogFont(&logFont);
logFont.lfCharSet=134; logFont.lfWidth=6; logFont.lfWeight=10; lstrcpy(logFont.lfFaceName,"华文彩云"); font.CreateFontIndirect(&logFont);
pOldFont=pDC->SelectObject(&font); pDC->SetTextColor(RGB(255,255,0)); pDC->TextOut(21,48,"Love You Forever");
font.DeleteObject();
logFont.lfWidth=6; logFont.lfHeight=12; logFont.lfWeight=0; lstrcpy(logFont.lfFaceName,"宋体"); font.CreateFontIndirect(&logFont); pDC->SelectObject(&font);
pDC->SetTextColor(RGB(0,255,0)); pDC->TextOut(22,35,strOutText); pDC->TextOut(22,66,"状态:"); pDC->TextOut(75,90,"☆For My Lover☆"); pDC->SetTextColor(RGB(0,150,0)); pDC->TextOut(60,103,"★星空物语 MADE BY July★");
font.DeleteObject(); pDC->SelectObject(pOldFont);}
六、计时器部分,OnTimer、RollText、CountTime、MoveSlide等4个函数:
int CMyPlayerDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here SetTimer(1,1000,NULL); fInited=FALSE;
DragAcceptFiles(TRUE); return 0;}
void CMyPlayerDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default RollText(); if(fPlaying){ CountTime(); MoveSlide(); CirculatePlay(); }
CDialog::OnTimer(nIDEvent);}
void CMyPlayerDlg::RollText(){ TCHAR ch; strOutText=""; for(UINT i=0;i<16;){ ch=strTitle.GetAt(nRollTextCounter+i); strOutText+=ch; i++; } nRollTextCounter+=2; if(nRollTextCounter>=strTitle.GetLength()-16) nRollTextCounter=0;
InvalidateRect(&rectTitle,TRUE);}
//计时
void CMyPlayerDlg::CountTime(){ m_nTime=MCIWndGetPosition(hAudio)/MCIWndGetSpeed(hAudio); int nMinute=m_nTime/60; int nSecond=m_nTime`; if(nMinute<10){ if(nSecond<10) strTime.Format("0%d:0%d",nMinute,nSecond); else strTime.Format("0%d:%d",nMinute,nSecond); }else{ if(nSecond<10) strTime.Format("%d:0%d",nMinute,nSecond); else strTime.Format("%d:%d",nMinute,nSecond); } InvalidateRect(&rectTime,TRUE);}
//滚动条设置
void CMyPlayerDlg::MoveSlide(){ if(hAudio!=NULL) m_slide.SetSlidePos(MCIWndGetPosition(hAudio)); }
七、关键的播放代码,Play
void CMyPlayerDlg::Play(int nIndex){ if(nIndex>=m_strPlayListArray.GetSize()) return; CString strFileName=m_strPlayListArray.GetAt(nIndex); if(!IsFileExist(strFileName)){ m_pPlayListDlg->m_playlist.DeleteString(nIndex); m_strPlayListArray.RemoveAt(nIndex,1); return; } if(hAudio!=NULL){ MCIWndDestroy(hAudio); hAudio=NULL; } try{ hAudio=MCIWndCreate(GetSafeHwnd(),AfxGetInstanceHandle(), WS_CHILD|MCIWNDF_NOMENU,strFileName); }catch(...) { if(nIndex>=0){ m_pPlayListDlg->m_playlist.DeleteString(nIndex); m_strPlayListArray.RemoveAt(nIndex,1); } return; } if(hAudio!=NULL){ MCIWndPlay(hAudio); if(!m_strLyricPath.IsEmpty()){ if(!m_pLyricDlg->OpenLyric(m_strLyricPath,nIndex)) m_pLyricDlg->OpenLyric(nIndex); }else m_pLyricDlg->OpenLyric(nIndex);
strTitle=GetFileTitle(strFileName); FormatTitle(strTitle); nRollTextCounter=0; m_nTime=0; fPlaying=TRUE; m_slide.SetRange(0,MCIWndGetLength(hAudio)); m_slide.SetSlidePos(0); m_pPlayListDlg->m_playlist.SetCurSel(nIndex);
int nSetVol=63*m_nVolume; if(nSetVol>1000) nSetVol=1000; MCIWndSetVolume(hAudio,nSetVol); }}
void CMyPlayerDlg::OnBtnPlay() { // TODO: Add your control notification handler code here int n=m_pPlayListDlg->m_playlist.GetCurSel(); if(n<0){ if(m_strPlayListArray.GetSize()>0){ Play(m_nPlayOrder[0]); m_nNowPlaying=0; } return; }
Play(n);
if(m_nPlayMode==MODE_RAND){ for(int i=0;i<m_strPlayListArray.GetSize();i++){ if(m_nPlayOrder[i]==n){ m_nNowPlaying=i; break; } } }else{ m_nNowPlaying=n; }}
八、打开文件
void CMyPlayerDlg::OnBtnOpen() { // TODO: Add your control notification handler code here CString strFilter="所有支持文件(*.mp3,*.wav,*.wma)|*.mp3;*.wav;*.wma||"; CFileDialog fdlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,strFilter); if(fdlg.DoModal()==IDOK){ CString strFileName=fdlg.GetPathName(); m_strPlayListArray.RemoveAll(); m_strPlayListArray.Add(strFileName); CString strList,strFile; strFile=GetFileTitle(strFileName); strList.Format("01 %s",strFile); m_pPlayListDlg->m_playlist.ResetContent(); m_pPlayListDlg->m_playlist.AddString(strList);
Play(0); }}
九、获取文件名
CString CMyPlayerDlg::GetFileTitle(CString strFileName){ CString str;
int nPos=-1; int nOldPos=-1; while((nPos=strFileName.Find("//",nPos+1))>0) nOldPos=nPos; str=strFileName.Right(strFileName.GetLength()-nOldPos-1); strFileName=str.Left(str.GetLength()-4); return strFileName;}
十、停止播放
void CMyPlayerDlg::OnBtnStop() { // TODO: Add your control notification handler code here if(hAudio!=NULL){ MCIWndStop(hAudio); m_nTime=0; fPlaying=FALSE; strTime="00:00"; m_slide.SetSlidePos(0); InvalidateRect(&rectTime,TRUE); }}
本文来自博客,转载请标明出处:http://blog.csdn.net/v_JULY_v/archive/2010/12/24/6095462.aspx