第 10 章 多媒体应用

38
第 10 第第第 第第 10.1 第第第 第第第第 (MCI) 10.2 第第 OpenGL 10.3 DirectX 第第

Upload: sana

Post on 16-Mar-2016

75 views

Category:

Documents


4 download

DESCRIPTION

第 10 章 多媒体应用. 10.1 使用媒体控制接口 (MCI) 10.2 使用 OpenGL 10.3 DirectX 编程. 10.1 使用媒体控制接口 (MCI). 10.1.1 MCI 设备类型 媒体控制接口允许控制两类设备:第一类为简单设备,是指那些不需要文件的设备,如 CD 音频播放设备;第二类为复合设备,是那些需要文件的设备,如数字视频及波形音频设备等。表 10.1 列出了目前已定义的设备的标识符。. 10.1 使用媒体控制接口 (MCI). 10.1.2 MCI 编程步骤 打开设备 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 10 章 多媒体应用

第 10 章多媒体应用 10.1 使用媒体控制接口 (MCI) 10.2 使用 OpenGL 10.3 DirectX 编程

Page 2: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI) 10.1.1 MCI 设备类型

媒体控制接口允许控制两类设备:第一类为简单设备,是指那些不需要文件的设备,如 CD 音频播放设备;第二类为复合设备,是那些需要文件的设备,如数字视频及波形音频设备等。表 10.1 列出了目前已定义的设备的标识符。

Page 3: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)10.1.2 MCI 编程步骤 打开设备 MCI 为不同的多媒体设备打开提供相应的数据结构类型。打开一个多媒体设备:定义一个多媒体设备结构类型变量,给结构变量中的相应参数赋值,调用 mciSendCommand 成功调用时,即可获得相应的设备标识符。下面的代码是打开波形音频设备:WORD wDeviceID; // MCI 设备 IDCString 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; 设置或获取设备信息 使用 MCI_SET 和 MCI_STATUS 命令可以设置和获取设备信息,函数 mciSendCommand发送命令时,使用相应的 MCI_SET_PARMS 结构。 将波形音频设备的时间格式设成毫秒:MCI_SET_PARMS setParms;setParms.dwTimeFormat=MCI_FORMAT_MILLISECONDS;if(mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT,(DWORD)(LPVOID) &setParms))return FALSE;

Page 4: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI) 播放设备

使用 MCI_PLAY 命令可以使设备播放多媒体文件,并在用函数 mciSendCommand 发送命令时,使用相应的 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;

关闭设备 用 MCI_STOP 和 MCI_CLOSE 用来停止播放和关闭设备。它们不需要设置或返回附加的信息,不必考虑相应的 MCI_GENERIC_PARMS 结构。下面是停止播放波形音频设备并关闭:if (wDeviceID){mciSendCommand (wDeviceID, MCI_STOP, MCI_WAIT, NULL); mciSendCommand (wDeviceID, MCI_CLOSE, NULL, NULL);}wDeviceID = 0;

Page 5: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI) 实例 [例 Ex_Wave] 播放WAVE音频。 (1)    用 MFC AppWizard 创建一个默认的基于对话框的应用程序项目 Ex_Wave 。(2)   单击开发环境标准工具栏中的新建工具按钮 () ,输入下列代码:class CWave : public CObject{ public:// 构造和析构函数CWave();virtual ~CWave();// 操作public:BOOL Open(CString waveFileName);// 调入一个波形文件并打开设备void Close(); // 关闭设备void Stop(); // 停止播放BOOL Play(CWnd *pWnd); // 播放并向窗口 pWnd 发送 MCI_NOTIFY 消息// 数据成员protected:WORD m_wDeviceID; // 用于保存设备标识BOOL m_bOpened; // 设备打开标志}; (3) 按快捷键 Ctrl+S ,指定文件名 Wave.h ,保存到 Ex_Wave 文件夹“ ..\Ex_Wave” 中。

Page 6: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(4)  按上述方法,再创建一个 Wave.cpp 文件,其代码如下:#include "stdafx.h"#include "Wave.h"CWave::CWave() // 在构造函数中添加一些初始代码{ m_bOpened = FALSE; // 设备没有打开m_wDeviceID = 0; // 设备号为 0 }CWave::~CWave() // 在析构函数中添加关闭设备代码{ Close(); // 关闭设备 }BOOL CWave::Play(CWnd *pWnd) // 在窗口中播放设备{ Stop(); // 停止播放设备,设备复位MCI_PLAY_PARMS playParms; // 定义一个播放结构变量playParms.dwCallback=(DWORD)pWnd->m_hWnd; // 设置回调窗口句柄mciSendCommand (m_wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, NULL);// 定位到设备的开始if (mciSendCommand (m_wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&playParms))/* 播放设备并向回调窗口发送 MCI_NOTIFY 消息 */return FALSE;else return TRUE;}

Page 7: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)void CWave::Stop() // 停止播放{ mciSendCommand (m_wDeviceID, MCI_STOP, NULL, NULL); }void CWave::Close() // 关闭设备{ m_bOpened = FALSE;if (m_wDeviceID){ mciSendCommand (m_wDeviceID, MCI_STOP, MCI_WAIT, NULL);mciSendCommand (m_wDeviceID, MCI_CLOSE, NULL, NULL); }m_wDeviceID = 0; }BOOL CWave::Open(CString waveFileName) // 打开设备并调入音频波型文件{ if (m_bOpened) Close(); // 若设备打开,关闭它MCI_OPEN_PARMS openParms;openParms.lpstrDeviceType = "waveaudio";openParms.lpstrElementName = waveFileName;if (mciSendCommand (NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_OPEN_TYPE|MCI_WAIT, (DWORD)(LPVOID) &openParms))return FALSE;// MCI_OPEN_ELEMENT 指定音频波型文件保存在 lpstrElementName 中,// MCI_OPEN_TYPE 指定设备类型保存在 lpstrDeviceType 中m_wDeviceID = openParms.wDeviceID;m_bOpened = TRUE;return TRUE;}

Page 8: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(5) 选择“工程”“添加工程”“ Files” ,选中源代码文件 Wave.h 和 Wave.cpp ,单击 [ 确定 ], CWave 类就加入到项目 Ex_Wave 中了。(6)  打开 StdAfx.h 文件,添加调用 MCI 函数所需要的头文件和库的包含语句:#ifndef _AFX_NO_AFXCMN_SUPPORT#include <afxcmn.h> // MFC support for Windows Common Controls#endif // _AFX_NO_AFXCMN_SUPPORT#include <mmsystem.h>#pragma comment (lib,"winmm.lib")(7)   切换到 ResourceView页面,打开 IDD_EX_WAVE_DIALOG 对话框资源。(8) 将对话框标题改为“播放波形音频”。 (9) 按图 10.1所示的布局,添加如表 10.1所示的控件。

Page 9: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI) (10) 打开 MFC ClassWizard 对话框,切换到 Member Variables页面,为上述控件添加相关联的成员变量如表 10.2。

(11) 为 CEx_WaveDlg 类添加一个公有型成员 CWave m_wave ,并在 Ex_WaveDlg.h 文件的前面添加 CWave 类的包含语句:#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include "Wave.h"

Page 10: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(12)   用 ClassWizard 在 CEx_WaveDlg 类分别为按钮控件 IDC_FILE、 IDC_PLAY 和 IDC_STOP 添加 BN_CLICKED 消息映射,并在函数中添加下列代码:void CEx_WaveDlg::OnFile() { CString filter;filter = " 波形音频文件 (*.wav)|*.wav||";CFileDialog dlg (TRUE, NULL, NULL, OFN_HIDEREADONLY, filter);if (dlg.DoModal () == IDOK){ CString str;str = dlg.GetPathName();if (m_wave.Open(str)){m_btnPlay.EnableWindow(TRUE);m_btnPlay.SetFocus();m_strFileName = str;UpdateData( FALSE );}else MessageBox(str+" 文件打不开或操作失败! ");}}

