MFC学习笔记之简单MP3播放器的设计

来源:互联网 发布:阿里云退款 编辑:程序博客网 时间:2024/05/22 00:37

         首先对MCI(Media Control Interface)媒体控制接口作简单介绍,MCI是微软公司提供的一组多媒体设备和文件的标准接口,其优点是可以方便地控制绝大所数多媒体设备,包括音频、视频、影碟、录像等多媒体设备,而不需要知道它们的内部工作状况。接口所支持的媒体格式包括avi、wav、mpeg、Mp3、wma等。这里要做的就是通过公开的访问接口直接调用系统内置引擎实现MP3的播放。

        接口函数的声明如下:

        MCIERROR WINAPI mciSendCommand(MCIDEVICEID mciId,

UINT uMsg,

DWORD dwParam1,

DWORD dwParam2)

其中mciId指定了设备标识,这个标识会在程序员打开MCI设备时由系统提供。uMsg指定将如何控制设备,即MCI指令,最后两个参数一般是一个数据结构,标识程序在访问MCI时要的信息。MCI常用指令有MCI_OPEN、MCI_PAUSE、MCI_CLOSE、MCI_STOP、MCI_PLAY、MCI_STATUS等。

        制作流程如下:

        1.在对话框上分别添加一个滑动条和四个按钮,如图所示:

播放进度、播放、暂停、停止、打开文件的ID号分别设置为IDC_PROCESS、IDC_PLAY_BUTTON、IDC_PAUSE_BUTTON、IDC_STOP_BUTTON、IDC_OPEN_BUTTON。

2.新建一个CMyPlayerControl类,其头文件和实现如下:

CMyPlayerControl.h:

<span style="font-size:18px;">#pragma once#ifndef _MY_PLAYER_CONTROL_H_#define _MY_PLAYER_CONTROL_H_//插入多媒体头文件#include<mmsystem.h>class CMyPlayerControl{public:CMyPlayerControl(void);~CMyPlayerControl(void);public:BOOL Open(LPCWSTR lpFileName);//打开文件void Play();//播放void Close();//关闭void Stop();//停止void Pause();//暂停DWORD GetLength(DWORD dwItem);//获取歌曲长度void SetWindowHwnd(HWND hWnd);//设置主窗口句柄private:MCI_OPEN_PARMS mciOpen;//打开设备参数HWND m_hWnd;//主窗口句柄DWORD dwFrom;//播放起始点};#endif</span>

CMyPlayerControl.cpp:因为类中调用了系统的MCI接口的API函数,所以必须加入winmm.lib这个静态链接库文件。

#include "StdAfx.h"#include "MyPlayerControl.h"CMyPlayerControl::CMyPlayerControl(void){}CMyPlayerControl::~CMyPlayerControl(void){Close();}DWORD CMyPlayerControl::GetLength(DWORD dwItem){//得到当前文件状态MCI_STATUS_PARMS mcistatusparms;mcistatusparms.dwCallback=(DWORD)m_hWnd;mcistatusparms.dwItem=dwItem;mcistatusparms.dwReturn=0;mciSendCommand(mciOpen.wDeviceID,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)&mcistatusparms);return mcistatusparms.dwReturn;}BOOL CMyPlayerControl::Open(LPCWSTR lpFileName){//如果有打开的MCI设备就关闭if(mciOpen.wDeviceID)Close();//初始化MCI_OPEN_PARMS结构中的文件类型mciOpen.lpstrDeviceType=NULL;//播放文件路径mciOpen.lpstrElementName=lpFileName;//向MCI设备发送命令消息(在打开设备时,设备号为0)if(mciSendCommand(0,MCI_OPEN,MCI_DEVTYPE_WAVEFORM_AUDIO,(DWORD)&mciOpen)){return FALSE;}dwFrom=MCI_MAKE_HMS(0,0,0);return TRUE;}void CMyPlayerControl::Play(){//播放参数结构MCI_PLAY_PARMS mciplayparms;//得到文件大小DWORD cdlen=GetLength(MCI_STATUS_LENGTH);DWORD cdto=MCI_MAKE_HMS(MCI_HMS_HOUR(cdlen),MCI_HMS_MINUTE(cdlen),MCI_HMS_SECOND(cdlen));//把文件中读出的大小转换为时间数量mciplayparms.dwCallback=NULL;mciplayparms.dwFrom=dwFrom;//设置起始位置mciplayparms.dwTo=cdto;//设置终止位置if(mciOpen.wDeviceID!=0)//判断是否打开文件{//播放音乐mciSendCommand(mciOpen.wDeviceID,MCI_PLAY,MCI_TO|MCI_FROM,(DWORD)(LPVOID)&mciplayparms);}}void CMyPlayerControl::Close(){if(mciOpen.wDeviceID){//执行MCI_CLOSE操作,关闭MCI设备mciSendCommand(mciOpen.wDeviceID,MCI_CLOSE,NULL,NULL);}}void CMyPlayerControl::Stop(){if(mciOpen.wDeviceID){//执行MCI_STOP操作,停止播放音乐mciSendCommand(mciOpen.wDeviceID,MCI_STOP,NULL,NULL);//把播放位置设定为音乐文件的开头(下一次播放操作从文件开头位置开始)mciSendCommand(mciOpen.wDeviceID,MCI_SEEK,MCI_SEEK_TO_START,NULL);}dwFrom=MCI_MAKE_HMS(0,0,0);}void CMyPlayerControl::Pause(){if(mciOpen.wDeviceID){//执行MCI_PAUSE操作,暂停播放音乐DWORD dwsf=GetLength(MCI_STATUS_POSITION);dwFrom=MCI_MAKE_MSF(MCI_MSF_MINUTE(dwsf),MCI_MSF_SECOND(dwsf),MCI_MSF_FRAME(dwsf));//执行MCI_PAUSE操作,暂停播放音乐mciSendCommand(mciOpen.wDeviceID,MCI_PAUSE,NULL,NULL);}}void CMyPlayerControl::SetWindowHwnd(HWND hWnd){m_hWnd=hWnd;}
使用类的定义方法,可以使这个类具有更高的重用性。

