DirectDraw的学习笔记

所需积分/C币:9 2013-03-07 11:39:19 288KB PDF
15
收藏 收藏
举报

DirectDrawDirectDrawDirectDrawDirectDraw的学习笔记的学习笔记的学习笔记的学习笔记 开始看Wince下面的DDraw编程了,在wince的对应目录下面有几个例子: 在使用 DirextDraw时,需要首先创建一个对象DirectDraw 的实体,该对象实体代表了微机显示适配器。然后,使用接口所提供的方法来操作该对象实体,使之完成有关命令和任务。
然后,你可以改变一下你的显示模式,这个是和你的底层驱动相关的,因为我们 的显示屏支持的格式很多,支持的分辨率也有很多,因而要选择一个显示模式, 当然你可以使用默认值,但是你也可以改变: IDirectDraw:: Setdisplaymode hRet=g pdd->SetdisplayMode(640, 480, 80, 0) 然后就是创建主表面和交换页了 / Create the primary surlace with one back buffer ZeroMemory &ddsd, sizeof(ddsd)) ddsd dwSize= sizeof(ddsd ddsd. dwFlags- DDSD CAPS DDSD BACKBUFFERCOUNT ddsd. ddsCaps. dwCaps= DDSCAPS PRIMARYSURFACE DDSCAPS FLIP DDSCAPS COMPLEX ddsd. dwbackBufferCount - =1 //这里我们设置的是只有一个缓存页面 这个参数是什么意思呢?首先设置 dwsize,这个成员主要是为了以后的扩展 然后就是一个 dwFlag,就是说这两个方面的变量我们是需要改变的,一个是CAPS 另一个是 BACKBUFFCOUNT,然后下面是具体的值,这里我们可以仔细的看一下 DDSCAPS PRIMARYSURFACE表示一个主表面: DDSCAPS FLIP表示一个交换页 DDSCAPS COMPLEX表示一个合成页。 最后,例子指定了一个后台缓冲后台缓冲就是实际的绘图操作先在那里完成,然 后,再快速的翻动(flip)到主平面( primary surface)上.在DDEx1中,后台缓冲的 数日是1.其实,你要你的显存允许,你想建几个就建几个.你想知道更多的关于 创建大于1块缓冲的信息,可以去看" triple buffering". 创建的"平面"占用的存储空间,可以是系统内存也可以是显存.如果应用程序使 用的空间超出了显存, DirectDraw就会使川系统内存.(例如你指定多块缓存在 个仅有1B显存的是配器上).你也可以这样设置 DDSCAPS结构的 deCaps成员, 设成 DDSCAPS VIDEOMEMEORY或 DDCAPS SYSTEMMEMORY以达到只用显存或只用内 存.(如指定用显存,而显存不够, DIrectdRaw7: Createsurface返回一个 DDERR OUTOFVIDEOMEMORY错误) 在填充完 DDSURFACEDESC2结构后,你就可以用他和gpDD指针 ( DirectDrawCreateex函数创建的 DirectDraw对象的指针)调用 DIrectdRaw7:: CreateSurface方法,就像下面 hRet=g pDD->CreateSurface(&ddsd, &g pDDSPrimary, NULL) if (hRet !=DD OK) //g pDDSPrimary points to the new surface else The surface was not created return False g pDDSPrimary参数将指向由 CreateSurface函数返回的主平面( primary surface)的地址,如果调用成功的话 指向主平面( primary surface)的指针有效后,就可以调用 IDirectDrawSurface7: GetAttachedSurface方法去得到一个指向缓冲的指. 如下: ZeroMemory( &ddscaps, sizeof (ddscaps)) ddscaps. dwCaps DDSCAPS BACKBUFFER hRet=g pDDSPrimary-GetAttachedSurface(&ddscaps, &g pDDSBack) if (hRet ! DD OK) //g pDDSBack points to the back buffer e⊥se return FALse 如果 DIrectdRaw Sur lace7: GeLAllachedSurr ace调用成功, g pDDSBack参数 将指向缓存区 在主平面( primary surface)和后台缓冲( back buffer)创建完成后,例子DDEx1 用 windows标准GDⅠ函数输出了一些文本在缓冲上.如下 (注意使用GDⅠ函数不一定就是GDI程序) if(g pDDSBack->GetDC( &hdc)=- DD OK) SetBkColor(hdc, RGB(0, 0, 255)) SetTextColor(hdc, RGB (255, 255, 0)) if(phase) GetClientRect(hWnd, &rc) GetTextExtentPoint(hdc, szMsg, strlen (szMsg), &size TextOut(hdc, (rc right-size cx)/2,(rc. bottom-size cy) szMsg, sizeor (szMsg)-1 TextOut(hdc, 0,0, szFrontMsg, Strlen(szfront Msg)) phase =0 e⊥se TextOut(hdc, 0, 0, szBackMsg, Istrlen(szBack Msg)) phase g pDDSBack->ReleaseDC(hdc 这个例子使用 the directDrawSurface7: GetA方法获得设备上下文的句柄, 并且,为了准备写入,将缓冲上锁.如果你不准备用需要设备上下文句柄的 windows函数,你可以使用 IDirectDrawSurface7:: Lock IDirectDrawSurface7: Unlock方法加解锁. 接下米, phase变量决定了应该输出到主缓存消息( primary buffer message)还 是后台缓存消息( back buffer message).如果 phase-1,输出 主缓存消息,且设 phase=0.如果 phase=0,输出后台缓存消息,且设 phase=1 当消息输出到缓存区后,用 dIrectυ rawSurface7:: Released方法将缓存区解 锁 对创建平面的内存上锁,是保证你的程序和系统不能同时对此内存进行存取.这 防止你写入"平面"内存事发生错误.另外,不对"平面"内存解锁,你的程序将无法 翻转平面. 平面被加锁之后,例子中用了标准 windowsGDI函数: SetBkco1or设置背景 色, Settextcolor设置在背景上显示的字的颜色,用 Textout在"表面"上输出文 字和背景色 当文字被输出到缓存之后,例子应用 DIrectdraw Sur race7:: Released方法解 锁"表面″并且释放句柄.不论在什么时候你的程序完成了对缓存的写入,一定要 调用 IDirectDrawSurface7: ReleaseDC EX IDirect Draw Surface7: Unlock之 具体用哪个,由你的程序而定.不解锁,你的程序将不能翻转平面. 注意:用 IDirectDraw Surface7: Unlock对″平面"解锁后,指向"平面"的指针将 会无效.你必须再用 IDirectDrawSur lace7::lock去获得一个有效的指针. 翻转平面 在DDEx1中, WM TIMER消息引发从缓存到主平面的翻转.当″平面"内存解锁后,你 就可以用 IDirectDrawSur race7:Flip方法实现从缓存到主平面的翻转.如下 case WM TIMer / Update and flip surfaces if (s bactive & TIMeR ID== wParam) UpdateFrame(hWnd while (true) hRet=g pDDSPrimary->Flip (Null, 0) break if (hRet = DDERR SURFACELOST) hRet=g pDDSPrimary->Restore o if (hRet!= DD OK) break if (hRet ! DDERR WASSTILLDRAWING break break 在例子中, g pDDSPrimary参数指示主平面和与他连接的缓存.当 IDirectDrawSurface7::門lip被调用,前后平面将会交换(只是交换指针,没有实 际的数据交换).如果翻转成功,讴回D0K,跳出循环. 如果翻转返回的是 DDERR SURFACELOST值,就试图用 IDirectDrawSurface7:: Restore方法保存平面.如果保存成功,程序循环到调用 IDirectDrawSurface7:Flip,再试一次.如果保存不成功,程序跳出循环,返回- 个错误 注意:当你调用 IDirectDrawSurface7::Flip时,翻转动作并不能马上完成.如 果,前一个翻转动作还没有完成, IDirectDrawSurface7:F1ip会返回 DDER_ WASSTILLDRAWING.在这个例子中, IDirectDrawSurface7::Flip会一直调 用直到返回DD0K 所以说这个 while循环很必要,因为这个Flip是一个非阻寒的函数,调用就会 返回,一直调用到成功为止。 当你按下F12键时,例子DDEx1将在退出程序前处理 WM DESTROY消息.这个消息 将调用 Releaseallob jects函数,这个函数包括了多个 Release调用.像下面样: static void ReleaseAllObjecls(void) if (g pDD! NULL) if (g pDDSPrimary !=NULL) g pDDSPrimary->Release( g pDDSPrimary NUll g pDD->Release( y pDD= NULL 这个程序检测 DirectDraw对象的指针gpDD和 DirectDraw平面对象的指针 g pDDSPrimary是否为NLL.然后,调用 IDirectDrawSurface7: Release方法令 DirectDraw平面对象的 reference count(可以认为是创建的对象的数目)数减 I,这使得 reference count减为0, DirectDraw平面对象就释放了.然后,还需将 他的指针值设为MLL.接下来,程序调用 DIrectdraw7:: Release,同样是令 Directdraw的 reference count减1,然后然后.全销毁 DirectDraw的学习笔记(3) 成简单的动画 以上我们己经讨论过的所有的例程,都简要描述∫如何在台缓冲区绘画,以及如何把后台缓 冲区弹出到主表面 的简单的实现方法。然而,这些例稈都是以极其缓慢的速度在运 行。下边的例程, 和 以实时运行它们的函数,更象一个实际的程序。 显示了如何为表面 设冒一个颜色码,并且演示了如何使用 方法将隐屏表面 的某些部分复制到后台缓冲区来生成动画。 显示了如何检察 的返回值,并得知按位隔行拷贝是否成 功 扩展了 的功能。它能在动画运行过程中,通过读调色板,来修正调色板。 颜色码和位图动画 的例程显示了一种将位图载入一个隐屏缓冲区的比较原始的形式。下边的 的例程,使用我前边凵经描述过的技术,将一个背景和一系列的 载入一个隐屏表面 。使用 方法,将隐屏表面 的部分复制到后台缓 冲区,这样,就生成了简单的位图动画。 是被 使用的位图文件,它包括了背景和六十张动画片,并在黑色的背景下 有一个旋转的红色的 的例程包含了了几个新的函数,它们可以为循环的 设置颜色码,然后把适当的 从隐屏表面 中复制到后台缓冲区中。 我很想指出,在 中 被看作为一个 。每当我听见的复数的 我就禁不住想起年轻的好莱坞女影星,因此,在这里,我把它们叫做 。我希望读者 不要介意 设置颜色码 除了在前边的例程中, 函数中所用到的功能外, 例程还包含有为 设置 颜色码的代码。颜色码是用来设置颜色值的,而且后者具有透明性。当使用一个硬件按位 隔行拷贝器时,除了被设置为颜色码的值外,一个长方形的所有的象素都被按位隔行拷贝了 这样在一个表血 上就生成了非长方形的象素。在 中设置颜色码的代码如 这一例程显小」设置颜色码的两种不同的方法ε第一种方法,也即程序的前三行,把包含在 结构中的颜色码范围设置成进制数或十进制数之后调用 方法把颜色码设置为黑色码。当然,这样做的前提是假定 色在颜色码表中的索引入口是,要完成这项简单的工作,你可调用 米改变相应的数据。 如果你的位图没有将入口设置为黑色会怎么样呢你也可以通过在调用 函数中设置你需要的颜色的值方法选择颜色黑色的值为(,,) 文件中函数 调用该文件中的另·个函数 数存储了象素的当前颜色值,该象素要位于 表面 的位图的(,)位置 上,之后取出你已经提供的值,并在(,)位置设置该象素的颜色。该函数然后用 每象素的位数来屏蔽颜色值ε一旦这样做了之后,原来的颜色就被放回到(,)位置, 并且,该调用将实际的颜色码值返冋给 。当上诉过程完成之后,颜色码值就 被放在结构 的 成员之中。同吋,该码值也被复制 成员中。然后,再调用 设置颜 色码。 你可能经注意到了位于 和 中的 参数。在 的 调用中,如果该参数的值被你传递作为颜色码,那么位图左上角 的象素就将被用作颜色码 位图的传送并不意味什么,因为,在(,)位的象素 的颜色是一个灰色的阴影。然而,你若想看见如何将(,)位的象素用作 例程中 的颜色码的话,你可以通过将位图文件 载入你的绘画应用程序中,然后,将( )位的象素改变为黑色来完成上述功能ε切记:必须将此改变存盘。然后改变 的程序代码行 来调用 重新编辑 例程,要保证资源定义文件也被重新编辑过,以便将新的位图被包括进去。 为了保证资源定义文件被重新编辑,你需要对 文件进行适当的删补工作,以使资 源定义文件编辑的进行有足够的空间。此时, 例程将把(,)位的象素用作颜色 码 中的动画 例程使用 函数米生成一个简单动画其使用包含在 文件的红色 中。动画由位于一个三角形内的三个红色 组成。这个例程将 的 和毫秒的数日相比较,这是因为对 的最后定义决定了是否重新 绘制任何,然后再使用方法 。首先,把背景从隐屏表面 按位隔行拷贝到缓冲区中,然后将 按位隔行拷贝后台缓冲区使用先前你已 经设置好的颜色码来决定哪些象素是透明的。在 被按位隔行拷贝到后台缓冲区后, 将调用方法 以弹出后台缓冲区和主衣面 注意:当 被用来从隐屏表面 按位隔行拷贝到背景时,传 值参数 的参数值就被设置为 。这就表明一个正常的 按位隔行拷贝将在没有透明位的情形卜发生。之后,当红色被按位隔行拷贝到后台 缓冲区, 参数的值就被设置为 在这个例程中,整个背景每次都将通过调用 函数重新绘制次。优化这例程 的一种方法是:仅将改变当前循环的红色 背景的部分再重新画一遍。因为组成 的长方形的位置和大小始终不变。因此,你就可以很容易地利用这种优化方法去修正 例程 动态修正调色板 例程 是在例程 的基础上进行了适当的修正而得到的,该例程演示了当个 应用程序在其运行过程中,如何动态地改变调色板的人口方式。尽管这样或许并没有在程序 中被普遍地应用,但 例程将给你一个于工操纵 谓色板的尝试 以下的一段程序代码摘自例程 ,它是利用文件 卜半部分(这部分包含了 系列红色的 的值来调用调色板进入方式。 程序中, 数组变量是一个被用在文件 下半部分的调色板色彩索引指针。 在使用他以前,所有的 数组变量都将被置为零。然后,隐屏缓冲区将被锁定, 以准备决定是否有某个色彩索引值被用户使用。 数组变量被置于从行、列开始的位图中。数组中的色彩索引值将由位图衣 面 所占用的内存中的数据字节决定。数据在内存中的位置由结构 中的成员 决定,它指向了位图 中行、列在内 存中的相关位置。然后,该指针所指向的特定的色彩索引值将被置为。行数变量的值将 随结构 的成员的值的变化而变化,以获得该象素在线性内存中 的实际位置。 置于数组变量 中的色彩索引值在以后将被用来决定究竞哪种色彩将在调色板中 循环。由于没有通用的色彩用在背景和红色的 之间,所以,只有那些与红色的 相关的色彩将在调色板中循环。如果你想要检查它们的真假,只需从数组变量中移去成员 即可。然后,你需要重新编译、运行该程序,这样你就将见到所期望的结果。(如果 没有乘上 ,那么红色的 将不可能达到。仅仅只能看到背景中的色彩被索引 然后循环) 常规显存宽度和护展内存宽度的关系 在我们继续谈论调色板循环以前,我想暂吋离开我们原来的话题·会儿,来谈谈显存宽度和 扩展宽度之间的关系。 如果你的应用稈序是为显存而编写的,那么扩展宽度就需要被赋予不同于显存宽度的值。因 为并不是所有的显存都被安排在同个线性块中。例如:在内存块中显存的扩展宽度将包括 位图的显存宽度加上高速缓存的一部分。下图2说明」在内存块中显存宽度和扩展宽度。 图矩形内存常规内存和扩展内参的关系 说明:在上图中,前置缓冲区和后台缓冲区都是 位,而高速缓冲区均为 位。为了获得写入缓冲区的下地址,你需要使用字节的显存以及字节(即) 的存储空间,这正是下一行的开始。 殷说米,当我们直接进入表面 所占内存空间时,总是利用方法 来返回显存扩展宽度的大小(或者,也可以通过方法 实现)。请不要怀疑扩展宽度单单是建立在显示模式的基础上的。 如果你的应用程序是工作在显示适配器上的,然而却看上去和其它的混淆不清,这可能是 你自己的原因造成的。 调色板的循环 数 在例程 中的工作方式与其在例程 中的工作方式相同。它 首先将背景按位隔行拷贝进后台缓冲区,然后将三个 按位隔行拷贝进前景中。尽管 在它表面 弹出衣面 集以前,函数 生成了调色板索引,而函数 正是通过它改变了调色板的主表面 。以上的功能由如下的一段程序代 码实现:

...展开详情
试读 18P DirectDraw的学习笔记
立即下载 低至0.43元/次 身份认证VIP会员低至7折
一个资源只可评论一次,评论内容不能少于5个字
您会向同学/朋友/同事推荐我们的CSDN下载吗?
谢谢参与!您的真实评价是我们改进的动力~
  • 领英

  • GitHub

  • 脉脉勋章

  • 签到王者

  • 技术圈认证(专家版)

关注 私信
上传资源赚钱or赚积分
最新推荐
DirectDraw的学习笔记 9积分/C币 立即下载
1/18
DirectDraw的学习笔记第1页
DirectDraw的学习笔记第2页
DirectDraw的学习笔记第3页
DirectDraw的学习笔记第4页

试读结束, 可继续读2页

9积分/C币 立即下载