Page 11: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)void CEx_WaveDlg::OnPlay() { if (m_wave.Play(this)){

m_btnPlay.EnableWindow(FALSE); // 禁用 [播放 ]按钮m_btnFile.EnableWindow(FALSE);// 禁用 [波形文件 ]按钮m_btnStop.EnableWindow(TRUE);m_btnStop.SetFocus(); // 设置控件输入焦点

}}void CEx_WaveDlg::OnStop() { m_wave.Stop();m_btnPlay.EnableWindow(TRUE);m_btnFile.EnableWindow(TRUE);m_btnStop.EnableWindow(FALSE); // 禁用 [停止 ]按钮m_btnPlay.SetFocus();}

Page 12: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI) (13)编译并运行。从Windows\Media 目录中调用一些波形文件,单击 [播放 ]按钮,来欣赏一下音乐,如图。

(14) 上述程序的运行结果中,当一个波形音乐播放完之后,若不单击 [停止 ]按钮,则 [播放 ]按钮被禁用。实际上,当波形音频播放完毕后, [播放 ] 就应该可以使用。为此需要处理 MM_MCINOTIFY 消息来实现,但由于MFC ClassWizard 不支持该消息的映射,因而需要手动进行。(15)  打开 Ex_WaveDlg.h 文件,添加 MM_MCINOTIFY 消息映射函数声明,如下面所示的代码:protected:…LRESULT OnMCINotify(WPARAM wParam,LPARAM lParam);

DECLARE_MESSAGE_MAP()};

Page 13: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(16)   打开 Ex_WaveDlg.cpp 文件,在类 CEx_WaveDlg 的消息入口处,添加消息宏指令:BEGIN_MESSAGE_MAP(CEx_WaveDlg, CDialog)//{{AFX_MSG_MAP(CEx_WaveDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_FILE, OnFile)ON_BN_CLICKED(IDC_PLAY, OnPlay)ON_BN_CLICKED(IDC_STOP, OnStop)//}}AFX_MSG_MAPON_MESSAGE(MM_MCINOTIFY,OnMCINotify)END_MESSAGE_MAP()(17)   在 Ex_WaveDlg.cpp 文件的最后,添加 CEx_WaveDlg::OnMCINotify 函数代码:LRESULT CEx_WaveDlg::OnMCINotify(WPARAM wParam, LPARAM lParam){ OnStop();return FALSE; }

(18)编译并运行。从Windows\Media 目录中调用一些波形文件,单击 [播放 ]按钮,看看与前面有什么不同。

Page 14: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)10.1.3 使用 MCIWnd 窗口类 MCIWnd 窗口类

MCIWnd 是一个控制多媒体设备的窗口类,它提供的函数、消息以及宏与上述的 MCI 的底层功能具体相似的方法。若在应用程序中使用 MCIWnd 函数所在的源文件的前面 (最好是 stdafx.h) 添加 vfw.h 的头文件,以及编译时加入 vfw32.lib库或在程序中加入下列语句:#pragma comment (lib,"vfw32.lib")在 MCIWnd 窗口类中,虽然它所提供的函数并不多,但是它所提供的宏却非常多,并且基本上与MCI 的底层功能相对应。

使用 MCIWnd 窗口类一般步骤在应用程序中使用 MCIWnd 窗口类的一般步骤是:

(1) 在程序中调用 MCIWndRegisterClass 函数注册 MCI 窗口类,以便以后用 CreateWindow 或 CreateWindowEx 函数创建窗口,或者直接调用函数 MCIWndCreate 创建窗口。(2)  获得相应的窗口句柄后,就可调用 MCIWndOpen宏来打开设备。 (3)MCIWnd 窗口提供了相应的媒体控制按钮,因而不需要编写额外的代码。(4)但作为技巧,用户还应该跟踪 MCIWnd 窗口的一些消息 ( 如 MCIWNDM_ NOTIFYSIZE) 来调整 MCIWnd 窗口。

Page 15: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI) 示例 [例 Ex_MCI] 制作一个多媒体播放器。 (1)  用 MFC AppWizard(exe) 创建一个默认的多文档应用程序项目 Ex_MCI 。(2) 在 StdAfx.h 中放入包含文件使得应用程序能使用所有的多媒体代码。由于项目中的每一个文件已经包含了 StdAfx.h ,所以在其他地方就不必再包含这些多媒体文件。...#endif // _AFX_NO_AFXCMN_SUPPORT#include <vfw.h>#pragma comment (lib,"vfw32.lib")... (3) 在 CEx_MCIApp::InitInstance 函数,使用 MCIWndRegisterClass 函数注册 MCI 窗口类。虽然,后面的创建窗口是直接调用函数 MCIWndCreate 来进行的,但还应该保证应用程序的运行系统拥有并支持MCIWnd 窗口类。 BOOL CEx_MCIApp::InitInstance(){ if (!MCIWndRegisterClass()) return FALSE;AfxEnableControlContainer();...}

Page 16: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(4) 在 Ex_MCIView 类中添加一个公共成员变量标识嵌入的 MCIWnd 窗口句柄。public: CEx_MCIDoc* GetDocument();HWND m_hMyMCIWnd;... (5) 为 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 ,由于以后要对 m_hMyMCIWnd进行判断,所以这一步非常重要。CEx_MCIView::CEx_MCIView(){ m_hMyMCIWnd = NULL; }

Page 17: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(7)  由于 MCIWnd会发送一个重要的消息 MCIWNDM_NOTIFYSIZE( 窗口大小改变 ) ,所以还要添加处理该消息的代码来调整窗口的大小以便能及时更新显示。但 MFC ClassWizard所封装的消息列表没有此消息,因而需要手动进行。在 Ex_MCIView.h 文件中的消息声明处添加下列代码:

// Generated message map functionsprotected:

//{{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)...ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)ON_MESSAGE(MCIWNDM_NOTIFYSIZE,OnNotifySize)END_MESSAGE_MAP()

Page 18: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(9)  为 CEx_MCIView 类添加函数 OnNotifySize ,调整MCIWnd 窗口的大小,代码: LONG CEx_MCIView::OnNotifySize(UINT wParam, LONG lParam){ CRect rc;CFrameWnd* pParent = GetParentFrame(); // 获取主框架窗口指针if (m_hMyMCIWnd){ ::GetWindowRect(m_hMyMCIWnd,rc);pParent->CalcWindowRect(rc,CWnd::adjustBorder);CSize size(rc.Width(),rc.Height());if (GetExStyle()&WS_EX_CLIENTEDGE){ size.cx+=4;size.cy+=4; }pParent->SetWindowPos(NULL,0,0,size.cx,size.cy,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);}else { pParent->SetWindowPos(NULL,0,0,200,160,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);}return 1;}

Page 19: 第 10 章 多媒体应用

10.1 使用媒体控制接口 (MCI)(10)编译并运行。调入一个 AVI 文件 ( 或其他媒体文件 ) 并单击 [播放 ]()按钮,其结果如图所示。

Page 20: 第 10 章 多媒体应用

10.2 使用 OpenGL 10.2.1 OpenGL 特点及功能

OpenGL 不但具有开放性、独立性和兼容性三大特点,还提供了七大功能。(1) 建模功能(2) 变换功能 (3)颜色模式设置   (4)光照和材质设置 (5)纹理映射 (6) 位图显示和图像增强 (7)双缓存动画

Page 21: 第 10 章 多媒体应用

10.2 使用 OpenGL10.2.2OpenGL 图形库 OpenGL图形库主要由核心库、实用库和辅助库三个部分组成。核心库中有一百多个函数,它们是最基本的函数,其前缀是 gl实用库 (OpenGL utility library, GLU) 的函数功能更高一些,如绘制复杂的曲线曲面等;辅助库 (OpenGL auxilary library,GLAUX) 的函数是一些特殊的函数,包括简单的窗口管理、输入事件处理、某些复杂三维物体绘制等函数,前缀为 aux 。 此外,还有不少非常重要的 WGL 函数,专用于 OpenGL 和 Windows 窗口系统的连接,其前缀为 wgl ,主要用于创建和选择绘图内容以及在窗口内任一位置显示字符位图。这些功能是对 Windows 和 OpenGL 的唯一补充。另外,还有一些个 Win32函数用来处理像素格式 ( pixel formats) 和双缓存,它们是对 Win32 系统的扩展。 在 MFC 中使用这些图形库的函数时,还必须在源文件的开头处加入相应的包含文件,以及编译时加入相应的库或在程序中加入,如下列语句:#include "gl\gl.h"#include "gl\glu.h"#include "gl\glaux.h"#pragma comment (lib,"Opengl32.lib")#pragma comment (lib,"Glu32.lib")#pragma comment (lib,"Glaux.lib")

Page 22: 第 10 章 多媒体应用

10.2 使用 OpenGL10.2.3 用 MFC 编写 OpenGL 程序 编写 OpenGL 程序一般步骤 (1)先设置设备环境 DC 的位图格式 (PIXELFORMAT)属性,通过填写一个 PIXELFORMATDESCRIPTOR 的结构来完成,该结构决定了 OpenGL 作图的物理设备的属性,比如该结构中的数据项 dwFlags 中 PFD_DOUBLEBUFFER 位,如果没有设置,通过该设备的 DC 作图的 OpenGL 命令就不可能使用双缓冲来做动画。由于有一些位图格式 (PIXELFORMAT)DC 不支持,因而程序必须先用 ChoosePixelFormat 来选择与 DC所支持的指定位图格式最接近的位图格式,然后用 SetPixelFormat 设置 DC 的位图格式。

(2)根据刚才的设备环境 DC 用 wglCreateContext 建立一个渲染环境 RC(Rendering Context , RC) ,并调用 wglMakeCurrent 使得 RC与 DC 建立联系。 (3) 调用 OpenGL 函数作图。 (4) 作图完毕以后,先通过设置当前 RC 为 NULL ,断开和该渲染环境的联系,然后再根据 RC 句柄的有效性进行释放或者删除。

Page 23: 第 10 章 多媒体应用

10.2 使用 OpenGL OpenGL 程序示例 [例 Ex_OpenGL] 使用 OpenGL。 (1) 用 MFC AppWizard 创建一个单文档应用程序项目 Ex_OpenGL ,在向导第 4 步中将默认的“打印和打印预览 (Printing and print Preview)”选项去掉 (因为这里不需要 ) ,单击 [ 完成 ]按钮。(2) 向 CEx_OpenGLView 类中添加下列成员变量: public:HGLRC m_hGLRC;(3) 向 CEx_OpenGLView 类中添加下列成员函数:public:void DrawScene();(4)编写 DrawScene 函数代码:{glClearColor(0.0,0.0,0.0,0.0); // 设置清屏所需要的颜色glClear(GL_COLOR_BUFFER_BIT); // 清屏glPushMatrix(); // 把当前操作矩阵压入矩阵堆栈glColor3f(1.0,0.0,1.0); // 设置绘图颜色auxWireTeapot(0.4); // 绘制茶壶的线框模型glPopMatrix(); // 恢复当前操作矩阵glFinish(); // 完成绘制}

Page 24: 第 10 章 多媒体应用

10.2 使用 OpenGL(5) 在 CEx_OpenGLView 类的头文件 Ex_OpenGLView.h 的开始处添加 OpenGL库的包含文件#include "gl\gl.h"#include "gl\glu.h"#include "gl\glaux.h"#pragma comment (lib,"Opengl32.lib")#pragma comment (lib,"Glu32.lib")#pragma comment (lib,"Glaux.lib") (6)修改 CEx_OpenGLView 类中的 PreCreateWindow 函数来重新设置文档窗口的风格, OpenGL 窗口必须具有 WS_CLIPSIBLINGS 和 WS_CLIPCHILDREN风格,如下面的代码:BOOL CEx_OpenGLView::PreCreateWindow(CREATESTRUCT& cs){cs.style |= WS_CLIPSIBLINGS|WS_CLIPCHILDREN;

return CView::PreCreateWindow(cs);}

Page 25: 第 10 章 多媒体应用

10.2 使用 OpenGL(7) 为 CEx_OpenGLView 类添加 WM_CREATE 消息处理,增加下列初始化代码: int CEx_OpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1;PIXELFORMATDESCRIPTOR pfd ={ sizeof(PIXELFORMATDESCRIPTOR), // 该结构的大小1, // 该结构的版本号,这里必须为 1PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, // 像素颜色模式为 RGBA24, // 颜色的位数为 24位0, 0, 0, 0, 0, 0, // 忽略各颜色分量在 RGBA 的位数0, // 在 RGBA 中没有 alpha 成分0, // 忽略 alpha 的偏移量0, // 没有累加缓冲区0, 0, 0, 0, // 忽略累加缓冲区中各颜色的位数32, // z缓冲区的深度为 32位0, // 没有模板缓冲区0, // 没有辅助缓冲区PFD_MAIN_PLANE, // 设为主平面类型0, // 保留,这里必须是 00, 0, 0 // 忽略层、颜色等的屏蔽};

Page 26: 第 10 章 多媒体应用

10.2 使用 OpenGLCClientDC dc(this);

int pixelformat = ChoosePixelFormat(dc.GetSafeHdc(), &pfd);if (SetPixelFormat(dc.GetSafeHdc(), pixelformat, &pfd) == FALSE){

MessageBox("SetPixelFormat failed");return -1;

}m_hGLRC = wglCreateContext(dc.GetSafeHdc());

return 0;}

Page 27: 第 10 章 多媒体应用

10.2 使用 OpenGL(8) 为 CEx_OpenGLView 类添加 WM_DESTROY 消息处理,并增加代码来释放 RC 句柄: void CEx_OpenGLView::OnDestroy() { if (wglGetCurrentContext()!=NULL)wglMakeCurrent(NULL,NULL);if (m_hGLRC!=NULL){ wglDeleteContext(m_hGLRC);m_hGLRC=NULL;}CView::OnDestroy();} (9) 为 CEx_OpenGLView 类添加 WM_SIZE 消息处理,增加代码。作用是窗口大小发生改变时,相应的改变视口大小和投影变换方式,场景中的物体正确地显示于窗口中。 void CEx_OpenGLView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy);if(cy > 0){ CClientDC dc(this);wglMakeCurrent(dc.GetSafeHdc(),m_hGLRC);glViewport(0, 0, cx, cy);wglMakeCurrent(NULL,NULL);}}

