第10章媒体控制接口 10.1MCI设备类型 10.2MCI编程步骤 103使用 MCIWnd窗口类
第10章媒体控制接口 10.1 MCI设备类型 10.2 MCI编程步骤 10.3使用MCIWnd窗口类
101MCI设备类型 媒体控制接口允许控制两类设备:第一类为简单设备,是指那些不需要文件 的设备,如CD音频播放设备;第二类为复合设备,是那些需要文件的设备 如数字视频及波形音频设备等。表列出了目前已定义的设备的标识符。 表101MCI设备类型 设备类型 说明 设备类型 说明 amadon 动画设备 scanner 图形扫描设备 CD音频设备 ncer MD设备 dat 数字音频磁带机 录相机设备 talⅵdo 数字视频设备 影碟播放设备 未定义的M设备 waveaulio 波形音频设备 overla y 窗口中的模拟设备
10.1 MCI设备类型 媒体控制接口允许控制两类设备:第一类为简单设备,是指那些不需要文件 的设备,如CD音频播放设备;第二类为复合设备,是那些需要文件的设备, 如数字视频及波形音频设备等。表列出了目前已定义的设备的标识符
102MCI编程步骤 打开设备 MCI为不同的多媒体设备打开提供相应的数据结构类型。若不想使用设备中特定的参 数数据,则可使用统一的 MCI OPEN_ PARMS结构,原型: ypedef struct k DWoRd dw Callback, ∥/低字节用于 MCI NOTIFY的窗口句柄 MCIDEVICEID WDeviceID;∥返回的设备标识符 LPCSTR pstr Device Type;∥/MCI设备的类型 LPCSTR pstrElementName ∥/设备元素 LPCSTR pstrAlias: ∥/可选的设备别名 3 MCI_OPEN_ PARMS 打开多媒体设备的过程:定义一个 MCI OPEN_ PARMS结构类型变量,给结构变量中 的相应参数赋值,调用 mciSend Command向设备发送 MCI OPEN命令消息,成功调用 时,可获得相应的设备标识符。例如,下面的代码是打开波形音频设备 WORD WDeviceID /MCI设备ID CString fileName: ∥/波形文件名 MCI OPEN PARMS open Parms ∥/MCI设备打开参数 open Parms. IpstrDevice Type=" waveaudio";∥/波形音频设备 open Parms. Ipstr ElementName fileName if(mciSend Command(NULL MCI_ OPEN MCI_OPEN_ELEMENT MCI_OPEN_TYPE (DWORD)(LPVOID) &open Parms)) return FALSE, wDeviceId= open Parms. wDeviceID
10.2 MCI编程步骤 ➢ 打开设备 MCI为不同的多媒体设备打开提供相应的数据结构类型。若不想使用设备中特定的参 数数据,则可使用统一的MCI_OPEN_PARMS结构,原型: typedef struct { DWORD dwCallback; // 低字节用于MCI_NOTIFY的窗口句柄 MCIDEVICEID wDeviceID; // 返回的设备标识符 LPCSTR lpstrDeviceType; // MCI设备的类型 LPCSTR lpstrElementName; // 设备元素 LPCSTR lpstrAlias; // 可选的设备别名 } MCI_OPEN_PARMS; 打开多媒体设备的过程:定义一个MCI_OPEN_PARMS结构类型变量,给结构变量中 的相应参数赋值,调用mciSendCommand向设备发送MCI_OPEN命令消息,成功调用 时,可获得相应的设备标识符。例如,下面的代码是打开波形音频设备: WORD wDeviceID; // MCI设备ID CString fileName; // 波形文件名 ... MCI_OPEN_PARMS openParms; // MCI设备打开参数 openParms.lpstrDeviceType = "waveaudio"; // 波形音频设备 openParms.lpstrElementName = fileName; if (mciSendCommand (NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_OPEN_TYPE, (DWORD)(LPVOID) &openParms)) return FALSE; wDeviceID = openParms.wDeviceID;
102MCI编程步骤 >设置或获取设备信息 使用 MCI SET和 MCI STATUS命令可以用来设置和获取设备信息,在用函数 mciSendCommand发送命令时,使用相应的 MCI SET PARMS和 MCI STATUS PARMS结构。原型 typedef struct dWord caLlback;∥/低字节用于 MCI NOTIEY的窗口句柄 dword dwtimeformat ∥/时间格式 dword dwaudio ∥/输出声道 3 MCI_ SET_ PARMS, typedef struct { Dword dwCallback;∥/低字节用于 MCI NOTIFY的窗口句柄 dword dwReturn ∥/要获取的设备信息 DWORD dwItem; ∥/需要获取的信息项 dword dwTrack ∥/曲目的长度或曲目号 3 MCI_ STATUS PARMS 例如,下面的代码是将波形音频设备的时间格式设成毫秒 MCI SET_ PARMS setParms setParms. dw TimeFormat=MCI FORMAT MILLISECONDS if (mciSend Command( DeviceID, MCI_ SET, MCI_ SET_TIME_ FORMAT (DWORD)(LPVOID) &setParms)) return FALSEr
10.2 MCI编程步骤 ➢ 设置或获取设备信息 使用MCI_SET和MCI_STATUS命令可以用来设置和获取设备信息,在用函数 mciSendCommand发送命令时,使用相应的MCI_SET_PARMS和 MCI_STATUS_PARMS结构。原型: typedef struct { DWORD dwCallback; // 低字节用于MCI_NOTIFY的窗口句柄 DWORD dwTimeFormat; // 时间格式 DWORD dwAudio; // 输出声道 } MCI_SET_PARMS; typedef struct { DWORD dwCallback; // 低字节用于MCI_NOTIFY的窗口句柄 DWORD dwReturn; // 要获取的设备信息 DWORD dwItem; // 需要获取的信息项 DWORD dwTrack; // 曲目的长度或曲目号 } MCI_STATUS_PARMS; 例如,下面的代码是将波形音频设备的时间格式设成毫秒: MCI_SET_PARMS setParms; setParms.dwTimeFormat=MCI_FORMAT_MILLISECONDS; if (mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &setParms)) return FALSE;
102MCI编程步骤 播放设备 使用MCI_PLAY命令可以使设备播放多媒体文件,并在用函数 mcisendcommand发送命令时,使用相应的 MCI PLAY PARMS结构,其原 型如下 typedef struct { DWORD caLlback;∥/低字节用于 MCI NOTIFY的窗口句柄 dWoRd dwFrom ∥/播放的起点位置 DWORD wTO ∥/播放的终点位置 S MCI PLAY_ PARMS, 例如,下面的代码是播放波形音频设备 MCI_PLAY_ PARMS play Parms, ∥/定位到开始位置 mciSendCommand (wDeviceID, MCI_ SEEK, MCI_SEEK_TO_ START, NULL) ∥/播放设备 if (mciSendCommand (w DeviceID, MCI_ PLAY, NULL (DWORD)(LPVOID) &play Parms)) return false else return TRUEr
10.2 MCI编程步骤 ➢ 播放设备 使用MCI_PLAY命令可以使设备播放多媒体文件,并在用函数 mciSendCommand发送命令时,使用相应的MCI_PLAY_PARMS结构,其原 型如下: typedef struct { DWORD dwCallback; // 低字节用于MCI_NOTIFY的窗口句柄 DWORD dwFrom; // 播放的起点位置 DWORD dwTo; // 播放的终点位置 } MCI_PLAY_PARMS; 例如,下面的代码是播放波形音频设备: MCI_PLAY_PARMS playParms; // 定位到开始位置 mciSendCommand (wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, NULL); // 播放设备 if (mciSendCommand (wDeviceID, MCI_PLAY, NULL, (DWORD)(LPVOID) &playParms)) return FALSE; else return TRUE;
102MCI编程步骤 例如,若接收 MM MCINOTIFY消息的窗口是一个对话框 CMyDlg,则添加消息处理的 过程如下 (1)切换到项目工作区窗口的 Classview页面,右击CMyD类,选择快捷菜单中的 “ Add Member Function.命令。为 CMyDlg类添加保护型的成员函数,原型: protected: LRESULT OnMCINotify(WPARAM wParam, LPARAM IParam); (2)在类 CMyDlg的消息入口处,添加下列消息宏指令: BEGIN_ MESSAGE_ MAP(CMyDlg, CDialog) //AFX_MSG_MAP(CMyDIg) JAFX_MSG_MAP ON_MESSAGE(MM_MCINOTIFY, OnMCINotify) END_ MESSAGE_ MAPO (3)编写 CMyDlg: OnMCINotify函数代码 LRESULT CMyDIg: OnMCINotify(WPARAM wParam, LPARAM IParam) return False (4)关闭设备 使用 MCI STOP和 MCI CLOSE命令可以分别用来停止播放和关闭设备。不需要设置或 返回附加的信息,因此不必考虑相应的 MC GENERIC PARMS结构
10.2 MCI编程步骤 例如,若接收MM_MCINOTIFY消息的窗口是一个对话框CMyDlg,则添加消息处理的 过程如下: (1)切换到项目工作区窗口的ClassView页面,右击CMyDlg类,选择快捷菜单中的 “Add Member Function...”命令。为CMyDlg类添加保护型的成员函数,原型: protected: LRESULT OnMCINotify(WPARAM wParam,LPARAM lParam); (2)在类CMyDlg的消息入口处,添加下列消息宏指令: BEGIN_MESSAGE_MAP(CMyDlg, CDialog) //{{AFX_MSG_MAP(CMyDlg) ... //}}AFX_MSG_MAP ON_MESSAGE(MM_MCINOTIFY,OnMCINotify) END_MESSAGE_MAP() (3)编写CMyDlg::OnMCINotify函数代码: LRESULT CMyDlg::OnMCINotify(WPARAM wParam, LPARAM lParam) { ... return FALSE; } (4)关闭设备 使用MCI_STOP和MCI_CLOSE命令可以分别用来停止播放和关闭设备。不需要设置或 返回附加的信息,因此不必考虑相应的MCI_GENERIC_PARMS结构
103使用 MCIWnd窗口类 MCIWnd是一个控制多媒体设备的窗口类。若在应用程序中使用 MCIWnd窗口 类,必须在调用 MCIWnd函数所在的源文件的前面添加vh的头文件,以及 编译时加入vw32.ib库或在程序中加入下列语句 #pragma comment(ib, vfw32 ib") 在 MCIWnd窗口类中,虽然它所提供的函数并不多,但是它所提供的宏却非常 多,并且基本上与MCI的底层功能相对应。 在应用程序中使用 MCIWnd窗口类的一般步骤是 (1)在程序中调用 MCIWndRegisterClass函数注册MCI窗口类,以便以后用 CreateWindow或 CreateWindowEx函数创建窗口,或者直接调用函数 MCIWndCreate创建窗口。 (2)获得相应的窗口句柄后,就可调用 MCIWndOpen宏来打开设备 (3)由于 MCIWnd窗口提供了相应的媒体控制按钮,因而不需要用户编写额外 的代码 (4)但作为技巧,用户还应该跟踪 MCIWnd窗口的一些消息(如 MCIWNDM NOTIFYSIZE来调整 MCIWnd窗口
10.3使用MCIWnd窗口类 ◆ MCIWnd是一个控制多媒体设备的窗口类。若在应用程序中使用MCIWnd窗口 类,必须在调用MCIWnd函数所在的源文件的前面添加vfw.h的头文件,以及 编译时加入vfw32.lib库或在程序中加入下列语句: #pragma comment (lib,"vfw32.lib") ◆ 在MCIWnd窗口类中,虽然它所提供的函数并不多,但是它所提供的宏却非常 多,并且基本上与MCI的底层功能相对应。 ◆ 在应用程序中使用MCIWnd窗口类的一般步骤是: (1)在程序中调用MCIWndRegisterClass函数注册MCI窗口类,以便以后用 CreateWindow或CreateWindowEx函数创建窗口,或者直接调用函数 MCIWndCreate创建窗口。 (2)获得相应的窗口句柄后,就可调用MCIWndOpen宏来打开设备。 (3)由于MCIWnd窗口提供了相应的媒体控制按钮,因而不需要用户编写额外 的代码。 (4)但作为技巧,用户还应该跟踪MCIWnd窗口的一些消息(如MCIWNDM_ NOTIFYSIZE)来调整MCIWnd窗口
103使用 MCIWnd窗口类 [例EⅹMC]利用 MCIWnd窗口类在多文档应用程序中添加一个多媒体播放器 (1)用 MFC AppWizard(exe)创建一个多文档项目 EX MCI,单击[ Finish]。 (2)在 StdAfx. h中放入包含文件使得应用程序能使用所有的多媒体代码。由于项目中的每 个文件已经包含了 StdAfx. h,所以在其他地方就不必再包含这些多媒体文件 #endif// AFX_ No AFXCMN_ SUPPORT #include #pragma comment (ib, vfw32 ib") (3)在 CEX MCIAPP: InitInstance函数,使用 MCIWndRegisterclassi函数注册MCI窗口 里 后面的创建窗口是直接调用函数 MCIWnd Create来进行的,但还应该保证应用 序的运行系统拥有并支持 MCIWnd窗口类。 BOOL CEX_ MCIApp: Initinstanceo if(!MCIWndRegisterClasso return FALSE AfXEnable ControlContainer O; (4)在 EX MCIView类中添加一个公共成员变量用来标识嵌入的MWnd窗口句柄。 public CEx_ MCIDOCK GetDocumento HWND m_ hMyMCIWnd
10.3使用MCIWnd窗口类 [例Ex_MCI] 利用MCIWnd窗口类在多文档应用程序中添加一个多媒体播放器。 (1)用MFC AppWizard(exe)创建一个多文档项目Ex_MCI,单击[Finish]。 (2)在StdAfx.h中放入包含文件使得应用程序能使用所有的多媒体代码。由于项目中的每 一个文件已经包含了StdAfx.h,所以在其他地方就不必再包含这些多媒体文件。 ... #endif // _AFX_NO_AFXCMN_SUPPORT #include #pragma comment (lib,"vfw32.lib") ... (3)在CEx_MCIApp::InitInstance函数,使用MCIWndRegisterClass函数注册MCI窗口类。 虽然,后面的创建窗口是直接调用函数MCIWndCreate来进行的,但还应该保证应用程 序的运行系统拥有并支持MCIWnd窗口类。 BOOL CEx_MCIApp::InitInstance() { if (!MCIWndRegisterClass()) return FALSE; AfxEnableControlContainer(); ... } (4)在Ex_MCIView类中添加一个公共成员变量用来标识嵌入的MCIWnd窗口句柄。 public: CEx_MCIDoc* GetDocument(); HWND m_hMyMCIWnd;
103使用 MCIWnd窗口类 (5)用 ClassWizard为 EX MCIView类中添加 OnInitialUpdate消息处理函数,增 加代码: void CEX_MCIView:: OnInitialUpdateo t CView: OnInitialUpdateo m_ hMyMCIWnd=MCIWndCreate(m_hWnd, AfXGetInstanceHandleo, MCIWNDF NOTIFYSIZE MCIWNDF NOERRORDLG I WS_CHILD WS_VISIBLE, NULL) if (m hMyMCIWnd==NULL return; const CString &filename=GetDocumento->GetPathNameo if (filename. GetLengtho>0) MCIWndOpen(m_ hMyMCIWnd, (LPCSTR)filename, 0); (6)在 CEX MCIView构造函数中将成员变量 m_hMyMCIWnd初始化为NUL CEX_MCIView: CEX_MCIViewo t m_hMyMCIWnd=NULLI
10.3使用MCIWnd窗口类 (5)用ClassWizard为Ex_MCIView类中添加OnInitialUpdate消息处理函数,增 加代码: void CEx_MCIView::OnInitialUpdate() { CView::OnInitialUpdate(); m_hMyMCIWnd=MCIWndCreate(m_hWnd,AfxGetInstanceHandle(), MCIWNDF_NOTIFYSIZE |MCIWNDF_NOERRORDLG | WS_CHILD|WS_VISIBLE,NULL); if (m_hMyMCIWnd==NULL) return; const CString &filename=GetDocument()->GetPathName(); if (filename.GetLength()>0) MCIWndOpen(m_hMyMCIWnd,(LPCSTR)filename,0); } (6)在CEx_MCIView构造函数中将成员变量m_hMyMCIWnd初始化为NULL。 CEx_MCIView::CEx_MCIView() { m_hMyMCIWnd=NULL; }
103使用 MCIWnd窗口类 (刀)要添加处理该消息的代码来调整窗口的大小以便能及时更新显示。需要手动进行 在 Ex MCIView, h文件中的消息声明处添加下列代码 // Generated message map functions protected: //AFX_ MSG(CEX_ MCIView) I/AFX_ MSG afx_msg LONG On NotifySize (UINT wParam, LONG IParam) DECLARE_ MESSAGE_ MAPO (8)在 Ex_MCIView cpp的消息入口处添加下列代码: BEGIN_MESSAGE_MAP(CEX_MCIView, CView) AFX_MSG_MAP (CEX_MCIView) ON_ MESSAGE(MCIWNDM_ NOTIFYSIZE, OnNotifysize //JAFX_MSG_MAP // Standard printing commands ON_COMMANDID_ FILE_PRINT, CView:: On FilePrint ON_COMMAND(ID_FILE- PRINT- DIRECT, CView:: On FilePrint) ON_COMMAND(ID_FILE_PRINT_ PREVIEW, CView:: On FilePrintPreview) END_MESSAGE_MAPO
10.3使用MCIWnd窗口类 (7) 要添加处理该消息的代码来调整窗口的大小以便能及时更新显示。需要手动进行。 在Ex_MCIView.h文件中的消息声明处添加下列代码: // Generated message map functions protected: //{{AFX_MSG(CEx_MCIView) ... //}}AFX_MSG afx_msg LONG OnNotifySize(UINT wParam, LONG lParam); DECLARE_MESSAGE_MAP() (8)在Ex_MCIView.cpp的消息入口处添加下列代码: BEGIN_MESSAGE_MAP(CEx_MCIView, CView) //{{AFX_MSG_MAP(CEx_MCIView) ... ON_MESSAGE(MCIWNDM_NOTIFYSIZE,OnNotifySize) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()