转载

    技术2022-05-19  26

    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


    最新回复(0)