Page 28: 第 10 章 多媒体应用

10.2 使用 OpenGL(10)  在 CEx_OpenGLView::OnDraw 中添加下列代码:void CEx_OpenGLView::OnDraw(CDC* pDC){ CEx_OpenGLDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);HWND hWnd=GetSafeHwnd(); // 获得当前窗口句柄HDC hDC=::GetDC(hWnd); // 获得与窗口句柄相关联的设备环境wglMakeCurrent(hDC,m_hGLRC);// 设置当前的渲染环境DrawScene(); // 绘制场景wglMakeCurrent(NULL,NULL); // 取消当前的渲染环境SwapBuffers(hDC); // 将图形显示在窗口的设备环境中} (11)编译并运行。注意运行时应保证屏幕的颜色在 16位以上,如图。

Page 29: 第 10 章 多媒体应用

10.3DirectX 编程 10.3.1 DirextX 概述 Direct3D 、 DirectDraw 和 DirectGraphics

DirectDraw为高速的 2D渲染提供了良好的支持,由于它具备直接显存访问和位快传送的能力,使得 2D图形的绘制速度相对 GDI有了一个质的飞跃,其渲染速度甚至有上百倍的差距。DirectX的版本到了 8.0 的时候结构发生了巨大的变化, 3D图形处理技术逐渐统一在 Vertex Shader 和 Pixel Shader 。 Vertex Shader被用来描述和修饰 3D物体的几何形状,同时也用来控制光亮和阴影; Pixel Shader则用来操纵物体表面的色彩和外观。Direct3DX 实用库是一个位于 Direct3D之上的辅助层,用于简化 3D图形开发者的常规工作。它包括了一个蒙皮库,支持对网格的操作,还有组装顶点与像素着色器的功能。除此以外, DirectX 9还提供位移贴图以及改进的设备模拟等特性的支持。 DirectSound 、 DirectMusic 和 DirectX Audio 在 DirectX中 DirectSound和 DirectMusic可以统称 DirectX Audio。 DirectX

