📄 chapter5.txt
字号:
●GetOverlayPosition()
●SetOverlayPosition()
●UpdateOverlay()
●UpdateOverlayDisplay()
●UpdateOverlayZOrder()
GetOverlayPosition()和SetOverlayPosition()函数用于控制重叠的位置。UpdateOverlay()函数用于更新大量的重叠设置,包括重叠是否可见,以及重叠是以色彩键码还是用alpha混合到背景表面上。
UpdateOverlayDisplay()函数用于更新显示设置。该函数用于更新整个重叠显示,或者只更新由AddOverlayDirtyRect()函数指定的矩形重叠部分。EnumOverlayZOrders()函数可根据重叠的Z值(Z值控制哪一个重叠位于最上面)重复重叠。重叠可按从前到后或从后到前的顺序枚举。
13. 剪裁器函数
DirectDraw支持的剪裁是将DirectDrawClipper接口(该接口我们尚未讨论)的一个实例连接到表面。一旦连接完毕,剪裁器对象就会有规律地blt到表面。剪裁器/表面的连接由以下两个DirectDrawSurface函数控制:
●GetClipper()
●SetClipper()
SetClipper()函数用来将剪裁器对象连接到表面。GetClipper()函数用于向前一个连接的剪裁器对象返回一个指针。SetClipper()函数还可用于解除表面同剪裁器的连接,具体的做法是通过指定NULL来替代DirctDrawClipper接口指针。
14。 调色板函数
像剪裁器一样,调色板也可连接到表面。DirctDrawSurface接口为此提供以下两个函数:
●GetPalette()
●SetPalette()
SetPalette()函数用来将DirctDrawPalette接口(该接口我们接下来就要讨论)的一个实例连接到表面。GetPalette()函数用于检索前一个连接调色板的指针。
调色板可被连接到任何表面,但只有连接到主表面时,调色板才起作用。当与主表面连接时,调色板决定显示硬件调色板的设置。
第六节 DirectDrawPlette接口函数
DirctDraw提供DirctDrawPalette接口用于调色板显示模式和表面。尽管Windows支持几种低于8位像素深度的显示模式,但DirctDraw所支持的唯一的调色板显示模式是8位模式。
DirctDrawPalette接口实例由DirctDraw CreatePalette()函数创建。CreatePalette()函数用大量的标志来定义调色板属性。
DirctDrawPalette接口只提供以下3个函数:
●GetCaps()
●GetEntries()
●SetEntries()
GetCaps()函数用于检索有关调色板的信息,包括调色板项目数量,调色板是否支持同步垂直刷新,以及在8位调色板状态下是否所有的256个调色板项目都能被设定。
SetEntries()函数允许在程序中设置调色板的色彩值。该数据从文件中读取。而这些项目在运行过程中可被计算和设定。GetEntries()函数用于检索先前设定的调色板项目。
DirctDrawPalette()接口实例可利用DirctDrawSurface SetPalette()函数连接到表面。将不同调色板连接到主表面或利用SetEntries()函数改变调色板项目都可激活调色板。
第七节 DirectDrawClipper接口函数
DirctDrawClipper接口支持剪裁。将剪裁器对象连接到表面并在blt操作中将其当作目标表面就可以进行剪裁。
directDrawClipper实例由DirectDraw CreateClipper()函数创建。DirectDrawClipper接口支持以下5个函数:
●SetHWnd()
●GetHWnd()
●IsClipListChanged()
●SetClipList()
●GetClipList()
剪裁器对象一般用于出现在窗口中的DirctDraw应用程序必需的剪裁。要求剪裁器必须确保在blt操作过程中考虑到桌面上其他的窗口。比如,当应用程序的全部或一部分被另一个窗口遮蔽,剪裁就必须确保被遮蔽的窗口不被DirctDraw应用程序破坏。
桌面剪裁由SetWnd()函数完成。SetHWnd()函数将剪裁器对象连接到一个窗口句柄。这样就初始化了Windows和剪裁器对象之间的通讯。当桌面上的任何一个窗口发生变化时,剪裁器对象就会得到通知,并作出反应。GetHWnd()函数用于决定剪裁器同哪一个窗口句柄连接。IsClipListChanged()函数用于决定内部剪裁清单是否因桌面的改变而被更新。
SetClipList()和GetClipList()函数为DirectDrawClipper接口提供便利的定制使用。SetClipList()函数用于定义一些矩形区域,这些矩形区域用来定义blt操作的合法区域。GetClipList()函数用于检索剪裁器的内部剪裁数据。
一旦被连接到表面,Blt(),BltBatch()以及UpdateOverlay()函数所进行的blt操作将根据DirctDrawCliper接口中包含的数据被自动地剪裁。注意,Blt Fast()函数在此被忽略。BltFast()函数不支持剪裁。
第八节 附加DirectDraw接口
DirctDraw还提供了另外个我们没有讨论的接口,它们是:
●DDVideoPortContainer
●DirectDrawColorControl
●DirectDrawVideoport
这些接口由DirectX5介绍,它们提供低水平视频端口控制。这些接口还向DirctDraw表面提供流活动视频的方法。尽管利用这些接口可以为DirctDraw应用程序增加视频支持,但除非高水平视频APIs不能满足需要,否则最好不用这一方法。
第九节 DirectDraw结构
我们已讨论过DirctDraw接口及其成员函数了,接下来再看看DirctDraw定义的结构。DirctDraw总共定义了8全结构:
●DDBLTFX
●DDCAPS
●DDOVERLAYFX
●DDPIXELFORMAT
●DDSURFACEDESC
●DDSCAPS
●DDBLTBATCH
●DDCOLORKEY
我们已经见过其中的一些结构了,比如在讨论DirctDrawSurface SetColorKey()函数时我们就接触过DDCOLORKEY结构。在此,我们不详细讨论每一个结构的细节,但必须指出,DirctDraw quirk被忘记时会导致失败。
以上所列结构中的前5个有一个称作dwSize的字段。该字段用于存储结构的大小,设定该字段的工作由你来做。另外,该字段如果没有被正确设定的话,那么任何一个将这5个结构作为变量的DirctDraw函数都会失效。
以DDSURFACEDESC结构为例,使用结构的代码如下:
DDSURFACEDESC surfdesc;
surfdesc.dwSize=sizeof(surfdesc);
surf->GetSurfaceDesc(&surfdesc);
首先声明结构,然后用sizeof()关键字设定dwSize字段。最后结构传递给DirctDrawSurface GetSurfaceDesc()函数。忘记设定dwSize字段将导致这段代码失效。
到底为什么DirctDraw坚持要求给出它所定义的结构的大小?原因在于这5个包含dwSize字段的结构将来有可能会改变。DirctDraw会检查结构的大小,以便确定正在使用的版本。DirctDraw坚持要求给出一个有效的大小值,是为了让开发者提供有效的结构大小。这样做是有好处的,因为DirctDraw的新版本可以正确运用旧版本的DirctDraw程序。
在使用结构之前,最好将结构初始化为零。这样,前面的代码就变成:
DDSURFACEDESC surfdesc;
ZeroMemory (&surfdesc,sizeof(surfdesc));
surfdesc.dwSize=sizeof(surfdesc);
surf->GetSurfaceDesc(&surfdesc);
ZeroMemory()函数是一个Win32函数,它将作为第一个参数的存储器设定为零.ZeroMemory()函数的第二个参数表明有多少存储器应被初始化。这一做法的好处是,通过GetSurfaceDesc()函数调用可以知道结构的哪些字段被更新了。如果没有对结构进行初始化,就有可能将结构字段中不可预测的值当作DirectDraw的设定值。
第十节 窗口应用程序
DirctDraw应用程序主要有两种型式:窗口的和全屏的。窗口DirctDraw应用程序看起来就像一个常规的Windows程序。我们很快将讨论到全屏应用程序。
窗口应用程序包括窗口边界、标题框以及菜单,这些都是传统的Windows应用程序中常见的部分。由于窗口应用程序同其他窗口一起出现在桌面上,因此它们被迫使用Windows当前所使用的分辨率和比特深度。
窗口程序有一个主表面,但只在进行真实页面翻转时才显现。而且,主表面并不代表窗口的客户区域(该区域在窗口边界内)。主表面还代表整个桌面。这就是说,你的程序必须追踪窗口的位置和大小,以便在窗口内正确显示可见的输出。换言之,利用窗口化的应用程序中可以在整个桌面上进行绘图。
如果不允许页面翻转,那么图像就必须从离屏缓冲区blt到主表面上。这就增加了图像撕裂的可能性,因为blt比页面翻转速度慢。为了避免图像撕裂,blt操作可以与监视的刷新率保持同步。
如果与窗口客户区域同样大小的离屏缓冲区被创建到显示RAM中,窗口应用程序就可以很好地运行。这样,窗口的内容可利用离屏表面合成。然后离屏表面可以通过硬件加速很快地到主表面上。
由于显示存储器的缺乏而不得不将离屏缓冲区创建到系统RAM中时,会严重影响性能。不幸的是,这种情况常常发生,尤其是在只有2MB显示卡的时候,这是因为人们总希望为自己Windows的桌面设置高分辨的显示模式。例如,采用1024×768×16显示模式的主表面自己就要占用2MB的RAM。在一个2MB显示卡上,几乎没有显示RAM留给离屏表面。
窗口应用程序的另一个问题是剪裁。一个性能良好的应用程序必须有一个连接到主表面的剪裁对象。这是有损性能的,原因在于为了检查剪裁器的剪裁清单内容,blt操作只能在一个小的矩形部分内进行。而且,不能使用优化的BltFast()函数。Bltting必须用较慢的,(而且更笨重的)Blt()函数。
最后要讲的是,窗口应用程序不允许全调色板控制。由于Windows保留了20个调色板项,所以在256种颜色只有236种颜色可被设定。被Windows保留的颜色只用系统调色板的前10个项和后10个项。因此在给图像上色时,只能使用中间236个调色板项。
第十一节全屏应用程序
包含对显示设备进行专有存取的DirctDraw应用程序就是全屏应用程序。这种应用程序可以任意选取显示卡所支持的显示模式,并享有全调色板控制。另外,全屏应用程序还可进行页面翻转。因此同窗口应用程序相比,全屏应用程序速度更快,灵活性更好。
典型的全屏应用程序首先检查所支持的显示模式,并激活其中一个。然后创建具有一个或更多后备缓冲区的可翻转主表面,剩下的显示RAM用于创建离屏表面。当显示RAM耗尽时,就启用系统RAM。屏幕被在后备缓冲区中合成的第一个场景更新,然后进行页面翻转。即使主表面占用了所有的可用的显示RAM,全屏应用程序还可输出执行其窗口化的副本,这是因为全屏应用程序可进行真实页面翻转。
由于全屏应用程序不一定非得使用Windows的当前显示模式,所以显示RAM的可用与否不存在多少问题。如果只检测到2MB的显示RAM,就可使用低分辨率显示模式来保留内存。如果检测到4MB的显示RAM,应用程序就可使用要求的显示模式并仍有保持良好性能。
全调色板控制也是个有利因素。这样可以使用所有256个调色板项而无需根据Windows保留的20中颜色重新分配位图。
第十二节混合应用程序
混合应用程序既可以在全屏方式下运行也可在窗口方式下运行。混合应用程序内部非常复杂,但却可以提供良好的性能。用户可在窗口方式下运行,如果太慢,则可切换到全屏方式下运行。
编写混合应用程序最好的方法是编写一个定制库,该库包括那些与应用程序使用全屏方式还是窗口方式无关的函数。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -