MFC学习笔记之简单MP3播放器的设计
2015-06-24 19:44
369 查看
首先对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:
CMyPlayerControl.cpp:因为类中调用了系统的MCI接口的API函数,所以必须加入winmm.lib这个静态链接库文件。
CMp3PlayerDlg.h的声明中为各个按钮添加单击事件响应函数,并添加OnOk、OnCancel虚函数,并对WM_TIMER添加响应函数,对滑动条添加私有变量CSliderControl m_process以及。其具体代码如下:
至此,完成。
接口函数的声明如下:
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格式的音乐。
至此,完成。
相关文章推荐
- YUV Tools 和 YUV Library
- 系统重装故障解决方案
- android mqtt运用
- 如何在屏幕上显示多个alv
- vim常用命令
- 深入理解javascript之原型
- Radar Installation -poj 1328
- OC4_遵守多个协议
- 使用python开发app后台,xml和json的区别
- 关于类似Gmail邮件撤销功能实现初探
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- 看代码中遇到的难点
- intent传递字符串数组
- POJ 3107 Godfather (树的重心)
- iOS下载文件之NSData -UIImage
- 应用宝认领
- Excel Sheet Column Number -- leetcode
- json, protobuf-c++,pbc,sproto 性能测试与解决方案
- iphone使用开源代码Asyncsocket进行socket编程
- inno setup安装包程序完整版