Audio不是简单地对声音的回放,而且提供了一个完整的系统,能够利用硬件加速的功能动态地操纵控制音轨和声道 (soundtrack)。在 DirectX 9中加入了 DirectMP3和 DirectCD 两个功能模块,它们使得主流的音频播放也能够通过 DirectX 与其调用程序更好地结合在一起。

Page 30: 第 10 章 多媒体应用

10.3DirectX 编程 DirectInput

用来管理用户输入。与Winodows事件响应相比, DirectInput 可以直接访问硬件,直接从输入缓冲区内检索数据,从而获得比响应 Windows 消息更快的速度。 DirectInput也对力反馈游戏杆 (Force Feedback) 提供了良好的支持。 DirectPlay

DirectPlay兼顾速度与易用性两个方面,在网络游戏简化多人游戏的开发。 DirectShow

提供了 Windows平台下高质量的媒体捕获和回放能力,支持格式: ASF、MPG、 AVI、MP3和 WAV 。 DirectShow支持使用 WDM 设备或老式视频设备进行视频捕获。当有硬件支持的环境下,它会在使用视频或音频时自动选择是否使用硬件加速。

Page 31: 第 10 章 多媒体应用

10.3DirectX 编程10.3.2Direct3D 编程 [例 Ex_D3D] 用 Visual C++进行 Direct3D编程。 (1) 用MFC AppWizard(EXE)创建一个默认的单文档应用程序 Ex_D3D。(2) 为 CEx_D3DView类添加两个保护型对象,代码:protected:LPDIRECT3D9 m_pD3D; // Direct3D 对象的接口指针LPDIRECT3DDEVICE9 m_pDevice; // 设备对象的接口指针(3)为 CEx_D3DView类添加 OnInitialUpdate函数的重载,添加 Direct3D初始化代码:void CEx_D3DView::OnInitialUpdate() { CView::OnInitialUpdate();m_pD3D = ::Direct3DCreate9(D3D_SDK_VERSION);D3DPRESENT_PARAMETERS d3dpp;::ZeroMemory(&d3dpp, sizeof(d3dpp));d3dpp.Windowed = TRUE; // 创建窗口模式的 Direct3D 程序d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, // 使用默认的显卡D3DDEVTYPE_HAL, // 指定设备类型为 HALm_hWnd,// Direct3D 窗口的句柄D3DCREATE_SOFTWARE_VERTEXPROCESSING,//软件顶点处理&d3dpp, &m_pDevice); }

Page 32: 第 10 章 多媒体应用

