DirectDraw7学习笔记(3)---显示位图及相关概念

来源:互联网 发布:公务员备考计划知乎 编辑:程序博客网 时间:2024/05/16 15:08

如果有朋友直接拷贝或转载引用我的文章,我并不反对,也无须得到我的同意,但请在转载引用的时候注明作者.

作者:蒋志强

前言

由于工作学习的原因,学习笔记被耽搁了.以前我们梳理了一下基本概念,这次我总结归纳一下显示一幅位图图象的步骤及相关概念.

使用DDraw的基本概念

在DDraw里面有一个Surface页面的重要概念,可以暂时简单的把Surface理解为的绘画的纸张,DDraw的Surface可以分为主屏页面和离屏页面,主屏页面实际上就是显卡中当前显示器屏幕的显存区域,所有对主屏页面的操作将直接对显示器的显示内容产生影响,而离屏页面则是在显存或内存中的一块区域(不是当前屏幕显示内容的存储区域),所以对离屏页面的操作并不直接造成显示器屏幕的改变.离屏页面的操作对显示虽然不直接造成影响,但它也十分重要,我们先利用离屏页面把各种绘制操作在离屏页面上完成,然后再把离屏页面设置为主屏页面,就可以避免屏幕的闪烁.这和在GDI方式下,利用兼容DC的思想是完全一致的,只是DDraw方式有更高的效率.

具体操作步骤

1.我们首先要建立一个DirectDraw对象;

2.设置DirectDraw的控制级和显示模式;

3.创建主屏页面;

4.利用GDI将图片文件装入GDI内存兼容DC中;

5.创建主屏页面的兼容DC,将GDI兼容DC中的图片传送到主屏页面兼容DC中;

一些说明

在DirectX8的完整SDK包安装后,包括有几个很用的*.h头文件和*.cpp源文件,这几个文件是微软自带的演示工程中使用到的.虽然我们写DDraw的程序完全可以不需要他们,但是这些文件很好的将DDraw的接口包装成了很好的类,体现了面向对象编程和代码重用的思想,好好阅读他们(毕竟能在微软写代码的程序员的水平是相当不错的)以及理解微软的演示工程的程序结构,是一个非常好的进步捷径(特别是象我这种菜鸟可以获益良多).但是一开始就直接用这些类,会让我们不太清楚DDraw究竟具体是怎么工作和使用,所以,我先直接用DDraw来写,后面我们再把DDraw自己包装为类,以便使用.

使用到重要函数

创建一个DDraw对象的函数

HRESULT WINAPI DirectDrawCreate(
  GUID FAR *lpGUID,       
  LPDIRECTDRAW FAR *lplpDD
  IUnknown FAR *pUnkOuter 
);

或者

HRESULT WINAPI DirectDrawCreateEx(
  GUID FAR *lpGUID,       
  LPDIRECTDRAW FAR *lplpDD,  REFIID iid,  IUnknown FAR *pUnkOuter 
);
这个函数创建了一个DDraw对象(或者说COM对象),实际上它对应了你的机器中的一块显卡.这个函数是DDraw体系中极少的几个不属于任何接口的函数,其他的决大多数函数都是某个接口中的函数.因为在最开始的时候,盘古开天地什么都没有,当然也没有任何接口或对象,所以就不会有在任何接口中的函数可以调用.我们先来看看使用它的具体代码:

LPDIRECTDRAW7 lpDD;

HRESULT hr;

if(FAILED(hr = DirectDrawCreateEx( NULL, (VOID**)&lpDD, IID_IDirectDraw7, NULL ))

{

      MessageBox("创建DDraw对象失败!","错误");

      return;

}

LPDIRECTDRAW7是DDraw对象的指针,在DDraw中LP是Long Pointer的意思,HRESULT是windows头文件宏中定义,实际上就是一个Long类型(typedef LONG HRESULT),FAILED是一个用于根据HRESULT值判断函数是否成功执行的宏.DirectDrawCreate的第一个参数是用于标识创建哪块显卡对应的DDraw对象,通常情况下给它赋值null则标明使用系统默认显卡(因为通常情况下,机器只安装了一块显卡),第二个参数是指向指针的指针,所以在指针lpDD前还加了个取地址&符,最后面的一个参数现在必须为null,这个参数是为了以后DirectX COM组件扩展.DirectDrawCreateEx比DirectDrawCreate多一个参数,用于指定创建什么版本的DirectDraw对象,我们使用IID_IDirectDraw7表示创建DirectDraw7的版本,当然我们也可以指定创建早期的DirectDraw版本,比如IID_IDirectDraw4 (向下向兼容是COM的重要特征).

 有了DDraw  COM对象后,就可以使用这个对象的函数了.

HRESULT SetCooperativeLevel(
  HWND hWnd,    
  DWORD dwFlags 
);

HRESULT SetDisplayMode(
  DWORD dwWidth,
  DWORD dwHeight,
  DWORD dwBPP,
  DWORD dwRefreshRate,
  DWORD dwFlags
);

是DDraw对象的IDirectDraw7接口中方法,前者设置控制级,后者设置显示模式.我们还是来看代码,再来解释:

 hr = lpDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN );
 if( FAILED(hr) )
        return ;

if( FAILED( lpDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) )
 if( FAILED(hr) )
        return E_FAIL;

SetCooperativeLevel函数设置DDraw对象对程序显示系统的控制级别,第一个参数应用程序所使用的窗口的句柄,第二个参数指明控制级别DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN表明DDraw对象独占显示设备并且全屏显示,其它程序就不能显示了.DDSCL_EXCLUSIVE这种参数很显然也是宏(#define DDSCL_EXCLUSIVE                         0x00000010l),这个参数可以多个属性通过或运算符 | 组合在一起,表示同时具有这几个属性,具体有哪些参数可以选择,你应该去查看微软DirectX的文档.

SetDisplayMode函数是用于设置显示模式的,因为在设置显示系统的控制级别的时候,我们设置为独占模式(另外也可以设置为窗口模式,窗口模式因为要考虑到其他的应用程序的显示,所以要复杂些,以后我们再讨论),所以我们现在可以直接设置显示系统的显示模式,也就是设置分辨率,刷新率和色彩深度.分辨率,刷新率和色彩深度应该设置为显示系统可以支持的模式,否则设置会失败(如果你设置分辨率为100*100,刷新率为999Hz,色彩深度为128位,我几乎肯定你一定不会成功的),因为你不应该让你的显示系统干一些他干不了的事情(就好象你不应该派一个农民去挑战一个牛头人).比较可取的方式是将显示模式设置为大多数显示系统都支持的模式,比如640*480,800*600的分辨率,8位(256色),16位或32位的色彩深度,60Hz,75Hz的刷新率,要注意的是很多显示卡都不支持24位的色彩深度,我们应该避免将色彩深度设为24 位.当设置为32位以下的色彩深度的时候,我们的显示系统会使用到调色板,开始时为了让问题尽量简单些,我们暂时不考虑调色板,直接将色彩深度设置为最简单的32位(当然这样做的代价是消耗相对较多存储空间).SetDisplayMode函数的第一个参数是水平分辨率,第二个参数是竖直分辨率,第三个参数是色彩深度,第四个参数是刷新率,当刷新率参数为0的时候,将使用当前显示系统的刷新率,第五个参数是扩展参数,现在我们用不上它,可以直接使用0,表示不使用.

原创粉丝点击