CMp3PlayerDlg.h的声明中为各个按钮添加单击事件响应函数,并添加OnOk、OnCancel虚函数,并对WM_TIMER添加响应函数,对滑动条添加私有变量CSliderControl m_process以及。其具体代码如下:

// Mp3PlayerDlg.h : 头文件//#if !defined(AFX_MP3PLAYERDLG_H__)#define AFX_MP3PLAYERDLG_H__#if _MSG_VER > 1000#pragma once#endif#include"MyPlayerControl.h"#include "afxcmn.h"// CMp3PlayerDlg 对话框class CMp3PlayerDlg : public CDialogEx{// 构造public:CMp3PlayerDlg(CWnd* pParent = NULL);// 标准构造函数// 对话框数据enum { IDD = IDD_MP3PLAYER_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV 支持// 实现protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()public:afx_msg void OnBnClickedPlayButton();afx_msg void OnBnClickedPauseButton();afx_msg void OnBnClickedStopButton();afx_msg void OnBnClickedOpenButton();CSliderCtrl m_process;private:CMyPlayerControl m_myPlayerControl;CString m_strFileName;virtual void OnCancel();virtual void OnOK();public:afx_msg void OnTimer(UINT_PTR nIDEvent);};#endif
在声明过函数之后,在源文件CMp3PlayerDlg.cpp中进行具体实现:

// Mp3PlayerDlg.cpp : 实现文件//#include "stdafx.h"#include "Mp3Player.h"#include "Mp3PlayerDlg.h"#include "afxdialogex.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx{public:CAboutDlg();// 对话框数据enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现protected:DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)END_MESSAGE_MAP()// CMp3PlayerDlg 对话框CMp3PlayerDlg::CMp3PlayerDlg(CWnd* pParent /*=NULL*/): CDialogEx(CMp3PlayerDlg::IDD, pParent), m_strFileName(_T("")){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CMp3PlayerDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_PROCESS, m_process);}BEGIN_MESSAGE_MAP(CMp3PlayerDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_PLAY_BUTTON, &CMp3PlayerDlg::OnBnClickedPlayButton)ON_BN_CLICKED(IDC_PAUSE_BUTTON, &CMp3PlayerDlg::OnBnClickedPauseButton)ON_BN_CLICKED(IDC_STOP_BUTTON, &CMp3PlayerDlg::OnBnClickedStopButton)ON_BN_CLICKED(IDC_OPEN_BUTTON, &CMp3PlayerDlg::OnBnClickedOpenButton)ON_WM_TIMER()END_MESSAGE_MAP()// CMp3PlayerDlg 消息处理程序BOOL CMp3PlayerDlg::OnInitDialog(){CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);// 设置大图标SetIcon(m_hIcon, FALSE);// 设置小图标// TODO: 在此添加额外的初始化代码return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}void CMp3PlayerDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}}// 如果向对话框添加最小化按钮,则需要下面的代码//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,//  这将由框架自动完成。void CMp3PlayerDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int 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;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CMp3PlayerDlg::OnQueryDragIcon(){return static_cast<HCURSOR>(m_hIcon);}void CMp3PlayerDlg::OnBnClickedPlayButton(){// TODO: 在此添加控件通知处理程序代码DWORD cdlen=m_myPlayerControl.GetLength(MCI_STATUS_LENGTH);m_myPlayerControl.Play();m_process.SetRange(0,cdlen);SetTimer(0,1000,NULL);}void CMp3PlayerDlg::OnBnClickedPauseButton(){// TODO: 在此添加控件通知处理程序代码m_myPlayerControl.Pause();//调用暂停}void CMp3PlayerDlg::OnBnClickedStopButton(){// TODO: 在此添加控件通知处理程序代码m_myPlayerControl.Stop();m_process.SetPos(0);KillTimer(0);}void CMp3PlayerDlg::OnBnClickedOpenButton(){// TODO: 在此添加控件通知处理程序代码CString strFilter(_T("MP3 Files(*.mp3)|*.mp3||"));CFileDialog OpenDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,strFilter);int nFlags=OpenDlg.DoModal();//通过打开对话框选择MP3文件if(nFlags==IDOK){//用户单击的是“打开”按钮,将文件路径名赋给成员变量m_strFileName备用m_strFileName=OpenDlg.GetPathName();//打开MCI设备,并将设备分配给选中的文件使用m_myPlayerControl.Open(m_strFileName);}}void CMp3PlayerDlg::OnCancel(){// TODO: 在此添加专用代码和/或调用基类CDialogEx::OnCancel();}void CMp3PlayerDlg::OnOK(){// TODO: 在此添加专用代码和/或调用基类CDialogEx::OnOK();}void CMp3PlayerDlg::OnTimer(UINT_PTR nIDEvent){// TODO: 在此添加消息处理程序代码和/或调用默认值//每秒钟得到的当前播放进度DWORD cdf=m_myPlayerControl.GetLength(MCI_STATUS_POSITION);m_process.SetPos(cdf);//设置进度条位置CDialogEx::OnTimer(nIDEvent);//调用其他Timer}
测试程序效果。操作方法为:单击“打开文件”按钮,弹出“打开”对话框。指定文件,并单击对话框中的“打开”按钮,打开指定文件后,单击“播放”按钮,这时进度条会自动向右增加,并且可以听到音乐开始播放了。这个例子只支持MP3格式的音乐。

至此,完成。

0 0
原创粉丝点击