10.3DirectX 编程(4)为 CEx_D3DView类添加WM_DESTROY消息映射,添加 Direct3D对象指针释放代码:void CEx_D3DView::OnDestroy() { CView::OnDestroy();m_pDevice->Release(); // 释放设备对象m_pD3D->Release(); // 释放 Direct3D 对象}(5) 打开 stdafx.h文件,添加 Direct3D的头文件和库的包含语句:#include <d3d9.h>#pragma comment (lib,"d3d9.lib")(6)在 CEx_D3DView::OnDraw函数中添加下列绘制代码:void CEx_D3DView::OnDraw(CDC* pDC){ CEx_D3DDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255), 1.0f, 0);// Direct3D规定在渲染前必须调用方法 IDirect3DDevice9::BeginScene ,m_pDevice->BeginScene();// 这里添加其他 3D绘制代码m_pDevice->EndScene();m_pDevice->Present(NULL, NULL, NULL, NULL);}

Page 33: 第 10 章 多媒体应用

10.3DirectX 编程(7)编译并运行,如图。 (8) 下面将要绘制一个三角形。 Direct3D中,所有的三维实体都是由三角形构成。对于三角形的顶点格式,在 class CEx_D3DView前面添加代码:// 定义 FVF 的顶点结构struct CUSTOMVERTEX{ float x, y, z; //顶点坐标DWORD color; //顶点颜色};// 定义 FVF 用到的数据项:坐标颜色#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)class CEx_D3DView : public CView{ … };

Page 34: 第 10 章 多媒体应用

10.3DirectX 编程(9)在 CEx_D3DView类定义一个用于顶点缓存区的的接口指针对象及构造三角形的函数 InitGe

ometry,代码:protected:LPDIRECT3D9 m_pD3D; // Direct3D 对象的接口指针LPDIRECT3DDEVICE9 m_pDevice; // 设备对象的接口指针LPDIRECT3DVERTEXBUFFER9 m_pVB; // 顶点缓存区的的接口指针void InitGeometry();(10) 在 CEx_D3DView::InitGeometry函数中添加代码:void CEx_D3DView::InitGeometry(){ // 构造三角形实体CUSTOMVERTEX vertices[] ={{ -0.6f, -0.6f, 0.0f, D3DCOLOR_XRGB(255,0,0) },{ 0.0f, 0.6f, 0.0f, D3DCOLOR_XRGB(0,255,0) },{ 0.6f, -0.6f, 0.0f, D3DCOLOR_XRGB(255, 255 ,0) }};// 创建顶点缓存区,并获取接口 IDirect3DVertexBuffer9的指针m_pDevice->CreateVertexBuffer(sizeof(vertices), //缓存区尺寸0, D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT, &m_pVB, NULL );void* pVertices;m_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 );memcpy( pVertices, vertices, sizeof(vertices) );m_pVB->Unlock();}

Page 35: 第 10 章 多媒体应用

10.3DirectX 编程(11) 在 CEx_D3DView::OnDestroy函数中添加下列代码:void CEx_D3DView::OnDestroy() { CView::OnDestroy();m_pVB->Release(); // 释放顶点缓存区m_pDevice->Release(); // 释放设备对象m_pD3D->Release(); // 释放 Direct3D 对象}(12) 在 CEx_D3DView::OnDraw函数中添加下列代码:void CEx_D3DView::OnDraw(CDC* pDC){ …m_pDevice->BeginScene();InitGeometry(); // 进行建模// 设置自定义的 FVFm_pDevice->SetFVF( D3DFVF_CUSTOMVERTEX );// 绑定顶点缓存区至设备数据源m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX) );// 绘制图元,其中参数 1 为图元格式,参数 3为三角形数目m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1);m_pDevice->EndScene();…}

Page 36: 第 10 章 多媒体应用

10.3DirectX 编程 (13) 编译并运行,如图。

(14) 显示出其颜色,要在 CEx_D3DView:: OnInitialUpdate函数中添加代码:void CEx_D3DView::OnInitialUpdate() { …// 因为使用顶点颜色渲染,所以要禁用光照处理m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );// 关闭“挑选”功能,允许渲染背面m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );}

(15) 再次编译并运行,如图。

Page 37: 第 10 章 多媒体应用

10.3DirectX 编程10.3.3 使用 DirectX 向导 [例 Ex_DirectX] 使用 DirectX 9应用程序向导来创建。

(1)选择“文件”“新建”菜单命令。单击“工程”标签,从列表框中选中项。(2) 在工程名称框中键入项目名称 Ex_DirectX。(3) 单击 [ 确定 ],如图。可以选择创建的窗口是单文档窗口还是 MFC 对话框窗口,以及对 DirectX 组件的支持等内容。 (4)去除 DirectInput 和 DirectMusic组件支持,单击 [下一个 ],如图。

Page 38: 第 10 章 多媒体应用

10.3DirectX 编程(5)选中“ Triangle(三角形 )” ,去除“ Direct3D fonts” 和“ 3D meshes”支持,单击 [ 完成 ]。单击 [ 确定 ] 系统将自动创建此应用程序框架代码。(6)编译并运行,如图。 (7) 将项目工作区窗口切换到 ClassView页面。需要说明的是,文件 Ex_DirectX.cpp 中的 WinMain 函数是程序的入口函数。